() => {
  it('should be able to render an input', () => {
    const { getByPlaceholderText } = render(
      <Input name="email" placeholder="E-mail" />,
    );

    expect(getByPlaceholderText('E-mail')).toBeTruthy();
  });

  it('should render highlight on input focus', async () => {
    const { getByPlaceholderText, getByTestId } = render(
      <Input name="email" placeholder="E-mail" />,
    );

    const inputElement = getByPlaceholderText('E-mail');
    const containerElement = getByTestId('input-container');

    fireEvent.focus(inputElement);

    await waitFor(() => {
      expect(containerElement).toHaveStyle('border-color: #ff9000;');
      expect(containerElement).toHaveStyle('color: #ff9000;');
    });

    fireEvent.blur(inputElement);

    await waitFor(() => {
      expect(containerElement).not.toHaveStyle('border-color: #ff9000;');
      expect(containerElement).not.toHaveStyle('color: #ff9000;');
    });
  });

  it('should keep input border highlight when input filled', async () => {
    const { getByPlaceholderText, getByTestId } = render(
      <Input name="email" placeholder="E-mail" />,
    );

    const inputElement = getByPlaceholderText('E-mail');
    const containerElement = getByTestId('input-container');

    fireEvent.change(inputElement, {
      target: { value: 'johndoe@example.com.br' },
    });

    fireEvent.blur(inputElement);

    await waitFor(() => {
      expect(containerElement).toHaveStyle('color: #ff9000;');
    });
  });
}


() => {
    const { getByPlaceholderText } = render(
      <Input name="email" placeholder="E-mail" />,
    );

    expect(getByPlaceholderText('E-mail')).toBeTruthy();
  }


async () => {
    const { getByPlaceholderText, getByTestId } = render(
      <Input name="email" placeholder="E-mail" />,
    );

    const inputElement = getByPlaceholderText('E-mail');
    const containerElement = getByTestId('input-container');

    fireEvent.focus(inputElement);

    await waitFor(() => {
      expect(containerElement).toHaveStyle('border-color: #ff9000;');
      expect(containerElement).toHaveStyle('color: #ff9000;');
    });

    fireEvent.blur(inputElement);

    await waitFor(() => {
      expect(containerElement).not.toHaveStyle('border-color: #ff9000;');
      expect(containerElement).not.toHaveStyle('color: #ff9000;');
    });
  }


() => {
      expect(containerElement).toHaveStyle('border-color: #ff9000;');
      expect(containerElement).toHaveStyle('color: #ff9000;');
    }


() => {
      expect(containerElement).not.toHaveStyle('border-color: #ff9000;');
      expect(containerElement).not.toHaveStyle('color: #ff9000;');
    }


async () => {
    const { getByPlaceholderText, getByTestId } = render(
      <Input name="email" placeholder="E-mail" />,
    );

    const inputElement = getByPlaceholderText('E-mail');
    const containerElement = getByTestId('input-container');

    fireEvent.change(inputElement, {
      target: { value: 'johndoe@example.com.br' },
    });

    fireEvent.blur(inputElement);

    await waitFor(() => {
      expect(containerElement).toHaveStyle('color: #ff9000;');
    });
  }


() => {
      expect(containerElement).toHaveStyle('color: #ff9000;');
    }


useField() {
      return {
        fieldName: 'email',
        defaultValue: '',
        error: '',
        registerField: jest.fn(),
      };
    }


async (req: Request, res: Response): Promise<void> => {
    const { filename, width, height } = req.query;
    // widht _ height _ filname
    const urlEnd: string =
      pahtEnd + 'w:' + width + '_' + 'h:' + height + '_' + filename + '.jpg';
    const urlStart: string = pahtStart + filename + '/img.jpg';

    // eslint-disable-next-line no-console
    console.log('----> processing image: ' + urlEnd);

    const heightNumber = Number(height);
    const widthNumber = Number(width);

    // factor out the image processing
    const img = await imageProcessing(
      urlStart,
      urlEnd,
      widthNumber,
      heightNumber
    );
    if (img) {
      res.writeHead(200, { 'content-type': 'image/jpg' });
      fs.createReadStream(urlEnd).pipe(res);
    } else {
      res.status(400).send('wrong syntax ');
    }
  }


({ open, error = false }: any) => (
  <div>
    {open !== undefined || error !== undefined ? (
      <Backdrop open={open}>
        {open ? <CircularProgress size={60} color="primary" /> : null


open ? <CircularProgress size={60} color="primary"


() => UserEntity


export class AccountEntity {
  id: string;
  name: string;
  amount: number
  currency: string
  hexColor: string
  createdAt: Date;
  updatedAt: Date;

  @Type(() => UserEntity)
  users: UserEntity[] = [];

  @Type(() => UserEntity)
  createdBy: UserEntity;

  @Exclude()
  UserAccount: any;

  constructor(partial: Partial<AccountEntity>) {
    Object.assign(this, partial);
  }
}


({
  id,
  className,
  label,
  checkedText = "Yes",
  uncheckedText = "No",
  ...props
}: TogglePropsType) => (

    {label} <input id={id} type="checkbox" {...props} />
    <label htmlFor


type TogglePropsType = {
  id: string
  className?: string
  label: string
  checkedText?: string
  uncheckedText?: string
}


cx("toggle", className)


export function isNr(n: any) { return typeof n === 'number' && !isNaN(n); }


export function toDMS(coordinate: number, posCardinal: string, negCardinal: string) {
  const absolute = Math.abs(coordinate);
  const degrees = Math.floor(absolute);
  const minutesNotTruncated = (absolute - degrees) * 60;
  const minutes = Math.floor(minutesNotTruncated);
  const seconds = Math.floor((minutesNotTruncated - minutes) * 60);
  const cardinal = coordinate >= 0 ? posCardinal : negCardinal;
  return `${degrees}°${minutes}'${seconds}"${cardinal}`
}


function latLng(latitude: number, longitude: number) {
  return [Math.round(latitude * 100000)/100000, Math.round(longitude * 100000)/100000]
}


function toMeter(v: number, units = 'm', delimiter = ',') {
  const toM = {cm:v*100, feet:v/3.281, inches:v/39.37, km:v/1000, miles:v*1609, m:v*1};
  if (units === 'm') {
    return `${delimiter}${v}`
  } else if (toM.hasOwnProperty(units)) {
    return `${delimiter}${toM[(units as keyof typeof toM)]}`
  }
  return ''
}


export function latLngStr(
	{latitude, longitude, altitude, units, accuracy, radius}: Partial<AsObjectNormalized>,
	onlyCoordinates = false
) {
	if (typeof latitude !== 'number' || typeof longitude !== 'number') { return '' }
	const [lat, lng] = latLng(latitude, longitude);
	if (onlyCoordinates) { return `${lat}, ${lng}` }
	const alt = typeof altitude !== 'number' ? '' : ` ⬍${altitude}${units||'m'}`;
	const rad = !radius ? '' : ` ⌀${radius}${units||'m'}`;
	return `${toDMS(lat,'N','S')} ${toDMS(lng,'E','W')}${alt}${rad}`
}


export function geoHref(
	{latitude, longitude, altitude, units, accuracy, radius, name = []}: Partial<AsObjectNormalized>
) {
  if (!Array.isArray(name)) { name = [`${name}`] }
  if (typeof latitude !== 'number' || typeof longitude !== 'number') {
    return {
      href: `geo:0,0?q=${name.join(',')}`,
      content: name.join(',')
    }
  }
	const [lat, lng] = latLng(latitude, longitude);
	const hrefs = [`geo:${lat},${lng}`];
  if (typeof altitude === 'number') { hrefs.push(toMeter(altitude, units)) }
  if (typeof radius === 'number') { hrefs.push(toMeter(radius, units, ';u=')) }
  const href = hrefs.join('');

  const alti = typeof altitude !== 'number' ? '' : ` ⬍${altitude}${units||'m'}`;
  const radi = !radius ? '' : ` ⌀${radius}${units||'m'}`;
  const content = <virtual>
    {toDMS(lat,'N','S')}

    {toDMS(lng,'E','W')}
    {!!alti && {alti}}
    {!!radi && {radi}}
  </virtual>;
  return { href, content }
}

export function apToGeoJSON(ap: AsObjectNormalized, messages: any = {}) {

	/* TODO
	Travel -> `target` can be the location …

	*/

	const [seen, results, features] = [new Set<string>(), new Set<string>(), []];
	const jp = (new JSONpointer(ap));
	jp.walk((value: any, pointer: string) => {
		/* make sure, pointer is unique and has at least both, longitude and latitude for GeoJSON */
		const matches = pointer.match(/(longitude|latitude)$/g);
		if (matches && !!matches.length) {
			const repl: any = {longitude: 'latitude', latitude: 'longitude'};
			seen.add(pointer);
			if (seen.has(pointer.replace(new RegExp(matches[0]+'$'), repl[matches[0]]))) {
				results.add(pointer.split('/location')[0])
			}
		}
	});
	/* build features from JSON pointers */
	/* TODO i18n */
	results.forEach((pointer) => {
		const {id = '', type: mainTypes = ['Object'], location} = jp.get(pointer);
    if (!location) { return }
		/* feature per location */
		location.forEach(({
			longitude, latitude, altitude, units, accuracy, radius,
			id: locationId, type: locationType = 'Place', name: n = '', summary: s = ''
		}: any) => {
			if (longitude && latitude) {
				if (Array.isArray(locationType)) { locationType = locationType[0] }
				const location = JSON.stringify({ longitude, latitude, altitude, units, accuracy, radius });
				const latLng = latLngStr({longitude, latitude, altitude, units, accuracy, radius});
				const name = !!n.length ? n.join(' – ') : '';
				const summary = !!s.length ? s.join(' – ') : '';

        const {location: _location = 'location', _of = 'of', _in = 'in'} = messages;
				const geoMeta = !pointer ? mainTypes.join(',') : pointer.split('/').reverse().reduce((s,p,i,a) => {
				  const nr = parseInt(p,10);
				  if (typeof nr === 'number' && !isNaN(nr)) {
            const type = messages.hasOwnProperty(a[i+1]) ? messages[a[i+1]] : a[i+1];
				  	const res = `${s}${type} ${nr+1} ${_in} `;
				  	a[i+1] = '';
				    return res
				  }
				  return s + p
				}, `${_location} ${_of} `).replace(/in $/g, '');

				/* and feature per type */
				mainTypes.forEach((apType: string) => {
					(features as any[]).push({
						type: "Feature",
						geometry: {
							type: "Point",
							coordinates: [longitude, latitude]
						},
						properties: {apType, pointer, id, locationId, locationType, location, name, summary, latLng, geoMeta}
					})
				})
			}
		});
	});
	return {type: "FeatureCollection", features: features.reverse()}
}

export function lngLatFromO(o: any): LngLatArray {
	let a: LngLatArray = [0, 0];
	if (isNr(o.latitude) && isNr(o.longitude)) {
		const alt = typeof o.altitude === 'number' && !isNaN(o.altitude) && o.altitude;
		a = !!alt ? [o.longitude, o.latitude, alt] : [o.longitude, o.latitude];
	} else if (isNr(o.lat)) {
		const lon = isNr(o.lon) ? o.lon : isNr(o.lng) ? o.lng : null;
		if (!isNr(lon)) {
			return a;
		}
		const alt = isNr(o.alt) && o.alt;
		a = !!alt ? [lon, o.lat, alt] : [lon, o.lat];
	}
	return a;
}
export function radiusFromO({radius, units = "m"}: any): RadiusO {
	if (!radius || !isNr(radius)) { return {} }
	radius = (units === 'cm') ? (radius / 100) : ((units === 'inches') ? (radius / 12) : radius);
	const conversionUnits: any = { cm: 'meters', inches: 'feet', m: 'meters', km: 'kilometers' }
	const radiusUnit: ("feet"|"kilometers"|"meters"|"miles"|"nautical-miles"|"yards") =
		conversionUnits.hasOwnProperty(units) ? conversionUnits[units] : units;
	return {radius, radiusUnit}
}


export function apToGeoJSON(ap: AsObjectNormalized, messages: any = {}) {

	/* TODO
	Travel -> `target` can be the location …

	*/

	const [seen, results, features] = [new Set<string>(), new Set<string>(), []];
	const jp = (new JSONpointer(ap));
	jp.walk((value: any, pointer: string) => {
		/* make sure, pointer is unique and has at least both, longitude and latitude for GeoJSON */
		const matches = pointer.match(/(longitude|latitude)$/g);
		if (matches && !!matches.length) {
			const repl: any = {longitude: 'latitude', latitude: 'longitude'};
			seen.add(pointer);
			if (seen.has(pointer.replace(new RegExp(matches[0]+'$'), repl[matches[0]]))) {
				results.add(pointer.split('/location')[0])
			}
		}
	});
	/* build features from JSON pointers */
	/* TODO i18n */
	results.forEach((pointer) => {
		const {id = '', type: mainTypes = ['Object'], location} = jp.get(pointer);
    if (!location) { return }
		/* feature per location */
		location.forEach(({
			longitude, latitude, altitude, units, accuracy, radius,
			id: locationId, type: locationType = 'Place', name: n = '', summary: s = ''
		}: any) => {
			if (longitude && latitude) {
				if (Array.isArray(locationType)) { locationType = locationType[0] }
				const location = JSON.stringify({ longitude, latitude, altitude, units, accuracy, radius });
				const latLng = latLngStr({longitude, latitude, altitude, units, accuracy, radius});
				const name = !!n.length ? n.join(' – ') : '';
				const summary = !!s.length ? s.join(' – ') : '';

        const {location: _location = 'location', _of = 'of', _in = 'in'} = messages;
				const geoMeta = !pointer ? mainTypes.join(',') : pointer.split('/').reverse().reduce((s,p,i,a) => {
				  const nr = parseInt(p,10);
				  if (typeof nr === 'number' && !isNaN(nr)) {
            const type = messages.hasOwnProperty(a[i+1]) ? messages[a[i+1]] : a[i+1];
				  	const res = `${s}${type} ${nr+1} ${_in} `;
				  	a[i+1] = '';
				    return res
				  }
				  return s + p
				}, `${_location} ${_of} `).replace(/in $/g, '');

				/* and feature per type */
				mainTypes.forEach((apType: string) => {
					(features as any[]).push({
						type: "Feature",
						geometry: {
							type: "Point",
							coordinates: [longitude, latitude]
						},
						properties: {apType, pointer, id, locationId, locationType, location, name, summary, latLng, geoMeta}
					})
				})
			}
		});
	});
	return {type: "FeatureCollection", features: features.reverse()}
}


export function lngLatFromO(o: any): LngLatArray {
	let a: LngLatArray = [0, 0];
	if (isNr(o.latitude) && isNr(o.longitude)) {
		const alt = typeof o.altitude === 'number' && !isNaN(o.altitude) && o.altitude;
		a = !!alt ? [o.longitude, o.latitude, alt] : [o.longitude, o.latitude];
	} else if (isNr(o.lat)) {
		const lon = isNr(o.lon) ? o.lon : isNr(o.lng) ? o.lng : null;
		if (!isNr(lon)) {
			return a;
		}
		const alt = isNr(o.alt) && o.alt;
		a = !!alt ? [lon, o.lat, alt] : [lon, o.lat];
	}
	return a;
}


export function radiusFromO({radius, units = "m"}: any): RadiusO {
	if (!radius || !isNr(radius)) { return {} }
	radius = (units === 'cm') ? (radius / 100) : ((units === 'inches') ? (radius / 12) : radius);
	const conversionUnits: any = { cm: 'meters', inches: 'feet', m: 'meters', km: 'kilometers' }
	const radiusUnit: ("feet"|"kilometers"|"meters"|"miles"|"nautical-miles"|"yards") =
		conversionUnits.hasOwnProperty(units) ? conversionUnits[units] : units;
	return {radius, radiusUnit}
}


(value: any, pointer: string) => {
		/* make sure, pointer is unique and has at least both, longitude and latitude for GeoJSON */
		const matches = pointer.match(/(longitude|latitude)$/g);
		if (matches && !!matches.length) {
			const repl: any = {longitude: 'latitude', latitude: 'longitude'};
			seen.add(pointer);
			if (seen.has(pointer.replace(new RegExp(matches[0]+'$'), repl[matches[0]]))) {
				results.add(pointer.split('/location')[0])
			}
		}
	}


(pointer) => {
		const {id = '', type: mainTypes = ['Object'], location} = jp.get(pointer);
    if (!location) { return }
		/* feature per location */
		location.forEach(({
			longitude, latitude, altitude, units, accuracy, radius,
			id: locationId, type: locationType = 'Place', name: n = '', summary: s = ''
		}: any) => {
			if (longitude && latitude) {
				if (Array.isArray(locationType)) { locationType = locationType[0] }
				const location = JSON.stringify({ longitude, latitude, altitude, units, accuracy, radius });
				const latLng = latLngStr({longitude, latitude, altitude, units, accuracy, radius});
				const name = !!n.length ? n.join(' – ') : '';
				const summary = !!s.length ? s.join(' – ') : '';

        const {location: _location = 'location', _of = 'of', _in = 'in'} = messages;
				const geoMeta = !pointer ? mainTypes.join(',') : pointer.split('/').reverse().reduce((s,p,i,a) => {
				  const nr = parseInt(p,10);
				  if (typeof nr === 'number' && !isNaN(nr)) {
            const type = messages.hasOwnProperty(a[i+1]) ? messages[a[i+1]] : a[i+1];
				  	const res = `${s}${type} ${nr+1} ${_in} `;
				  	a[i+1] = '';
				    return res
				  }
				  return s + p
				}, `${_location} ${_of} `).replace(/in $/g, '');

				/* and feature per type */
				mainTypes.forEach((apType: string) => {
					(features as any[]).push({
						type: "Feature",
						geometry: {
							type: "Point",
							coordinates: [longitude, latitude]
						},
						properties: {apType, pointer, id, locationId, locationType, location, name, summary, latLng, geoMeta}
					})
				})
			}
		});
	}


({
			longitude, latitude, altitude, units, accuracy, radius,
			id: locationId, type: locationType = 'Place', name: n = '', summary: s = ''
		}: any) => {
			if (longitude && latitude) {
				if (Array.isArray(locationType)) { locationType = locationType[0] }
				const location = JSON.stringify({ longitude, latitude, altitude, units, accuracy, radius });
				const latLng = latLngStr({longitude, latitude, altitude, units, accuracy, radius});
				const name = !!n.length ? n.join(' – ') : '';
				const summary = !!s.length ? s.join(' – ') : '';

        const {location: _location = 'location', _of = 'of', _in = 'in'} = messages;
				const geoMeta = !pointer ? mainTypes.join(',') : pointer.split('/').reverse().reduce((s,p,i,a) => {
				  const nr = parseInt(p,10);
				  if (typeof nr === 'number' && !isNaN(nr)) {
            const type = messages.hasOwnProperty(a[i+1]) ? messages[a[i+1]] : a[i+1];
				  	const res = `${s}${type} ${nr+1} ${_in} `;
				  	a[i+1] = '';
				    return res
				  }
				  return s + p
				}, `${_location} ${_of} `).replace(/in $/g, '');

				/* and feature per type */
				mainTypes.forEach((apType: string) => {
					(features as any[]).push({
						type: "Feature",
						geometry: {
							type: "Point",
							coordinates: [longitude, latitude]
						},
						properties: {apType, pointer, id, locationId, locationType, location, name, summary, latLng, geoMeta}
					})
				})
			}
		}


(s,p,i,a) => {
				  const nr = parseInt(p,10);
				  if (typeof nr === 'number' && !isNaN(nr)) {
            const type = messages.hasOwnProperty(a[i+1]) ? messages[a[i+1]] : a[i+1];
				  	const res = `${s}${type} ${nr+1} ${_in} `;
				  	a[i+1] = '';
				    return res
				  }
				  return s + p
				}


(apType: string) => {
					(features as any[]).push({
						type: "Feature",
						geometry: {
							type: "Point",
							coordinates: [longitude, latitude]
						},
						properties: {apType, pointer, id, locationId, locationType, location, name, summary, latLng, geoMeta}
					})
				}


export type EsriUnits = ("feet"|"kilometers"|"meters"|"miles"|"nautical-miles"|"yards");


export type LngLatArray = [number, number] | [number, number, number];


export type RadiusO = {radius?: number; radiusUnit?: EsriUnits;};


toDMS(lat,'N','S')


toDMS(lng,'E','W')


() => ({
  __esModule: true,
  default: jest.fn(),
})


() => {
  jest.clearAllMocks();
}


() => {
  it('Tests daily reset event', async () => {
    await postResetMessage(0);

    expect(postDiscordChannelMessage).toHaveBeenCalledTimes(1);
    expect(postDiscordChannelMessage).toHaveBeenNthCalledWith(1, ':tada: Daily quests have reset');
  });

  it('Tests weekly reset event', async () => {
    await postResetMessage(2);

    expect(postDiscordChannelMessage).toHaveBeenCalledTimes(1);
    expect(postDiscordChannelMessage).toHaveBeenNthCalledWith(1, ':tada: Daily quests and raids have reset');
  });
}


async () => {
    await postResetMessage(0);

    expect(postDiscordChannelMessage).toHaveBeenCalledTimes(1);
    expect(postDiscordChannelMessage).toHaveBeenNthCalledWith(1, ':tada: Daily quests have reset');
  }


async () => {
    await postResetMessage(2);

    expect(postDiscordChannelMessage).toHaveBeenCalledTimes(1);
    expect(postDiscordChannelMessage).toHaveBeenNthCalledWith(1, ':tada: Daily quests and raids have reset');
  }


(extraContext, extra) => {
            if (extra) {
                if (!(babylonMaterial instanceof PBRMaterial)) {
                    throw new Error(`${extraContext}: Material type not supported`);
                }

                const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial);

                if (babylonMaterial.needAlphaBlending()) {
                    babylonMaterial.forceDepthWrite = true;
                    babylonMaterial.separateCullingPass = true;
                }

                babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite;
                babylonMaterial.twoSidedLighting = true;

                return promise;
            }

            return null;
        }


(loader) => new MSFT_minecraftMesh(loader)


/** @hidden */
export class MSFT_minecraftMesh implements IGLTFLoaderExtension {
    public readonly name = NAME;
    public enabled: boolean;

    private _loader: GLTFLoader;

    constructor(loader: GLTFLoader) {
        this._loader = loader;
        this.enabled = this._loader.isExtensionUsed(NAME);
    }

    public dispose() {
        (this._loader as any) = null;
    }

    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
        return GLTFLoader.LoadExtraAsync<boolean>(context, material, this.name, (extraContext, extra) => {
            if (extra) {
                if (!(babylonMaterial instanceof PBRMaterial)) {
                    throw new Error(`${extraContext}: Material type not supported`);
                }

                const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial);

                if (babylonMaterial.needAlphaBlending()) {
                    babylonMaterial.forceDepthWrite = true;
                    babylonMaterial.separateCullingPass = true;
                }

                babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite;
                babylonMaterial.twoSidedLighting = true;

                return promise;
            }

            return null;
        });
    }
}


public dispose() {
        (this._loader as any) = null;
    }


public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
        return GLTFLoader.LoadExtraAsync<boolean>(context, material, this.name, (extraContext, extra) => {
            if (extra) {
                if (!(babylonMaterial instanceof PBRMaterial)) {
                    throw new Error(`${extraContext}: Material type not supported`);
                }

                const promise = this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial);

                if (babylonMaterial.needAlphaBlending()) {
                    babylonMaterial.forceDepthWrite = true;
                    babylonMaterial.separateCullingPass = true;
                }

                babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite;
                babylonMaterial.twoSidedLighting = true;

                return promise;
            }

            return null;
        });
    }


export class MockToken__factory extends ContractFactory {
  constructor(signer?: Signer) {
    super(_abi, _bytecode, signer);
  }

  deploy(
    name: string,
    symbol: string,
    decimals: BigNumberish,
    overrides?: Overrides & { from?: string | Promise<string> }
  ): Promise<MockToken> {
    return super.deploy(
      name,
      symbol,
      decimals,
      overrides || {}
    ) as Promise<MockToken>;
  }
  getDeployTransaction(
    name: string,
    symbol: string,
    decimals: BigNumberish,
    overrides?: Overrides & { from?: string | Promise<string> }
  ): TransactionRequest {
    return super.getDeployTransaction(name, symbol, decimals, overrides || {});
  }
  attach(address: string): MockToken {
    return super.attach(address) as MockToken;
  }
  connect(signer: Signer): MockToken__factory {
    return super.connect(signer) as MockToken__factory;
  }
  static readonly bytecode = _bytecode;
  static readonly abi = _abi;
  static createInterface(): MockTokenInterface {
    return new utils.Interface(_abi) as MockTokenInterface;
  }
  static connect(
    address: string,
    signerOrProvider: Signer | Provider
  ): MockToken {
    return new Contract(address, _abi, signerOrProvider) as MockToken;
  }
}


deploy(
    name: string,
    symbol: string,
    decimals: BigNumberish,
    overrides?: Overrides & { from?: string | Promise<string> }
  ): Promise<MockToken> {
    return super.deploy(
      name,
      symbol,
      decimals,
      overrides || {}
    ) as Promise<MockToken>;
  }


getDeployTransaction(
    name: string,
    symbol: string,
    decimals: BigNumberish,
    overrides?: Overrides & { from?: string | Promise<string> }
  ): TransactionRequest {
    return super.getDeployTransaction(name, symbol, decimals, overrides || {});
  }


attach(address: string): MockToken {
    return super.attach(address) as MockToken;
  }


connect(signer: Signer): MockToken__factory {
    return super.connect(signer) as MockToken__factory;
  }


static createInterface(): MockTokenInterface {
    return new utils.Interface(_abi) as MockTokenInterface;
  }


static connect(
    address: string,
    signerOrProvider: Signer | Provider
  ): MockToken {
    return new Contract(address, _abi, signerOrProvider) as MockToken;
  }


() => {
  it ('should apply diffs properly', () => {
    class Deep extends Model<One> {
      num = fnx.number
      @fnx.action increment?() {
        this.num++
      }
    }
    class Obj extends Model<One> {
      deep = fnx.object(Deep)
      arr = fnx.arrayOf(fnx.boolean)
    }
    class One extends Model<One> {
      str = fnx.string
      @fnx.optional num = fnx.number
      bool = fnx.boolean
      obj = fnx.object(Obj)
      map = fnx.mapOf(fnx.complex.date)

      @fnx.action setStr?(value: string) {
        this.str = value
      }

      @fnx.action randomStuff?() {
        this.bool = false
        this.obj = { arr: [ false, true ], deep: { num: 0 } }
        this.map = { a100: new Date(100) }
      }

      @fnx.action removeNum?() {
        delete this.num
      }
    }
    class Two extends One { }

    const initialState: One = {
      str: 'hi',
      num: 3,
      bool: false,
      obj: { arr: [ true, false ], deep: { num: -1 } },
      map: { }
    }
    const initialState2: One = {
      str: 'hi',
      num: 3,
      bool: false,
      obj: { arr: [ true, false ], deep: { num: -1 } },
      map: { }
    }

    const one = new One(initialState)
    const two = new Two(initialState2)

    one.use(next => {
      two.applyDiffs(next().diff)
    })

    one.setStr('hello')
    one.randomStuff()
    one.removeNum()
    one.obj.deep.increment()
    one.obj.deep.increment()

    const actual = two.getSnapshot({ asString: true })
    const expected = one.getSnapshot({ asString: true })

    expect(actual).toBe(expected)
  })
}


() => {
    class Deep extends Model<One> {
      num = fnx.number
      @fnx.action increment?() {
        this.num++
      }
    }
    class Obj extends Model<One> {
      deep = fnx.object(Deep)
      arr = fnx.arrayOf(fnx.boolean)
    }
    class One extends Model<One> {
      str = fnx.string
      @fnx.optional num = fnx.number
      bool = fnx.boolean
      obj = fnx.object(Obj)
      map = fnx.mapOf(fnx.complex.date)

      @fnx.action setStr?(value: string) {
        this.str = value
      }

      @fnx.action randomStuff?() {
        this.bool = false
        this.obj = { arr: [ false, true ], deep: { num: 0 } }
        this.map = { a100: new Date(100) }
      }

      @fnx.action removeNum?() {
        delete this.num
      }
    }
    class Two extends One { }

    const initialState: One = {
      str: 'hi',
      num: 3,
      bool: false,
      obj: { arr: [ true, false ], deep: { num: -1 } },
      map: { }
    }
    const initialState2: One = {
      str: 'hi',
      num: 3,
      bool: false,
      obj: { arr: [ true, false ], deep: { num: -1 } },
      map: { }
    }

    const one = new One(initialState)
    const two = new Two(initialState2)

    one.use(next => {
      two.applyDiffs(next().diff)
    })

    one.setStr('hello')
    one.randomStuff()
    one.removeNum()
    one.obj.deep.increment()
    one.obj.deep.increment()

    const actual = two.getSnapshot({ asString: true })
    const expected = one.getSnapshot({ asString: true })

    expect(actual).toBe(expected)
  }


next => {
      two.applyDiffs(next().diff)
    }


class Deep extends Model<One> {
      num = fnx.number
      @fnx.action increment?() {
        this.num++
      }
    }


class Obj extends Model<One> {
      deep = fnx.object(Deep)
      arr = fnx.arrayOf(fnx.boolean)
    }


class One extends Model<One> {
      str = fnx.string
      @fnx.optional num = fnx.number
      bool = fnx.boolean
      obj = fnx.object(Obj)
      map = fnx.mapOf(fnx.complex.date)

      @fnx.action setStr?(value: string) {
        this.str = value
      }

      @fnx.action randomStuff?() {
        this.bool = false
        this.obj = { arr: [ false, true ], deep: { num: 0 } }
        this.map = { a100: new Date(100) }
      }

      @fnx.action removeNum?() {
        delete this.num
      }
    }


class Two extends One { }


@fnx.action increment?() {
        this.num++
      }


@fnx.action setStr?(value: string) {
        this.str = value
      }


@fnx.action randomStuff?() {
        this.bool = false
        this.obj = { arr: [ false, true ], deep: { num: 0 } }
        this.map = { a100: new Date(100) }
      }


@fnx.action removeNum?() {
        delete this.num
      }


class Environment extends DynamicEnvironment {
  public appTitle?: string;
  public logoUrl?: string;
  public logoInvertedUrl?: string;
  public production: boolean;
  public appConfigUrl: string;
  public baseUrl: string;
  public pollingIntervalMillis?: number;

  constructor() {
    super();
    this.production = true;
    this.appConfigUrl = 'assets/branding/app-config.json';
    this.baseUrl = '/bridge';
  }
}


export interface IRootState {
  app: IAppState
  user: IUserState
  settings: ISettingsState
}


export default function ModalAddress({
  address,
  deliveryTime,
}: Props): JSX.Element {
  return (

{parseDeliveryTime(deliveryTime)}

{address.street}

      {address.unit &&
{address.unit}
}

{`${address.city}, ${address.state} ${address.zip}`}

{`Notes: ${address.notes}`}


type Props = {
  address: Address;
  deliveryTime: string;
};


parseDeliveryTime(deliveryTime)


/* eslint-disable @typescript-eslint/no-empty-interface */
export interface BpmnLogger {
    debug(message: string, ...args: any[]): void;
    error(message: string, ...args: any[]): void;
    warn(message: string, ...args: any[]): void;
}


export interface BpmnRecordAny extends Record<string, any> {}


export interface BpmnMessage extends BpmnRecordAny {
    fields?: BpmnFields;
    content?: BpmnContent;
    properties?: BpmnProperties;
}


export interface BpmnBehaviour extends BpmnRecordAny {
    id: string;
    type: string;
    execute<M extends BpmnMessage = BpmnApiMessage, R = void>(executeMessage?: M): R;
}


export interface BpmnActivityBehaviour extends BpmnBehaviour {}


export interface BpmnLoopCharacteristicsBehaviour extends BpmnBehaviour {}


export interface BpmnTaskBehaviour extends BpmnActivityBehaviour {
    loopCharacteristics: BpmnLoopCharacteristicsBehaviour;
}


export interface BpmnProcessBehaviour extends BpmnBehaviour {}


export interface BpmnFlowBehaviour extends BpmnBehaviour {}


// export interface BpmnExecutionEventMessageContent {
//     id: string;
//     type: string;
//     executionId: string;
//     parent?: BpmnExecutionEventMessageContent;
//     path?: BpmnExecutionEventMessageContent[];
// }
export interface BpmnProcessExecutionDefinition {
    state: 'pending' | 'running' | 'completed';
    run(callback?: any): void;
    resume(callback?: any): void;

    recover(state?: any): void;

    sendMessage<M extends BpmnMessage = BpmnApiMessage>(message: M): void;

    executionId: string;
    execution: BpmnProcessExecution;
    getProcesses(): BpmnProcess[];

    getExecutableProcesses(): BpmnProcess[];
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): BpmnApi<any>;
    getElementById<E extends BpmnElement = BpmnElement>(elementId: string): E;
    getActivityById(childId: string): BpmnActivity;
    environment: BpmnEnvironment;
    status: string;
    stopped: boolean;
    type: string;
    signal<M extends BpmnMessage = BpmnApiMessage>(message?: M): void;
    broker: BpmnDefinitionBroker;
    id: string;
    isRunning: boolean;
    name: string;
    logger: BpmnLogger;
    waitFor<R>(name: string, onMessage?: OnMessageCallback): Promise<R>;
}


export interface BpmnProcessExecutionDefinitionState {
    state: 'pending' | 'running' | 'completed';
    processes: {
        [processId: string]: {
            variables: any;
            services: any;
            children: BpmnProcessExecutionState[];
        };
    };
}


export interface BpmnProcessExecutionState {
    name: string;
    state: BpmnProcessExecutionStatus;
    stopped: boolean;
    engineVersion: string;
    environment: BpmnEnvironment;
    definitions: BpmnProcessExecutionDefinitionState[];

    entered: boolean;
}


export interface BpmnElement {
    readonly id: string;
    readonly type: string;
    readonly name: string;
}


export interface BpmnActivity extends BpmnElement, BpmnActivityApi {}


export interface BpmnFlow extends BpmnElement, BpmnFlowApi {}


export interface BpmnDefinition extends BpmnDefinitionApi {}


export interface BpmnBroker<W = any> {
    new (owner: W);
    owner: W;
    dismiss(onMessage?: OnMessageCallback): void;
    subscribeTmp(exchangeName: string, pattern: string, onMessage?: any, options?: BpmnRecordAny): any;
    subscribeOnce(exchangeName: string, pattern: string, onMessage?: any, options?: BpmnRecordAny): any;
    unsubscribe(queueName: string, onMessage: any): void;
    assertExchange(exchangeName: string, type?: string, options?: BpmnRecordAny): void;
    deleteExchange(exchangeName: string, ifUnused?: boolean): void;
    bindExchange(source: string, destination: string, pattern?: any, ...args: any[]): void;
    unbindExchange(source: string, destination: string, pattern?: any): any;

    publish(exchangeName: string, routingKey: string, content?: any, options?: BpmnRecordAny): void;
    close(): void;

    assertQueue(
        queueName: string,
        options?: { durable?: boolean; autoDelete?: boolean; deadLetterExchange?: string },
    ): void;
    bindQueue(queueName: string, exchangeName: string, pattern: string, options?: BpmnRecordAny): void;
    unbindQueue(queueName: string, exchangeName: string, pattern: string): void;
    consume(queueName: string, onMessage: any, options?: BpmnRecordAny): void;
    cancel(consumerTag: string): void;
    createQueue(): any;
    deleteQueue(queueName: string, options?: { ifUnused: boolean; ifEmpty?: boolean }): void;
    getExchange(exchangeName: string): any;
    getQueue(queueName: string): any;
    getState<S>(): S;
    recover<S>(state: S): any;
    purgeQueue(queueName: string): void;
    sendToQueue(queueName: string, content?: any, options?: BpmnRecordAny): void;
    stop(): void;
    reset(): void;
    get(queueName: string, options?: any): any;
    ack(message: any, allUpTo?: boolean): void;
    ackAll(): void;
    nack(message: any, allUpTo?: boolean, requeue?: boolean): void;
    nackAll(): void;
    prefetch(count: boolean): void;
    peek(ignoreDelivered?: boolean): any;
    emit(eventName: string, content?: any): void;
    reject(requeue?: boolean): void;
    reject(message: any, requeue?: boolean): void;
    unbindConsumer(): void;
    on(eventName: string, handler: Function): void;
    once(eventName: string, handler: Function): void;
    off(eventName: string, handler: Function): void;
    createShovel(name: string, source: string, destination: string, options?: any): any;
    getShovel(name: string): any;
    closeShovel(name: string): void;
}


export interface BpmnActivityBroker extends BpmnExecutionBroker<BpmnActivity> {}


export interface BpmnProcessBroker extends BpmnExecutionBroker<BpmnProcess> {}


export interface BpmnMessageFlowBroker extends BpmnEventBroker<BpmnFlow> {}


export interface BpmnDefinitionBroker extends BpmnEventBroker<BpmnDefinition> {}


export interface BpmnExecutionBroker<W = any> extends BpmnEventBroker<W> {}


export interface BpmnEventBroker<W = any> extends BpmnBroker<W> {
    new (brokerOwner: W, options?: BpmnRecordAny, onBrokerReturn?: (message?: any) => void);
    broker: BpmnBroker<W>;
    eventPrefix: string;

    on<M = W, R = any>(
        eventName: string,
        callback: (message: M) => void,
        eventOptions?: { once?: boolean } & BpmnRecordAny,
    ): R;
    once<M = W, R = any>(eventName: string, callback: (message: M) => void, eventOptions?: BpmnRecordAny): R;
    waitFor<R>(eventName: string, onMessage?: OnMessageCallback): Promise<R>;
    emit<C = BpmnRecordAny, P = BpmnContent>(eventName: string, content?: C, props?: P): void;
    emitFatal<E = Error | string, C = BpmnContent>(error: E, content?: C): void;
}


export interface BpmnBrokerState {}


export interface BpmnState {
    settings: BpmnSettings;
    variables: BpmnVariables;
    output: BpmnApiOutput;
}


export interface BpmnEnvironmentState {
    settings: BpmnSettings;
    variables: BpmnVariables;
    output: BpmnApiOutput;
}


// export function cloneContent(content, extend) {}
// export function cloneMessage(message, overrideContent) {}
// export function cloneParent(parent) {}
// export function unshiftParent(parent, adoptingParent) {}
// export function pushParent(parent, ancestor) {}
export interface BpmnDataObject extends BpmnElement {}


export interface BpmnAssociation extends BpmnElement {}


export interface BpmnSequenceFlow extends BpmnFlow, BpmnSequenceFlowApi {}


export interface BpmnMessageFlow extends BpmnFlow, BpmnMessageFlowApi {}


export interface BpmnExtention {
    activate<M extends BpmnMessage = BpmnApiMessage>(message?: M): void;
    deactivate<M extends BpmnMessage = BpmnApiMessage>(message?: M): void;
}


export interface BpmnApiExecutionContext {
    id: string;
    name: string;
    type: string;
    sid: string;
    definitionContext: BpmnProcessExecutionDefinition;
    environment: BpmnEnvironment;
    clone(): BpmnApiExecutionContext;
    getActivities(): BpmnActivity[];
    getActivityById(activityId: string): BpmnActivity;
    getAssociations(): BpmnAssociation[];
    getExecutableProcesses(): BpmnProcess[];
    getDataObjectById(id: string): BpmnDataObject;
    getInboundAssociations(): BpmnAssociation[];
    getInboundSequenceFlows(): BpmnSequenceFlow[];
    getMessageFlows(): BpmnMessageFlow;
    getOutboundSequenceFlows(): BpmnSequenceFlow[];
    getOutboundAssociations(): BpmnAssociation[];
    getProcessById(processId: string): BpmnProcess;
    getProcesses(): BpmnProcess[];
    getSequenceFlowById(id: string): BpmnSequenceFlow;
    getSequenceFlows(): BpmnSequenceFlow[];
    getStartActivities(): BpmnActivity[];
    loadExtensions(activity: BpmnActivity): BpmnExtentions;
}


export interface BpmnExpressions {
    resolveExpression: BpmnResolveExpression;
    isExpression(text: string): boolean;
    hasExpression(text: string): boolean;
}


export interface BpmnScript {
    execute<R, Z = void>(executionContext: BpmnApiExecutionContext, callback?: BpmnCallback<R>): Z;
}


export interface BpmnScript {
    getScript(scriptType: string, activity: BpmnActivityApi): BpmnScript;
    register(activity: BpmnActivityApi): void;
}


export interface BpmnServices extends Record<string, BpmnService> {}


export interface BpmnService {
    <M = any, C = any, R = void>(executionMessage: M, callback: BpmnCallback<C>): R;
    <M = any, C = any, R = void>(...args: any[]): (executionMessage: M, callback: BpmnCallback<C>) => R;
}


export interface BpmnSettings extends BpmnRecordAny {}


export interface BpmnApiExpression {}


export interface BpmnVariables<E = any> extends Record<string, E> {}


export interface BpmnApiOutput<E = any> extends Record<string, E> {}


export interface BpmnApiMessage extends BpmnMessage {}


export interface BpmnApiExtention {
    <E extends BpmnElement = BpmnActivity, R = void>(element: E, context: BpmnProcess): R;
    <R = void>(...args: any[]): R;
}


export interface BpmnExtentions extends Record<string, BpmnApiExtention> {}


export interface BpmnEnvironmentOptions extends BpmnRecordAny {}


export interface BpmnEnvironment {
    options: BpmnEnvironmentOptions;
    expressions: BpmnApiExpression[];
    extensions: Record<string, BpmnExtentions>;
    output: BpmnApiOutput;
    scripts: Record<string, BpmnScript>;
    services: Record<string, BpmnService>;
    settings: BpmnSettings;
    variables: BpmnVariables;
    addService(name: string, fn: BpmnService): void;
    assignVariables(newVars: BpmnVariables): void;
    clone(): BpmnEnvironment;
    getScript(...args: any[]): BpmnScript;
    getServiceByName(serviceName: string): BpmnService;
    getState(): BpmnEnvironmentState;
    registerScript(...args: any[]): void;
    resolveExpression: BpmnResolveExpression;
    recover(state: BpmnState): BpmnEnvironment;
    Logger: BpmnLogger;
}


export interface BpmnFields extends BpmnRecordAny {}


export interface BpmnContent extends BpmnRecordAny {}


export interface BpmnProperties extends BpmnRecordAny {}


export interface BpmnApi<T> {
    readonly id: string;
    // type: BpmnElementType;
    readonly name: string;
    readonly executionId: string;
    readonly environment: BpmnEnvironment;
    readonly fields: BpmnFields;
    readonly content: BpmnContent;
    readonly messageProperties: BpmnProperties;
    readonly owner: any;
    cancel(): void;
    discard(): void;
    signal<M extends BpmnMessage = BpmnApiMessage, P = BpmnRecordAny>(message?: M, options?: P): void;
    stop(): void;
    resolveExpression(expression: string): string;
    sendApiMessage(action: string, content: BpmnContent, options?: BpmnRecordAny): void;
    createMessage<C extends BpmnContent, R = C>(content?: C): R;
    getPostponed(...args: any[]): BpmnElement[];
}


export interface BpmnFlowApi extends BpmnApi<BpmnFlow> {
    readonly id: string;
    readonly name: string;
    readonly parent: BpmnElement;
    readonly behaviour: BpmnFlowBehaviour;
}


export interface BpmnMessageFlowApi extends BpmnApi<BpmnMessageFlow> {
    readonly id: string;
    readonly type: 'message' | string;
    readonly name: string;
    readonly broker: BpmnMessageFlowBroker;
    readonly parent: BpmnElement;
    readonly behaviour: BpmnFlowBehaviour;
    readonly source: string;
    readonly target: string;
    readonly environment: BpmnEnvironment;
    readonly counters: BpmnCounter;
    on: BpmnMessageFlowBroker['on'];
    once: BpmnMessageFlowBroker['once'];
    emit: BpmnMessageFlowBroker['emit'];
    waitFor: BpmnMessageFlowBroker['waitFor'];
    discard(): void;
    activate(): void;
    deactivate(): void;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): BpmnMessageFlowApi;
    getState(): BpmnFlowState;
    recover<S>(state: S): void;
    resume(): void;
    stop(): void;
}


export interface BpmnSequenceFlowApi extends BpmnApi<BpmnSequenceFlow> {
    readonly id: string;
    readonly type: 'sequenceflow' | string;
    readonly name: string;
    readonly broker: BpmnMessageFlowBroker;
    readonly parent: BpmnElement;
    readonly behaviour: BpmnFlowBehaviour;
    readonly sourceId: string;
    readonly targetId: string;
    readonly isDefault: boolean;
    readonly isSequenceFlow: true;
    readonly environment: BpmnEnvironment;
    readonly counters: BpmnCounter;
    on: BpmnMessageFlowBroker['on'];
    once: BpmnMessageFlowBroker['once'];
    waitFor: BpmnMessageFlowBroker['waitFor'];
    discard(): void;
    evaluateCondition<M extends BpmnMessage = BpmnApiMessage>(
        message: M,
        onEvaluateError: (...args: any[]) => void,
    ): void;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): BpmnSequenceFlowApi;
    getCondition(): string;
    getState(): BpmnFlowState;
    preFlight(action: string): string;
    recover<S>(state: S): void;
    shake(): void;
    stop(): void;
    take<C>(content: C): void;
}


export interface BpmnProcessApi {
    readonly broker: BpmnProcessBroker;
    on: BpmnProcessBroker['on'];
    once: BpmnProcessBroker['once'];
    waitFor: BpmnProcessBroker['waitFor'];
    readonly extensions: BpmnExtentions;
    readonly id: string;
    readonly type: 'process';
    readonly name: string;
    readonly isExecutable: boolean;
    readonly behaviour: BpmnProcessBehaviour;
    readonly counters: BpmnCounter;
    readonly executionId: string;
    readonly status: string;
    readonly stopped: boolean;
    readonly execution: BpmnProcessExecution;
    readonly isRunning: boolean;
    readonly context: BpmnApiExecutionContext;
    readonly environment: BpmnEnvironment;
    readonly parent: BpmnProcess;
    readonly logger: BpmnLogger;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): BpmnProcessApi;
    getActivities(): BpmnActivity[];
    getActivityById(id: string): BpmnActivity;
    getSequenceFlows(): BpmnSequenceFlow[];
    getPostponed(): BpmnElement[];
    getStartActivities(): BpmnActivity[];
    getState(): BpmnProcessState;
    init(): void;
    recover<S = any>(state: S): BpmnProcess;
    resume(): BpmnProcessApi;
    run<M = any>(runContent: M): void;
    sendMessage<M extends BpmnMessage = BpmnApiMessage>(message: M): void;
    signal<M extends BpmnMessage = BpmnApiMessage>(message?: M): void;
    stop(): void;
}


export interface BpmnDefinitionApi extends BpmnApi<BpmnDefinition> {
    broker: BpmnDefinitionBroker;
    on: BpmnDefinitionBroker['on'];
    once: BpmnDefinitionBroker['once'];
    waitFor: BpmnDefinitionBroker['waitFor'];
    emit: BpmnDefinitionBroker['emit'];
    emitFatal: BpmnDefinitionBroker['emitFatal'];
    id: string;
    type: 'definition';
    name: string;
    logger: BpmnLogger;
    context: BpmnApiExecutionContext;
    readonly counters: BpmnCounter;
    readonly executionId: string;
    readonly status: string;
    readonly execution: BpmnDefinitionExecution;
    readonly isRunning: boolean;
    readonly environment: BpmnEnvironment;
    run<R>(callback?: BpmnCallback<R>): this;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): this;
    getState(): BpmnDefinitionState;
    getActivityById(id: string): BpmnActivity | null;
    getElementById(id: string): BpmnElement | null;
    getPostponed(): BpmnElement[];
    getProcesses(): BpmnProcess[];
    getExecutableProcesses(): BpmnProcess[];
    getProcessById(id: string): BpmnProcess;
    sendMessage<M extends BpmnMessage = BpmnApiMessage>(message: M): this;
    recover<S>(state?: S): this;
    resume<R>(callback?: BpmnCallback<R>): this;
    signal<M extends BpmnMessage = BpmnApiMessage>(message?: M): this;
    stop(): void;
}


export interface BpmnDefinitionExecution {
    id: string;
    type: 'definition';
    broker: BpmnDefinitionBroker;
    readonly environment: BpmnEnvironment;
    readonly executionId: string;
    readonly completed: boolean;
    readonly status: string;
    readonly stopped: boolean;
    readonly postponedCount: number;
    readonly isRunning: boolean;
    readonly processes: BpmnProcess[];
    createMessage<C extends BpmnContent, R = C>(content?: C): R;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): this;
    getState(): BpmnDefinitionState;
    getPostponed(): BpmnElement[];
    execute<M extends BpmnMessage = BpmnApiMessage>(message?: M): boolean;
    resume<R>(callback?: BpmnCallback<R>): this;
    recover<S>(state?: S): this;
    stop(): void;
}


export interface BpmnActivityApi extends BpmnApi<BpmnActivity> {
    readonly type: 'activity' | string;
    readonly broker: BpmnActivityBroker;
    on: BpmnActivityBroker['on'];
    once: BpmnActivityBroker['once'];
    waitFor: BpmnActivityBroker['waitFor'];
    readonly extensions: BpmnExtentions;

    readonly behaviour: BpmnActivityBehaviour;
    readonly isEnd: boolean;
    readonly isStart: boolean;
    readonly isSubProcess: boolean;
    readonly isThrowing: boolean;
    readonly isForCompensation: boolean;
    readonly triggeredByEvent: boolean;
    readonly parent: BpmnElement;
    attachedTo: BpmnActivity;
    readonly environment: BpmnEnvironment;
    readonly inbound: BpmnSequenceFlow[];
    readonly outbound: BpmnSequenceFlow[];
    readonly counters: BpmnCounter;
    readonly executionId: string;
    status:
        | 'enter'
        | 'entered'
        | 'discard'
        | 'start'
        | 'execute'
        | 'executing'
        | 'formatting'
        | 'executed'
        | 'end'
        | 'discarded';
    readonly stopped: boolean;
    readonly isRunning: boolean;
    Behaviour: BpmnActivityBehaviour;
    activate(): any;
    deactivate(): void;
    logger: BpmnLogger;
    discard(): void;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): BpmnActivityApi;
    getActivityById(id: string): BpmnActivity;
    getState(): BpmnActivityState;
    init(): void;
    recover<S = any>(state: S): BpmnActivityApi;
    resume(): BpmnActivityApi;
    run<M extends BpmnMessage = BpmnApiMessage>(runContent?: M): void;
    shake(): void;
    stop(): void;
    next<M extends BpmnMessage = BpmnApiMessage>(): M;
}


export interface BpmnProcessState {
    id: string;
    type: string;
    name: string;
    parent: BpmnProcessState;
    executionId: string;
    status: string;
    stopped: boolean;
    counters: BpmnCounter;
    broker: BpmnBrokerState;
    execution: BpmnExecutionProcessState;
}


export interface BpmnProcess extends BpmnProcessApi {
    new (processDefinition: any, context: BpmnApiExecutionContext);
}


export interface BpmnProcessExecution {
    readonly id: string;
    readonly type: string;
    readonly broker: BpmnExecutionBroker;
    readonly environment: BpmnEnvironment;
    readonly executionId: string;
    readonly completed: boolean;
    readonly status: BpmnProcessExecutionStatus;
    readonly stopped: boolean;
    readonly postponedCount: number;
    readonly isRunning: boolean;
    discard(): void;
    execute<M extends BpmnMessage = BpmnApiMessage>(executeMessage: M): boolean;
    getApi<M extends BpmnMessage = BpmnApiMessage>(message?: M): BpmnProcessApi;
    getActivityById(id: string): BpmnActivity;
    getActivities(): BpmnActivity[];
    getPostponed(): BpmnElement[];
    getSequenceFlows(): BpmnSequenceFlow[];
    getState(): BpmnExecutionProcessState;
    recover(): BpmnProcessExecution;
    stop(): void;
}


export interface BpmnCounter extends Record<string, number> {}


export interface BpmnActivityState {
    id: string;
    type: string;
    counters: BpmnCounter;
}


export interface BpmnAssociationState {
    id: string;
    type: string;
    counters: BpmnCounter;
}


export interface BpmnFlowState {
    id: string;
    type: string;
    counters: BpmnCounter;
}


export interface BpmnMessageFlowState {
    id: string;
    type: string;
    counters: BpmnCounter;
}


export interface BpmnExecutionProcessState {
    executionId: string;
    stopped: boolean;
    completed: boolean;
    status: BpmnExecutionProcessStatus;
    children: BpmnActivityState[];
    flows: BpmnFlowState[];
    messageFlows: BpmnMessageFlowState[];
    associations: BpmnAssociationState[];
}


export interface BpmnDefinitionState {
    readonly executionId: string;
    readonly stopped: boolean;
    readonly completed: boolean;
    readonly status: string;
    readonly processes: BpmnProcessState[];
}


export interface BpmnEngineRuntimeState {
    readonly name: string;
    readonly state: BpmnEngineRuntimeStateType;
    readonly stopped: boolean;
    readonly engineVersion: boolean;
    readonly environment: BpmnEnvironment;
    readonly definitions: BpmnDefinitionState;
}


export interface BpmnEngineRuntimeOptions {
    name?: string;
    variables?: BpmnVariables;

    Logger?: BpmnLogger;

    scripts?: Record<string, BpmnScript>;
    listener?: EventEmitter;
    services?: BpmnServices;

    elements?: any;

    typeResolver?: <R>(...elements: any) => R;
    moddleOptions?: any;

    extensions?: BpmnExtentions;
}


export interface BpmnEngineRuntime extends EventEmitter {
    readonly broker: BpmnBroker<this>;
    readonly name: string;

    // readonly on: BpmnBroker['on'];
    // readonly once: BpmnBroker['once'];
    // readonly off: BpmnBroker['off'];

    readonly environment: BpmnEnvironment;
    readonly execution: BpmnProcessExecution;
    readonly stopped: boolean;
    readonly state: BpmnEngineRuntimeStateType;
    execute<P extends BpmnEngineRuntimeOptions = BpmnEngineRuntimeOptions>(
        executeOptions?: P,
    ): Promise<BpmnEngineRuntimeApi>;
    logger: BpmnLogger;
    getDefinitionById(id: string): Promise<BpmnDefinition>;
    getDefinitions(executeOptions?: BpmnEngineRuntimeOptions): Promise<BpmnDefinition[]>;
    getState(): Promise<BpmnEngineRuntimeState>;
    recover<S, P>(savedState: S, recoverOptions: P): this;
    resume<P extends BpmnEngineRuntimeOptions = BpmnEngineRuntimeOptions>(
        executeOptions?: P,
    ): Promise<BpmnEngineRuntimeApi>;
    stop(): Promise<void>;
    waitFor<R = void>(eventName: string, onMessage?: OnMessageCallback): Promise<R>;
}


export interface BpmnEngineRuntimeExecution extends BpmnEngineRuntimeApi {}


export interface BpmnEngineRuntimeApi {
    readonly name: string;
    readonly state: BpmnEngineRuntimeStateType;
    readonly stopped: boolean;
    readonly environment: BpmnEnvironment;
    readonly definitions: BpmnDefinition[];
    stop(): Promise<void>;
    getState(): Promise<BpmnEngineRuntimeState>;
    getPostponed(): Promise<BpmnElement[]>;
    waitFor<R = void>(eventName: string, onMessage?: OnMessageCallback): Promise<R>;
}


export type BpmnCallback<R, Z = void> = (err: Error, result: R) => Z;


export type BpmnResolveExpression = <E = string>(expression: string, apiMessage?: BpmnApiMessage, owner?: any) => E;


export type BpmnElementType =
    | 'activity'
    | 'process'
    | 'flow'
    | 'association'
    | 'sequenceflow'
    | 'message'
    | 'defnition';


export type BpmnProcessExecutionStatus = 'stopped' | 'idle' | 'error' | 'running';


export type BpmnExecutionProcessStatus = 'start' | 'init' | 'discard' | 'terminate' | 'executing';


export type BpmnEngineRuntimeStateType = 'stopped' | 'idle' | 'error' | 'running';


export type OnMessageCallback = (routingKey: string, message: string, owner: any) => void;


/* istanbul ignore next: autogenerated */
export class EdgeGatewaySslVpnRadiusAuthServer extends EdgeGatewaySslVpnAuthServer {

  constructor(private _json: EdgeGatewaySslVpnRadiusAuthServerJson) {
    super(_json);
  }

  /**
   * Get object id.
   * @returns {string}
   */
  get objectId(): string {
    return this._json.object_id;
  }

  /**
   * Get enabled.
   * @returns {boolean}
   */
  get enabled(): boolean {
    return this._json.enabled;
  }

  /**
   * Get secondary auth server.
   * @returns {boolean}
   */
  get secondaryAuthServer(): boolean {
    return this._json.secondary_auth_server;
  }

  /**
   * Get terminate session on auth fails.
   * @returns {boolean}
   */
  get terminateSessionOnAuthFails(): boolean {
    return this._json.terminate_session_on_auth_fails;
  }

  /**
   * Get ip.
   * @returns {string}
   */
  get ip(): string {
    return this._json.ip;
  }

  /**
   * Get port.
   * @returns {number}
   */
  get port(): number {
    return this._json.port;
  }

  /**
   * Get timeout.
   * @returns {number}
   */
  get timeout(): number {
    return this._json.timeout;
  }

  /**
   * Get secret.
   * @returns {string}
   */
  get secret(): string {
    return this._json.secret;
  }

  /**
   * Get nas ip.
   * @returns {string}
   */
  get nasIp(): string {
    return this._json.nas_ip;
  }

  /**
   * Get retry count.
   * @returns {number}
   */
  get retryCount(): number {
    return this._json.retry_count;
  }

  /**
   * Get auth server type.
   * @returns {EdgeGatewaySslVpnAuthServerType}
   */
  get authServerType(): EdgeGatewaySslVpnAuthServerType {
    return this._json.auth_server_type;
  }

  /**
   * Get the json representation of this class.
   * @returns {EdgeGatewaySslVpnRadiusAuthServerJson}
   */
  get json(): EdgeGatewaySslVpnRadiusAuthServerJson {
    return Object.assign({}, this._json);
  }

  /**
   * Get the string representation of this class.
   * @returns {string}
   */
  toString(): string {
    return JSON.stringify(this._json, undefined, 2);
  }
}


/**
   * Get the string representation of this class.
   * @returns {string}
   */
toString(): string {
    return JSON.stringify(this._json, undefined, 2);
  }


() => {
  let bb = bodybuilder()
  Object.entries(STUFF).forEach(([key, value]: any) => {
    bb = bb.orFilter(
      'term',
      key !== 'medals' && key !== 'stamps' && key !== 'coin'
        ? 'format_id.keyword'
        : 'subject_curated_title',
      key !== 'medals' && key !== 'stamps' && key !== 'coin' ? value.id : key
    )
  })
  return bb
}


([key, value]: any) => {
    bb = bb.orFilter(
      'term',
      key !== 'medals' && key !== 'stamps' && key !== 'coin'
        ? 'format_id.keyword'
        : 'subject_curated_title',
      key !== 'medals' && key !== 'stamps' && key !== 'coin' ? value.id : key
    )
  }


async (array, callback) => {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array)
  }
}


({ query, esQuery }) => {
  return query.filter('bool', (b) => {
    esQuery.values.forEach((val) => {
      if (esQuery.type === 'must_not') {
        b = b.notFilter(esQuery.matchType, esQuery.field, val)
      } else {
        // should (ignoring must for now)
        b = b.orFilter(esQuery.matchType, esQuery.field, val)
      }
    })
    return b
  })
}


(b) => {
    esQuery.values.forEach((val) => {
      if (esQuery.type === 'must_not') {
        b = b.notFilter(esQuery.matchType, esQuery.field, val)
      } else {
        // should (ignoring must for now)
        b = b.orFilter(esQuery.matchType, esQuery.field, val)
      }
    })
    return b
  }


(val) => {
      if (esQuery.type === 'must_not') {
        b = b.notFilter(esQuery.matchType, esQuery.field, val)
      } else {
        // should (ignoring must for now)
        b = b.orFilter(esQuery.matchType, esQuery.field, val)
      }
    }


({ key, id, query }) => {
  const field =
    key !== 'medals' && key !== 'stamps' && key !== 'coin'
      ? 'format_id.keyword'
      : 'subject_curated_title'
  const value =
    key !== 'medals' && key !== 'stamps' && key !== 'coin' ? id : key
  return query.filter('term', field, value)
}


(url): any => {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = url
  })
}


(resolve, reject) => {
    const img = new Image()
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = url
  }


() => resolve(img)


async (bucket) => {
  // gets image as canvas that can be queried like:
  // pixelData = canvas.getContext('2d').getImageData(x, y, 1, 1).data
  const url = BASE_URL + 'pixels/' + bucket.key + '.png'
  const img = await loadImage(url)
  const canvas = document.createElement('canvas')
  canvas.width = img.width
  canvas.height = img.height
  canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height)
  return { pixels: canvas, width: img.width }
}


(pixels) => {
  const width = pixels.width
  const height = pixels.height
  const tileCount = width * height
  const imgData = pixels.getContext('2d').getImageData(0, 0, width, height)

  const positions = new Float32Array(width * height * 3)
  const colors = new Float32Array(width * height * 3)
  const hsls = new Float32Array(width * height * 3)

  const color = new THREE.Color()
  for (let i = 0, i4 = 0, l = tileCount; i < l; i++, i4 += 4) {
    color.setRGB(
      imgData.data[i4] / 255,
      imgData.data[i4 + 1] / 255,
      imgData.data[i4 + 2] / 255
    )
    const hsl = { h: 0, s: 0, l: 0 }
    color.getHSL(hsl)

    const x = i % width
    const y = Math.floor(i / width)
    const z = 0

    positions[i * 3] = x
    positions[i * 3 + 1] = y
    positions[i * 3 + 2] = z

    colors[i * 3] = color.r
    colors[i * 3 + 1] = color.g
    colors[i * 3 + 2] = color.b

    hsls[i * 3] = hsl.h
    hsls[i * 3 + 1] = hsl.s
    hsls[i * 3 + 2] = hsl.l
  }
  return { colors, positions, hsls }
}


({ hsls, width }) => {
  const l = hsls.length / 3
  const toSort = []
  for (let i = 0, i3 = 0; i < l; i++, i3 += 3) {
    toSort.push({ h: hsls[i3], s: hsls[i3 + 1], l: hsls[i3 + 2], i })
  }
  toSort.sort((a, b) =>
    b.h === a.h ? (b.l === a.l ? a.s - b.s : b.l - a.l) : b.h - a.h
  )
  const sorted = toSort.map((i) => i.i)
  const huePositions = new Float32Array(hsls.length)
  const hueIndexes = new Float32Array(l)
  sorted.forEach((i, idx) => {
    // the i-th color item needs to go to x,y based on idx
    const x = idx % width
    const y = Math.floor(idx / width)
    const z = 0
    huePositions[i * 3] = x
    huePositions[i * 3 + 1] = y
    huePositions[i * 3 + 2] = z
    hueIndexes[idx] = i
  })
  return { huePositions, hueIndexes }
}


(a, b) =>
    b.h === a.h ? (b.l === a.l ? a.s - b.s : b.l - a.l) : b.h - a.h


(i) => i.i


(i, idx) => {
    // the i-th color item needs to go to x,y based on idx
    const x = idx % width
    const y = Math.floor(idx / width)
    const z = 0
    huePositions[i * 3] = x
    huePositions[i * 3 + 1] = y
    huePositions[i * 3 + 2] = z
    hueIndexes[idx] = i
  }


(data) => {
  const rows = data.split('\n').filter((r) => r !== '')
  const header = rows.splice(0, 1)[0]
  const wh = header.split(' ')
  const w = Number(wh[0])
  const h = Number(wh[1])
  const tsnePositions = new Float32Array(rows.length * 3)
  const tsneIndexes = new Float32Array(w * h).fill(-1)
  rows.forEach((row, i) => {
    const xy = row.split(' ')
    const x = Number(xy[0])
    const y = Number(xy[1])
    tsnePositions[i * 3] = x
    tsnePositions[i * 3 + 1] = y
    tsnePositions[i * 3 + 2] = 0
    tsneIndexes[y * w + x] = i
  })
  return { tsneIndexes, tsnePositions }
}


(r) => r !== ''


(row, i) => {
    const xy = row.split(' ')
    const x = Number(xy[0])
    const y = Number(xy[1])
    tsnePositions[i * 3] = x
    tsnePositions[i * 3 + 1] = y
    tsnePositions[i * 3 + 2] = 0
    tsneIndexes[y * w + x] = i
  }


(data, side) => {
  const rows = data.split('\n').filter((r) => r !== '')
  const toSort = []
  const l = rows.length
  for (let i = 0; i < l; i++) {
    toSort.push({ year: Number(rows[i]), i })
  }
  toSort.sort((a, b) => a.year - b.year)
  const yearPositions = new Float32Array(l * 3)
  const yearIndexes = new Float32Array(l)
  const yearYears = new Float32Array(l)
  toSort.forEach((i, idx) => {
    // the i-th year item needs to go to x,y based on idx
    const x = idx % side
    const y = Math.floor(idx / side)
    const z = 0
    yearPositions[i.i * 3] = x
    yearPositions[i.i * 3 + 1] = y
    yearPositions[i.i * 3 + 2] = z
    yearIndexes[idx] = i.i
    yearYears[i.i] = i.year
  })
  return { yearIndexes, yearPositions, yearYears }
}


(a, b) => a.year - b.year


(i, idx) => {
    // the i-th year item needs to go to x,y based on idx
    const x = idx % side
    const y = Math.floor(idx / side)
    const z = 0
    yearPositions[i.i * 3] = x
    yearPositions[i.i * 3 + 1] = y
    yearPositions[i.i * 3 + 2] = z
    yearIndexes[idx] = i.i
    yearYears[i.i] = i.year
  }


(state) =>
      Object.values(state.stuff)
        .map((b: any) => b.count)
        .reduce((a, b) => a + b, 0)


(b: any) => b.count


(a, b) => a + b


(atlas) => {
        commit('decreaseLoadedAtlas')
        atlas.encoding = THREE.sRGBEncoding
        atlas.flipY = false
        commit('setAtlasForBucketIndex', { bucket, index, atlas })
      }


(p) => {
              return { color: p.h, percent: Number(p.f) }
            }


(p) => p.t.split(':')


async (row) => {
        const key = row.bucket
        if (!STUFF[key]) return
        const count = Number(row.count)
        const bucket = { ...STUFF[key], count, key }
        const imCount = count < 10 ? count : 10
        bucket.images = []
        for (let i = 0; i < imCount; i++) {
          bucket.images.push(BASE_URL + 'images/' + key + '/' + i + '.jpg')
        }
        buckets[key] = bucket
        // get the pixels ahead of time
        const pixelData = await getPixelsForBucket(bucket)
        pixels[key] = pixelData
        if (bucketKey && key === bucketKey) {
          state.currentBucket = bucket
        }
        total += count
      }


async (_, index) => {
        let query = baseQuery()
          .size(MAX_WINDOW_SIZE)
          .from(index * MAX_WINDOW_SIZE)
          .rawOption('_source', '_id')
        query = makeFilter({ key, id, query })
        const esQuery = bucket.esQuery
        if (esQuery) query = makeFancyFilter({ query, esQuery })

        const baseResponse = await instance.post(url, {
          ...query.build(),
          ...params
        })
        const hits = baseResponse.data.hits
        ids = ids.concat(hits.hits.map((hit) => hit._id))
      }


(hit) => hit._id


(state, { id, image, title }) => {
      if (id !== state.fileData['id']) return // race condition lost
      const fileData = { ...state.fileData, image, title }
      state.fileData = fileData
    }


(state, { id, palette, colorNames }) => {
      if (id !== state.fileData['id']) return // race condition lost
      const fileData = { ...state.fileData, palette, colorNames }
      state.fileData = fileData
    }


(state, value) => (state.bucketKey = value)


(state, value) => (state.loadingBucket = value)


(state, value) => (state.bucketObjects = value)


(state, newState) => (state = { ...state, ...newState })


(state) => (state.confirmedAtlas = true)


(state, value) => (state.showAtlases = value)


(state, value) => {
      if (!value) value = 'default'
      state.sort = value
    }


(state, value) => {
      state.loadedAtlas = value
    }


(state) => {
      state.loadedAtlas--
    }


(state, { bucket, index, atlas }) => {
      const atlases = { ...state.atlases }
      let newBucket
      if (atlases[bucket.key]) {
        newBucket = [...atlases[bucket.key]]
      } else {
        newBucket = []
      }
      newBucket[index] = atlas
      atlases[bucket.key] = newBucket
      state.atlases = atlases
    }


(state, data) => (state.fileData = data)


(state, stuff) => (state.stuff = stuff)


(state, bucket) => (state.currentBucket = bucket)


getCurrentAtlases({ dispatch, commit }, { bucket, atlasCount }) {
      commit('setLoadedAtlas', atlasCount)
      for (let index = 0; index < atlasCount; index++) {
        dispatch('getAtlasForBucketIndex', { bucket, index })
      }
    }


getAtlasForBucketIndex({ commit }, { bucket, index }) {
      const url = BASE_URL + 'atlas/' + bucket.key + '_' + index + '.jpg'
      const texture = new AjaxTextureLoader()
      texture.load(url, (atlas) => {
        commit('decreaseLoadedAtlas')
        atlas.encoding = THREE.sRGBEncoding
        atlas.flipY = false
        commit('setAtlasForBucketIndex', { bucket, index, atlas })
      })
    }


async loadFilePalette({ commit }, { id, url }) {
      let palette = []
      const colorNames = []
      try {
        const response = await instance.get(url)
        const palettes = response.data
        palette = palettes
          ? palettes.map((p) => {
              return { color: p.h, percent: Number(p.f) }
            })
          : []
        const colorNames = palettes ? palettes.map((p) => p.t.split(':')) : []
        commit('setFilePalette', { id, palette, colorNames })
      } catch {
        commit('setFilePalette', { id, palette, colorNames })
      }
    }


async loadFileImage({ commit }, { id, url }) {
      const notFoundImg = BASE_URL + 'assets/not_found.svg'
      try {
        const response = await instance.get(url)
        const image = response.data.file.image.variants['300_300'].url
        const title = response.data.file.title
        const img = await loadImage(image)
        if (img) {
          commit('setFileImageTitle', { id, image, title })
        }
      } catch {
        commit('setFileImageTitle', { id, image: notFoundImg, title: -1 })
      }
    }


loadFile({ dispatch }, { fileId }) {
      const id = fileId
      let url = API_BASE_URL + 'files/' + fileId
      dispatch('loadFileImage', { id, url })
      url = S3_BASE_URL + 'colors_minimal/' + id + '.json'
      dispatch('loadFilePalette', { id, url })
    }


async getBuckets({ state, commit }) {
      const bucketKey = state.bucketKey
      const url = BASE_URL + 'counts.csv'
      const response = await instance.get(url)
      const data = await csv().fromString(response.data)
      const buckets = {}
      const pixels = {}
      let total = 0
      await asyncForEach(data, async (row) => {
        const key = row.bucket
        if (!STUFF[key]) return
        const count = Number(row.count)
        const bucket = { ...STUFF[key], count, key }
        const imCount = count < 10 ? count : 10
        bucket.images = []
        for (let i = 0; i < imCount; i++) {
          bucket.images.push(BASE_URL + 'images/' + key + '/' + i + '.jpg')
        }
        buckets[key] = bucket
        // get the pixels ahead of time
        const pixelData = await getPixelsForBucket(bucket)
        pixels[key] = pixelData
        if (bucketKey && key === bucketKey) {
          state.currentBucket = bucket
        }
        total += count
      })
      state.stuff = buckets
      state.pixels = pixels
      state.itemsTotal = total
      state.loaded = true
      commit('updateState', state)
    }


async loadBucket({ state, commit }, bucket) {
      if (!bucket) {
        commit('setBucket', null)
        return
      }
      commit('setLoadingBucket', true)
      const url = BASE_URL + 'buckets/' + bucket.key + '.txt'
      const response = await instance.get(url)
      const ids = response.data
      const currentBucket = { ...state.stuff[bucket.id], ...bucket }
      currentBucket.ids = ids.split(',')

      // color data
      const { pixels, width } = state.pixels[bucket.key]
      currentBucket.pixels = pixels
      const { colors, positions, hsls } = getColorsPositions(
        currentBucket.pixels
      )
      state.defaultColors = colors
      state.defaultPositions = positions
      const { huePositions, hueIndexes } = sortByHue({ hsls, width })

      // tsne data
      const tsneUrl = BASE_URL + 'similarities/' + bucket.key + '.txt'
      const tsneResponse = await instance.get(tsneUrl)
      const parsedTsne = parseTsne(tsneResponse.data)
      const { tsneIndexes, tsnePositions } = parsedTsne

      // year data
      const yearUrl = BASE_URL + 'years/' + bucket.key + '.txt'
      const yearResponse = await instance.get(yearUrl)
      const parsedYear = parseYear(yearResponse.data, width)
      const { yearIndexes, yearPositions, yearYears } = parsedYear

      state.yearPositions = yearPositions
      state.yearIndexes = yearIndexes
      state.yearYears = yearYears
      state.tsnePositions = tsnePositions
      state.tsneIndexes = tsneIndexes
      state.huePositions = huePositions
      state.hueIndexes = hueIndexes
      state.currentBucket = currentBucket
      state.loadingBucket = false
      commit('updateState', state)
    }


async getIdsForBucket({ state, commit }, bucket) {
      const url = process.env.VUE_APP_ELASTIC_BASE_URL + '_search'
      const key = bucket.key
      const id = bucket.id
      const count = bucket.count
      const pages = Math.ceil(count / MAX_WINDOW_SIZE)
      const pageArray = new Array(pages)
      const params = { track_total_hits: true }
      let ids = []
      await asyncForEach(pageArray, async (_, index) => {
        let query = baseQuery()
          .size(MAX_WINDOW_SIZE)
          .from(index * MAX_WINDOW_SIZE)
          .rawOption('_source', '_id')
        query = makeFilter({ key, id, query })
        const esQuery = bucket.esQuery
        if (esQuery) query = makeFancyFilter({ query, esQuery })

        const baseResponse = await instance.post(url, {
          ...query.build(),
          ...params
        })
        const hits = baseResponse.data.hits
        ids = ids.concat(hits.hits.map((hit) => hit._id))
      })
      const newBucket = { ...bucket, data: [...ids] }
      let newStuff = { ...state.stuff }
      newStuff = { ...newStuff, [key]: newBucket }
      const stuff = { ...newStuff }
      commit('updateState', { ...state, stuff })
    }


export function Star(props?: StarProps): Primitive {
    const { outerRadius, innerRadius, thickness, pointCount } = { ...DefaultStarProps, ...props };

    const triangleCount = pointCount * 2 * 2;
    const builder = PrimitiveBuilder(triangleCount);

    const innerPoints = new Float32Array(pointCount * 2);
    const outerPoints = new Float32Array(pointCount * 2);

    for (let i = 0; i < pointCount; ++i) {
        const io = i * 2, ii = i * 2 + 1;
        const co = (io + 1) / pointCount * Math.PI, ci = (ii + 1) / pointCount * Math.PI;
        outerPoints[io] = Math.cos(co) * outerRadius;
        outerPoints[ii] = Math.sin(co) * outerRadius;
        innerPoints[io] = Math.cos(ci) * innerRadius;
        innerPoints[ii] = Math.sin(ci) * innerRadius;
    }

    Vec3.set(op, 0, 0, thickness / 2);
    Vec3.set(on, 0, 0, -thickness / 2);

    for (let i = 0; i < pointCount; ++i) {
        const ni = (i + 1) % pointCount;
        Vec3.set(a, outerPoints[i * 2], outerPoints[i * 2 + 1], 0);
        Vec3.set(b, innerPoints[i * 2], innerPoints[i * 2 + 1], 0);
        Vec3.set(c, outerPoints[ni * 2], outerPoints[ni * 2 + 1], 0);

        builder.add(op, a, b);
        builder.add(b, a, on);
        builder.add(op, b, c);
        builder.add(c, b, on);
    }

    return builder.getPrimitive();
}


export type StarProps = Partial<typeof DefaultStarProps>


(): void => {
  beforeEach(async (): Promise<void> => {
    await waitReady();
  });

  [256, 1024, 2048].forEach((rounds): void => {
    it(`has equivalent Wasm & JS results (${rounds} rounds)`, (): void => {
      const salt = randomAsU8a();

      expect(
        u8aEq(
          pbkdf2Encode(TEST_PASSWORD, salt, rounds, false).password,
          pbkdf2Encode(TEST_PASSWORD, salt, rounds, true).password
        )
      ).toBe(true);
    });
  });

  [false, true].forEach((onlyJs): void => {
    it(`creates known iterations (onlyJs = ${onlyJs.toString()})`, (): void => {
      expect(
        u8aToHex(pbkdf2Encode(TEST_PASSWORD, KNOWN_SALT, 2048, onlyJs).password)
      ).toEqual(
        '0x600ba9ad65e4294d112e028fdad5dd8fce0a6a6e6b89fb36ed006785ccc3b3aec46831b3105c24237293e6cfa1a0ef6717c113f87ff9237a3f73d210adfa6634'
      );
    });
  });
}


async (): Promise<void> => {
    await waitReady();
  }


(rounds): void => {
    it(`has equivalent Wasm & JS results (${rounds} rounds)`, (): void => {
      const salt = randomAsU8a();

      expect(
        u8aEq(
          pbkdf2Encode(TEST_PASSWORD, salt, rounds, false).password,
          pbkdf2Encode(TEST_PASSWORD, salt, rounds, true).password
        )
      ).toBe(true);
    });
  }


(): void => {
      const salt = randomAsU8a();

      expect(
        u8aEq(
          pbkdf2Encode(TEST_PASSWORD, salt, rounds, false).password,
          pbkdf2Encode(TEST_PASSWORD, salt, rounds, true).password
        )
      ).toBe(true);
    }


(onlyJs): void => {
    it(`creates known iterations (onlyJs = ${onlyJs.toString()})`, (): void => {
      expect(
        u8aToHex(pbkdf2Encode(TEST_PASSWORD, KNOWN_SALT, 2048, onlyJs).password)
      ).toEqual(
        '0x600ba9ad65e4294d112e028fdad5dd8fce0a6a6e6b89fb36ed006785ccc3b3aec46831b3105c24237293e6cfa1a0ef6717c113f87ff9237a3f73d210adfa6634'
      );
    });
  }


(): void => {
      expect(
        u8aToHex(pbkdf2Encode(TEST_PASSWORD, KNOWN_SALT, 2048, onlyJs).password)
      ).toEqual(
        '0x600ba9ad65e4294d112e028fdad5dd8fce0a6a6e6b89fb36ed006785ccc3b3aec46831b3105c24237293e6cfa1a0ef6717c113f87ff9237a3f73d210adfa6634'
      );
    }


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'scalecloud';
}


/**
 * Error thrown for errors in an arithmetic, casting, or conversion
 * operation.
 */
export declare class ArithmeticError extends AbstractError {
    /**
     * Create a new arithmetic error.
     * @param message The error message.
     * @param innerError The inner exception.
     */
    constructor(message?: string, innerError?: Error);
}


declare function Pencil(props: any): any;


export enum PROVIDERS {
  USER_REPOSITORY = 'USER_REPOSITORY',
  MESSAGE_REPOSITORY = 'MESSAGE_REPOSITORY',
  DATABASE_MAIN_CONNECTION = 'DATABASE_MAIN_CONNECTION',
  CACHE_MAIN_CONNECTION = 'CACHE_MAIN_CONNECTION',
}


/** mat-form-field for GlobExpression inputs. */
@Component({
  selector: 'date-time-input-toggle',
  templateUrl: './date_time_input_toggle.ng.html',
  styleUrls: ['./date_time_input_toggle.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DateTimeInputToggle {
  @Input('for') dateTimeInput?: DateTimeInput;

  calendarClick() {
    if (this.dateTimeInput === undefined) {
      throw new Error(
          '[for] input must be specified on date-time-input-toggle');
    }

    this.dateTimeInput.calendarClick();
  }

  clockClick() {
    if (this.dateTimeInput === undefined) {
      throw new Error(
          '[for] input must be specified on date-time-input-toggle');
    }

    this.dateTimeInput.clockClick();
  }
}


calendarClick() {
    if (this.dateTimeInput === undefined) {
      throw new Error(
          '[for] input must be specified on date-time-input-toggle');
    }

    this.dateTimeInput.calendarClick();
  }


clockClick() {
    if (this.dateTimeInput === undefined) {
      throw new Error(
          '[for] input must be specified on date-time-input-toggle');
    }

    this.dateTimeInput.clockClick();
  }


@Module({
  imports: [
    PassportModule.register({ defaultStrategy: "jwt" }),
    JwtModule.register({
      secret: process.env.JWT_SECRET || jwtConfig.secret,
      signOptions: {
        expiresIn: jwtConfig.expiresIn,
      },
    }),
    TypeOrmModule.forFeature([UserRepository]),
  ],
  controllers: [AuthController],
  providers: [AuthService, JwtStrategy],
  exports: [JwtStrategy, PassportModule],
})
export class AuthModule {}


(config: any) => (this.gitConfig = config)


account => {
      this.account = account;
      this.gitConfigurationService.setupGitConfiguration();
    }


@Component({
  selector: 'jhi-home',
  templateUrl: './home.component.html',
  styleUrls: ['home.scss']
})
export class HomeComponent implements OnInit, OnDestroy {
  account: Account | null = null;
  authSubscription?: Subscription;
  gitConfig: GitConfigurationModel;

  constructor(
    private accountService: AccountService,
    private loginModalService: LoginModalService,
    private gitConfigurationService: GitConfigurationService
  ) {
    this.gitConfig = this.gitConfigurationService.gitConfig;
  }

  ngOnInit(): void {
    this.gitConfigurationService.sharedData.subscribe((config: any) => (this.gitConfig = config));
    this.authSubscription = this.accountService.getAuthenticationState().subscribe(account => {
      this.account = account;
      this.gitConfigurationService.setupGitConfiguration();
    });
  }

  isAuthenticated(): boolean {
    return this.accountService.isAuthenticated();
  }

  login(): void {
    this.loginModalService.open();
  }

  ngOnDestroy(): void {
    if (this.authSubscription) {
      this.authSubscription.unsubscribe();
    }
  }
}


ngOnInit(): void {
    this.gitConfigurationService.sharedData.subscribe((config: any) => (this.gitConfig = config));
    this.authSubscription = this.accountService.getAuthenticationState().subscribe(account => {
      this.account = account;
      this.gitConfigurationService.setupGitConfiguration();
    });
  }


isAuthenticated(): boolean {
    return this.accountService.isAuthenticated();
  }


login(): void {
    this.loginModalService.open();
  }


ngOnDestroy(): void {
    if (this.authSubscription) {
      this.authSubscription.unsubscribe();
    }
  }


export class CollectionResponseAssociatedId {
    'results': Array<AssociatedId>;
    'paging'?: Paging;

    static discriminator: string | undefined = undefined;

    static attributeTypeMap: Array<{name: string, baseName: string, type: string}> = [
        {
            "name": "results",
            "baseName": "results",
            "type": "Array<AssociatedId>"
        },
        {
            "name": "paging",
            "baseName": "paging",
            "type": "Paging"
        }    ];

    static getAttributeTypeMap() {
        return CollectionResponseAssociatedId.attributeTypeMap;
    }
}


static getAttributeTypeMap() {
        return CollectionResponseAssociatedId.attributeTypeMap;
    }


function newCharacterToken(index: number, code: number): Token {
  return new Token(index, TokenType.Character, code, StringWrapper.fromCharCode(code));
}


function newIdentifierToken(index: number, text: string): Token {
  return new Token(index, TokenType.Identifier, 0, text);
}


function newKeywordToken(index: number, text: string): Token {
  return new Token(index, TokenType.Keyword, 0, text);
}


function newOperatorToken(index: number, text: string): Token {
  return new Token(index, TokenType.Operator, 0, text);
}


function newStringToken(index: number, text: string): Token {
  return new Token(index, TokenType.String, 0, text);
}


function newNumberToken(index: number, n: number): Token {
  return new Token(index, TokenType.Number, n, "");
}


function isWhitespace(code: number): boolean {
  return (code >= $TAB && code <= $SPACE) || (code == $NBSP);
}


function isIdentifierStart(code: number): boolean {
  return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || (code == $_) || (code == $$);
}


export function isIdentifier(input: string): boolean {
  if (input.length == 0) return false;
  var scanner = new _Scanner(input);
  if (!isIdentifierStart(scanner.peek)) return false;
  scanner.advance();
  while (scanner.peek !== $EOF) {
    if (!isIdentifierPart(scanner.peek)) return false;
    scanner.advance();
  }
  return true;
}


function isIdentifierPart(code: number): boolean {
  return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) ||
         (code == $_) || (code == $$);
}


function isDigit(code: number): boolean {
  return $0 <= code && code <= $9;
}


function isExponentStart(code: number): boolean {
  return code == $e || code == $E;
}


function isExponentSign(code: number): boolean {
  return code == $MINUS || code == $PLUS;
}


export function isQuote(code: number): boolean {
  return code === $SQ || code === $DQ || code === $BT;
}


function unescape(code: number): number {
  switch (code) {
    case $n:
      return $LF;
    case $f:
      return $FF;
    case $r:
      return $CR;
    case $t:
      return $TAB;
    case $v:
      return $VTAB;
    default:
      return code;
  }
}


@Injectable()
export class Lexer {
  tokenize(text: string): any[] {
    var scanner = new _Scanner(text);
    var tokens = [];
    var token = scanner.scanToken();
    while (token != null) {
      tokens.push(token);
      token = scanner.scanToken();
    }
    return tokens;
  }
}


export class Token {
  constructor(public index: number, public type: TokenType, public numValue: number,
              public strValue: string) {}

  isCharacter(code: number): boolean {
    return (this.type == TokenType.Character && this.numValue == code);
  }

  isNumber(): boolean { return (this.type == TokenType.Number); }

  isString(): boolean { return (this.type == TokenType.String); }

  isOperator(operater: string): boolean {
    return (this.type == TokenType.Operator && this.strValue == operater);
  }

  isIdentifier(): boolean { return (this.type == TokenType.Identifier); }

  isKeyword(): boolean { return (this.type == TokenType.Keyword); }

  isKeywordVar(): boolean { return (this.type == TokenType.Keyword && this.strValue == "var"); }

  isKeywordNull(): boolean { return (this.type == TokenType.Keyword && this.strValue == "null"); }

  isKeywordUndefined(): boolean {
    return (this.type == TokenType.Keyword && this.strValue == "undefined");
  }

  isKeywordTrue(): boolean { return (this.type == TokenType.Keyword && this.strValue == "true"); }

  isKeywordFalse(): boolean { return (this.type == TokenType.Keyword && this.strValue == "false"); }

  toNumber(): number {
    // -1 instead of NULL ok?
    return (this.type == TokenType.Number) ? this.numValue : -1;
  }

  toString(): string {
    switch (this.type) {
      case TokenType.Character:
      case TokenType.Identifier:
      case TokenType.Keyword:
      case TokenType.Operator:
      case TokenType.String:
        return this.strValue;
      case TokenType.Number:
        return this.numValue.toString();
      default:
        return null;
    }
  }
}


export class ScannerError extends BaseException {
  constructor(public message) { super(); }

  toString(): string { return this.message; }
}


class _Scanner {
  length: number;
  peek: number = 0;
  index: number = -1;

  constructor(public input: string) {
    this.length = input.length;
    this.advance();
  }

  advance() {
    this.peek =
        ++this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.input, this.index);
  }

  scanToken(): Token {
    var input = this.input, length = this.length, peek = this.peek, index = this.index;

    // Skip whitespace.
    while (peek <= $SPACE) {
      if (++index >= length) {
        peek = $EOF;
        break;
      } else {
        peek = StringWrapper.charCodeAt(input, index);
      }
    }

    this.peek = peek;
    this.index = index;

    if (index >= length) {
      return null;
    }

    // Handle identifiers and numbers.
    if (isIdentifierStart(peek)) return this.scanIdentifier();
    if (isDigit(peek)) return this.scanNumber(index);

    var start: number = index;
    switch (peek) {
      case $PERIOD:
        this.advance();
        return isDigit(this.peek) ? this.scanNumber(start) : newCharacterToken(start, $PERIOD);
      case $LPAREN:
      case $RPAREN:
      case $LBRACE:
      case $RBRACE:
      case $LBRACKET:
      case $RBRACKET:
      case $COMMA:
      case $COLON:
      case $SEMICOLON:
        return this.scanCharacter(start, peek);
      case $SQ:
      case $DQ:
        return this.scanString();
      case $HASH:
      case $PLUS:
      case $MINUS:
      case $STAR:
      case $SLASH:
      case $PERCENT:
      case $CARET:
        return this.scanOperator(start, StringWrapper.fromCharCode(peek));
      case $QUESTION:
        return this.scanComplexOperator(start, '?', $PERIOD, '.');
      case $LT:
      case $GT:
        return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=');
      case $BANG:
      case $EQ:
        return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=', $EQ,
                                        '=');
      case $AMPERSAND:
        return this.scanComplexOperator(start, '&', $AMPERSAND, '&');
      case $BAR:
        return this.scanComplexOperator(start, '|', $BAR, '|');
      case $NBSP:
        while (isWhitespace(this.peek)) this.advance();
        return this.scanToken();
    }

    this.error(`Unexpected character [${StringWrapper.fromCharCode(peek)}]`, 0);
    return null;
  }

  scanCharacter(start: number, code: number): Token {
    this.advance();
    return newCharacterToken(start, code);
  }

  scanOperator(start: number, str: string): Token {
    this.advance();
    return newOperatorToken(start, str);
  }

  /**
   * Tokenize a 2/3 char long operator
   *
   * @param start start index in the expression
   * @param one first symbol (always part of the operator)
   * @param twoCode code point for the second symbol
   * @param two second symbol (part of the operator when the second code point matches)
   * @param threeCode code point for the third symbol
   * @param three third symbol (part of the operator when provided and matches source expression)
   * @returns {Token}
   */
  scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
                      three?: string): Token {
    this.advance();
    var str: string = one;
    if (this.peek == twoCode) {
      this.advance();
      str += two;
    }
    if (isPresent(threeCode) && this.peek == threeCode) {
      this.advance();
      str += three;
    }
    return newOperatorToken(start, str);
  }

  scanIdentifier(): Token {
    var start: number = this.index;
    this.advance();
    while (isIdentifierPart(this.peek)) this.advance();
    var str: string = this.input.substring(start, this.index);
    if (SetWrapper.has(KEYWORDS, str)) {
      return newKeywordToken(start, str);
    } else {
      return newIdentifierToken(start, str);
    }
  }

  scanNumber(start: number): Token {
    var simple: boolean = (this.index === start);
    this.advance();  // Skip initial digit.
    while (true) {
      if (isDigit(this.peek)) {
        // Do nothing.
      } else if (this.peek == $PERIOD) {
        simple = false;
      } else if (isExponentStart(this.peek)) {
        this.advance();
        if (isExponentSign(this.peek)) this.advance();
        if (!isDigit(this.peek)) this.error('Invalid exponent', -1);
        simple = false;
      } else {
        break;
      }
      this.advance();
    }
    var str: string = this.input.substring(start, this.index);
    // TODO
    var value: number =
        simple ? NumberWrapper.parseIntAutoRadix(str) : NumberWrapper.parseFloat(str);
    return newNumberToken(start, value);
  }

  scanString(): Token {
    var start: number = this.index;
    var quote: number = this.peek;
    this.advance();  // Skip initial quote.

    var buffer: StringJoiner;
    var marker: number = this.index;
    var input: string = this.input;

    while (this.peek != quote) {
      if (this.peek == $BACKSLASH) {
        if (buffer == null) buffer = new StringJoiner();
        buffer.add(input.substring(marker, this.index));
        this.advance();
        var unescapedCode: number;
        if (this.peek == $u) {
          // 4 character hex code for unicode character.
          var hex: string = input.substring(this.index + 1, this.index + 5);
          try {
            unescapedCode = NumberWrapper.parseInt(hex, 16);
          } catch (e) {
            this.error(`Invalid unicode escape [\\u${hex}]`, 0);
          }
          for (var i: number = 0; i < 5; i++) {
            this.advance();
          }
        } else {
          unescapedCode = unescape(this.peek);
          this.advance();
        }
        buffer.add(StringWrapper.fromCharCode(unescapedCode));
        marker = this.index;
      } else if (this.peek == $EOF) {
        this.error('Unterminated quote', 0);
      } else {
        this.advance();
      }
    }

    var last: string = input.substring(marker, this.index);
    this.advance();  // Skip terminating quote.

    // Compute the unescaped string value.
    var unescaped: string = last;
    if (buffer != null) {
      buffer.add(last);
      unescaped = buffer.toString();
    }
    return newStringToken(start, unescaped);
  }

  error(message: string, offset: number) {
    var position: number = this.index + offset;
    throw new ScannerError(
        `Lexer Error: ${message} at column ${position} in expression [${this.input}]`);
  }
}


export enum TokenType {
  Character,
  Identifier,
  Keyword,
  String,
  Operator,
  Number
}


tokenize(text: string): any[] {
    var scanner = new _Scanner(text);
    var tokens = [];
    var token = scanner.scanToken();
    while (token != null) {
      tokens.push(token);
      token = scanner.scanToken();
    }
    return tokens;
  }


isCharacter(code: number): boolean {
    return (this.type == TokenType.Character && this.numValue == code);
  }


isNumber(): boolean { return (this.type == TokenType.Number); }


isString(): boolean { return (this.type == TokenType.String); }


isOperator(operater: string): boolean {
    return (this.type == TokenType.Operator && this.strValue == operater);
  }


isIdentifier(): boolean { return (this.type == TokenType.Identifier); }


isKeyword(): boolean { return (this.type == TokenType.Keyword); }


isKeywordVar(): boolean { return (this.type == TokenType.Keyword && this.strValue == "var"); }


isKeywordNull(): boolean { return (this.type == TokenType.Keyword && this.strValue == "null"); }


isKeywordUndefined(): boolean {
    return (this.type == TokenType.Keyword && this.strValue == "undefined");
  }


isKeywordTrue(): boolean { return (this.type == TokenType.Keyword && this.strValue == "true"); }


isKeywordFalse(): boolean { return (this.type == TokenType.Keyword && this.strValue == "false"); }


toNumber(): number {
    // -1 instead of NULL ok?
    return (this.type == TokenType.Number) ? this.numValue : -1;
  }


toString(): string {
    switch (this.type) {
      case TokenType.Character:
      case TokenType.Identifier:
      case TokenType.Keyword:
      case TokenType.Operator:
      case TokenType.String:
        return this.strValue;
      case TokenType.Number:
        return this.numValue.toString();
      default:
        return null;
    }
  }


toString(): string { return this.message; }


advance() {
    this.peek =
        ++this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.input, this.index);
  }


scanToken(): Token {
    var input = this.input, length = this.length, peek = this.peek, index = this.index;

    // Skip whitespace.
    while (peek <= $SPACE) {
      if (++index >= length) {
        peek = $EOF;
        break;
      } else {
        peek = StringWrapper.charCodeAt(input, index);
      }
    }

    this.peek = peek;
    this.index = index;

    if (index >= length) {
      return null;
    }

    // Handle identifiers and numbers.
    if (isIdentifierStart(peek)) return this.scanIdentifier();
    if (isDigit(peek)) return this.scanNumber(index);

    var start: number = index;
    switch (peek) {
      case $PERIOD:
        this.advance();
        return isDigit(this.peek) ? this.scanNumber(start) : newCharacterToken(start, $PERIOD);
      case $LPAREN:
      case $RPAREN:
      case $LBRACE:
      case $RBRACE:
      case $LBRACKET:
      case $RBRACKET:
      case $COMMA:
      case $COLON:
      case $SEMICOLON:
        return this.scanCharacter(start, peek);
      case $SQ:
      case $DQ:
        return this.scanString();
      case $HASH:
      case $PLUS:
      case $MINUS:
      case $STAR:
      case $SLASH:
      case $PERCENT:
      case $CARET:
        return this.scanOperator(start, StringWrapper.fromCharCode(peek));
      case $QUESTION:
        return this.scanComplexOperator(start, '?', $PERIOD, '.');
      case $LT:
      case $GT:
        return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=');
      case $BANG:
      case $EQ:
        return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=', $EQ,
                                        '=');
      case $AMPERSAND:
        return this.scanComplexOperator(start, '&', $AMPERSAND, '&');
      case $BAR:
        return this.scanComplexOperator(start, '|', $BAR, '|');
      case $NBSP:
        while (isWhitespace(this.peek)) this.advance();
        return this.scanToken();
    }

    this.error(`Unexpected character [${StringWrapper.fromCharCode(peek)}]`, 0);
    return null;
  }


scanCharacter(start: number, code: number): Token {
    this.advance();
    return newCharacterToken(start, code);
  }


scanOperator(start: number, str: string): Token {
    this.advance();
    return newOperatorToken(start, str);
  }


/**
   * Tokenize a 2/3 char long operator
   *
   * @param start start index in the expression
   * @param one first symbol (always part of the operator)
   * @param twoCode code point for the second symbol
   * @param two second symbol (part of the operator when the second code point matches)
   * @param threeCode code point for the third symbol
   * @param three third symbol (part of the operator when provided and matches source expression)
   * @returns {Token}
   */
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
                      three?: string): Token {
    this.advance();
    var str: string = one;
    if (this.peek == twoCode) {
      this.advance();
      str += two;
    }
    if (isPresent(threeCode) && this.peek == threeCode) {
      this.advance();
      str += three;
    }
    return newOperatorToken(start, str);
  }


scanIdentifier(): Token {
    var start: number = this.index;
    this.advance();
    while (isIdentifierPart(this.peek)) this.advance();
    var str: string = this.input.substring(start, this.index);
    if (SetWrapper.has(KEYWORDS, str)) {
      return newKeywordToken(start, str);
    } else {
      return newIdentifierToken(start, str);
    }
  }


scanNumber(start: number): Token {
    var simple: boolean = (this.index === start);
    this.advance();  // Skip initial digit.
    while (true) {
      if (isDigit(this.peek)) {
        // Do nothing.
      } else if (this.peek == $PERIOD) {
        simple = false;
      } else if (isExponentStart(this.peek)) {
        this.advance();
        if (isExponentSign(this.peek)) this.advance();
        if (!isDigit(this.peek)) this.error('Invalid exponent', -1);
        simple = false;
      } else {
        break;
      }
      this.advance();
    }
    var str: string = this.input.substring(start, this.index);
    // TODO
    var value: number =
        simple ? NumberWrapper.parseIntAutoRadix(str) : NumberWrapper.parseFloat(str);
    return newNumberToken(start, value);
  }