text:
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Host from '../host/host.js';
import * as SDK from '../sdk/sdk.js';
import * as UI from '../ui/ui.js';

/**
 * @unrestricted
 */
export class SensorsView extends UI.Widget.VBox {
  constructor() {
    super(true);
    this.registerRequiredCSS('emulation/sensors.css');
    this.contentElement.classList.add('sensors-view');

    this._LocationSetting = Common.Settings.Settings.instance().createSetting('emulation.locationOverride', '');
    this._Location = SDK.EmulationModel.Location.parseSetting(this._LocationSetting.get());
    this._LocationOverrideEnabled = false;
    this._createLocationSection(this._Location);

    this.contentElement.createChild('div').classList.add('panel-section-separator');

    this._deviceOrientationSetting =
        Common.Settings.Settings.instance().createSetting('emulation.deviceOrientationOverride', '');
    this._deviceOrientation = SDK.EmulationModel.DeviceOrientation.parseSetting(this._deviceOrientationSetting.get());
    this._deviceOrientationOverrideEnabled = false;
    this._createDeviceOrientationSection();

    this.contentElement.createChild('div').classList.add('panel-section-separator');

    this._appendTouchControl();
  }

  /**
   * @return {!SensorsView}
   */
  static instance() {
    if (!SensorsView._instanceObject) {
      SensorsView._instanceObject = new SensorsView();
    }
    return SensorsView._instanceObject;
  }

  /**
   * @param {!SDK.EmulationModel.Location} location
   */
  _createLocationSection(location) {
    const geogroup = this.contentElement.createChild('section', 'sensors-group');
    const geogroupTitle = UI.UIUtils.createLabel(ls`Location`, 'sensors-group-title');
    geogroup.appendChild(geogroupTitle);
    const fields = geogroup.createChild('div', 'geo-fields');
    let selectedIndex = 0;

    const noOverrideOption = {title: Common.UIString.UIString('No override'), location: NonPresetOptions.NoOverride};

    this._locationSelectElement = fields.createChild('select', 'chrome-select');
    UI.ARIAUtils.bindLabelToControl(geogroupTitle, this._locationSelectElement);

    // No override
    this._locationSelectElement.appendChild(new Option(noOverrideOption.title, noOverrideOption.location));

    // Locations
    this._customLocationsGroup = this._locationSelectElement.createChild('optgroup');
    this._customLocationsGroup.label = ls`Overrides`;
    const customLocations = Common.Settings.Settings.instance().moduleSetting('emulation.locations');
    const manageButton = UI.UIUtils.createTextButton(ls`Manage`, () => Common.Revealer.reveal(customLocations));
    UI.ARIAUtils.setAccessibleName(manageButton, ls`Manage the list of locations`);
    fields.appendChild(manageButton);
    const fillCustomSettings = () => {
      this._customLocationsGroup.removeChildren();
      for (const [i, customLocation] of customLocations.get().entries()) {
        this._customLocationsGroup.appendChild(new Option(customLocation.title, JSON.stringify(customLocation)));
        if (location.latitude === customLocation.lat && location.longitude === customLocation.long) {
          // If the location coming from settings matches the custom location, use its index to select the option
          selectedIndex = i + 1;
        }
      }
    };
    customLocations.addChangeListener(fillCustomSettings);
    fillCustomSettings();

    // Other location
    const customLocationOption = {title: Common.UIString.UIString('Other…'), location: NonPresetOptions.Custom};
    this._locationSelectElement.appendChild(new Option(customLocationOption.title, customLocationOption.location));

    // Error location.
    const group = this._locationSelectElement.createChild('optgroup');
    group.label = ls`Error`;
    group.appendChild(new Option(ls`Location unavailable`, NonPresetOptions.Unavailable));

    this._locationSelectElement.selectedIndex = selectedIndex;
    this._locationSelectElement.addEventListener('change', this._LocationSelectChanged.bind(this));

    // Validated input fieldset.
    this._fieldsetElement = fields.createChild('fieldset');
    this._fieldsetElement.disabled = !this._LocationOverrideEnabled;
    this._fieldsetElement.id = 'location-override-section';

    const latitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group');
    const longitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group');
    const timezoneGroup = this._fieldsetElement.createChild('div', 'latlong-group');
    const localeGroup = this._fieldsetElement.createChild('div', 'latlong-group');

    const cmdOrCtrl = Host.Platform.isMac() ? '\u2318' : 'Ctrl';
    const modifierKeyMessage = ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`;

    this._latitudeInput = UI.UIUtils.createInput('', 'number');
    latitudeGroup.appendChild(this._latitudeInput);
    this._latitudeInput.setAttribute('step', 'any');
    this._latitudeInput.value = 0;
    this._latitudeSetter = UI.UIUtils.bindInput(
        this._latitudeInput, this._applyLocationUserInput.bind(this), SDK.EmulationModel.Location.latitudeValidator,
        true, 0.1);
    this._latitudeSetter(String(location.latitude));
    this._latitudeInput.title = modifierKeyMessage;
    latitudeGroup.appendChild(UI.UIUtils.createLabel(ls`Latitude`, 'latlong-title', this._latitudeInput));

    this._longitudeInput = UI.UIUtils.createInput('', 'number');
    longitudeGroup.appendChild(this._longitudeInput);
    this._longitudeInput.setAttribute('step', 'any');
    this._longitudeInput.value = 0;
    this._longitudeSetter = UI.UIUtils.bindInput(
        this._longitudeInput, this._applyLocationUserInput.bind(this), SDK.EmulationModel.Location.longitudeValidator,
        true, 0.1);
    this._longitudeSetter(String(location.longitude));
    this._longitudeInput.title = modifierKeyMessage;
    longitudeGroup.appendChild(UI.UIUtils.createLabel(ls`Longitude`, 'latlong-title', this._longitudeInput));

    this._timezoneInput = UI.UIUtils.createInput('', 'text');
    timezoneGroup.appendChild(this._timezoneInput);
    this._timezoneInput.value = 'Europe/Berlin';
    this._timezoneSetter = UI.UIUtils.bindInput(
        this._timezoneInput, this._applyLocationUserInput.bind(this), SDK.EmulationModel.Location.timezoneIdValidator,
        false);
    this._timezoneSetter(location.timezoneId);
    timezoneGroup.appendChild(UI.UIUtils.createLabel(ls`Timezone ID`, 'timezone-title', this._timezoneInput));
    this._timezoneError = timezoneGroup.createChild('div', 'timezone-error');

    this._localeInput = UI.UIUtils.createInput('', 'text');
    localeGroup.appendChild(this._localeInput);
    this._localeInput.value = 'en-US';
    this._localeSetter = UI.UIUtils.bindInput(
        this._localeInput, this._applyLocationUserInput.bind(this), SDK.EmulationModel.Location.localeValidator, false);
    this._localeSetter(location.locale);
    localeGroup.appendChild(UI.UIUtils.createLabel(ls`Locale`, 'locale-title', this._localeInput));
    this._localeError = localeGroup.createChild('div', 'locale-error');
  }

  _LocationSelectChanged() {
    this._fieldsetElement.disabled = false;
    this._timezoneError.textContent = '';
    const value = this._locationSelectElement.options[this._locationSelectElement.selectedIndex].value;
    if (value === NonPresetOptions.NoOverride) {
      this._LocationOverrideEnabled = false;
      this._clearFieldsetElementInputs();
      this._fieldsetElement.disabled = true;
    } else if (value === NonPresetOptions.Custom) {
      this._LocationOverrideEnabled = true;
      const location = SDK.EmulationModel.Location.parseUserInput(
          this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim(),
          this._localeInput.value.trim());
      if (!location) {
        return;
      }
      this._Location = location;
    } else if (value === NonPresetOptions.Unavailable) {
      this._LocationOverrideEnabled = true;
      this._Location = new SDK.EmulationModel.Location(0, 0, '', '', true);
    } else {
      this._LocationOverrideEnabled = true;
      const coordinates = JSON.parse(value);
      this._Location = new SDK.EmulationModel.Location(
          coordinates.lat, coordinates.long, coordinates.timezoneId, coordinates.locale, false);
      this._latitudeSetter(coordinates.lat);
      this._longitudeSetter(coordinates.long);
      this._timezoneSetter(coordinates.timezoneId);
      this._localeSetter(coordinates.locale);
    }

    this._applyLocation();
    if (value === NonPresetOptions.Custom) {
      this._latitudeInput.focus();
    }
  }

  _applyLocationUserInput() {
    const location = SDK.EmulationModel.Location.parseUserInput(
        this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim(),
        this._localeInput.value.trim());
    if (!location) {
      return;
    }

    this._timezoneError.textContent = '';

    this._setSelectElementLabel(this._locationSelectElement, NonPresetOptions.Custom);
    this._Location = location;
    this._applyLocation();
  }

  _applyLocation() {
    if (this._LocationOverrideEnabled) {
      this._LocationSetting.set(this._Location.toSetting());
    } else {
      this._LocationSetting.remove();
    }
    for (const emulationModel of SDK.SDKModel.TargetManager.instance().models(SDK.EmulationModel.EmulationModel)) {
      emulationModel.emulateLocation(this._LocationOverrideEnabled ? this._Location : null).catch(err => {
        switch (err.type) {
          case 'emulation-set-timezone': {
            this._timezoneError.textContent = err.message;
            break;
          }
          case 'emulation-set-locale': {
            this._localeError.textContent = err.message;
            break;
          }
        }
      });
    }
  }

  _clearFieldsetElementInputs() {
    this._latitudeSetter(0);
    this._longitudeSetter(0);
    this._timezoneSetter('');
    this._localeSetter('');
  }

  _createDeviceOrientationSection() {
    const orientationGroup = this.contentElement.createChild('section', 'sensors-group');
    const orientationTitle = UI.UIUtils.createLabel(ls`Orientation`, 'sensors-group-title');
    orientationGroup.appendChild(orientationTitle);
    const orientationContent = orientationGroup.createChild('div', 'orientation-content');
    const fields = orientationContent.createChild('div', 'orientation-fields');

    const orientationOffOption = {title: Common.UIString.UIString('Off'), orientation: NonPresetOptions.NoOverride};
    const customOrientationOption = {
      title: Common.UIString.UIString('Custom orientation'),
      orientation: NonPresetOptions.Custom,
    };
    this._orientationSelectElement = this.contentElement.createChild('select', 'chrome-select');
    UI.ARIAUtils.bindLabelToControl(orientationTitle, this._orientationSelectElement);
    this._orientationSelectElement.appendChild(
        new Option(orientationOffOption.title, orientationOffOption.orientation));
    this._orientationSelectElement.appendChild(
        new Option(customOrientationOption.title, customOrientationOption.orientation));

    const orientationGroups = PresetOrientations;
    for (let i = 0; i < orientationGroups.length; ++i) {
      const groupElement = this._orientationSelectElement.createChild('optgroup');
      groupElement.label = orientationGroups[i].title;
      const group = orientationGroups[i].value;
      for (let j = 0; j < group.length; ++j) {
        groupElement.appendChild(new Option(group[j].title, group[j].orientation));
      }
    }
    this._orientationSelectElement.selectedIndex = 0;
    fields.appendChild(this._orientationSelectElement);
    this._orientationSelectElement.addEventListener('change', this._orientationSelectChanged.bind(this));

    this._deviceOrientationFieldset = this._createDeviceOrientationOverrideElement(this._deviceOrientation);

    this._stageElement = orientationContent.createChild('div', 'orientation-stage');
    this._orientationLayer = this._stageElement.createChild('div', 'orientation-layer');
    this._boxElement = this._orientationLayer.createChild('section', 'orientation-box orientation-element');

    this._boxElement.createChild('section', 'orientation-front orientation-element');
    this._boxElement.createChild('section', 'orientation-top orientation-element');
    this._boxElement.createChild('section', 'orientation-back orientation-element');
    this._boxElement.createChild('section', 'orientation-left orientation-element');
    this._boxElement.createChild('section', 'orientation-right orientation-element');
    this._boxElement.createChild('section', 'orientation-bottom orientation-element');

    UI.UIUtils.installDragHandle(this._stageElement, this._onBoxDragStart.bind(this), event => {
      this._onBoxDrag(event);
    }, null, '-webkit-grabbing', '-webkit-grab');

    fields.appendChild(this._deviceOrientationFieldset);
    this._enableOrientationFields(true);
    this._setBoxOrientation(this._deviceOrientation, false);
  }

  /**
   * @param {?boolean} disable
   */
  _enableOrientationFields(disable) {
    if (disable) {
      this._deviceOrientationFieldset.disabled = true;
      this._stageElement.classList.add('disabled');
      this._stageElement.title = ls`Enable orientation to rotate`;
    } else {
      this._deviceOrientationFieldset.disabled = false;
      this._stageElement.classList.remove('disabled');
      this._stageElement.title = ls`Shift+drag horizontally to rotate around the y-axis`;
    }
  }

  _orientationSelectChanged() {
    const value = this._orientationSelectElement.options[this._orientationSelectElement.selectedIndex].value;
    this._enableOrientationFields(false);

    if (value === NonPresetOptions.NoOverride) {
      this._deviceOrientationOverrideEnabled = false;
      this._enableOrientationFields(true);
    } else if (value === NonPresetOptions.Custom) {
      this._deviceOrientationOverrideEnabled = true;
      this._alphaElement.focus();
    } else {
      const parsedValue = JSON.parse(value);
      this._deviceOrientationOverrideEnabled = true;
      this._deviceOrientation =
          new SDK.EmulationModel.DeviceOrientation(parsedValue[0], parsedValue[1], parsedValue[2]);
      this._setDeviceOrientation(this._deviceOrientation, DeviceOrientationModificationSource.SelectPreset);
    }
  }

  _applyDeviceOrientation() {
    if (this._deviceOrientationOverrideEnabled) {
      this._deviceOrientationSetting.set(this._deviceOrientation.toSetting());
    }
    for (const emulationModel of SDK.SDKModel.TargetManager.instance().models(SDK.EmulationModel.EmulationModel)) {
      emulationModel.emulateDeviceOrientation(this._deviceOrientationOverrideEnabled ? this._deviceOrientation : null);
    }
  }

  /**
   * @param {!Element} selectElement
   * @param {string} labelValue
   */
  _setSelectElementLabel(selectElement, labelValue) {
    const optionValues = Array.prototype.map.call(selectElement.options, x => x.value);
    selectElement.selectedIndex = optionValues.indexOf(labelValue);
  }

  _applyDeviceOrientationUserInput() {
    this._setDeviceOrientation(
        SDK.EmulationModel.DeviceOrientation.parseUserInput(
            this._alphaElement.value.trim(), this._betaElement.value.trim(), this._gammaElement.value.trim()),
        DeviceOrientationModificationSource.UserInput);
    this._setSelectElementLabel(this._orientationSelectElement, NonPresetOptions.Custom);
  }

  _resetDeviceOrientation() {
    this._setDeviceOrientation(
        new SDK.EmulationModel.DeviceOrientation(0, 90, 0), DeviceOrientationModificationSource.ResetButton);
    this._setSelectElementLabel(this._orientationSelectElement, '[0, 90, 0]');
  }

  /**
   * @param {?SDK.EmulationModel.DeviceOrientation} deviceOrientation
   * @param {!DeviceOrientationModificationSource} modificationSource
   */
  _setDeviceOrientation(deviceOrientation, modificationSource) {
    if (!deviceOrientation) {
      return;
    }

    /**
     * @param {number} angle
     * @return {number}
     */
    function roundAngle(angle) {
      return Math.round(angle * 10000) / 10000;
    }

    if (modificationSource !== DeviceOrientationModificationSource.UserInput) {
      this._alphaSetter(roundAngle(deviceOrientation.alpha));
      this._betaSetter(roundAngle(deviceOrientation.beta));
      this._gammaSetter(roundAngle(deviceOrientation.gamma));
    }

    const animate = modificationSource !== DeviceOrientationModificationSource.UserDrag;
    this._setBoxOrientation(deviceOrientation, animate);

    this._deviceOrientation = deviceOrientation;
    this._applyDeviceOrientation();

    UI.ARIAUtils.alert(
        ls`Device orientation set to alpha: ${deviceOrientation.alpha}, beta: ${deviceOrientation.beta}, gamma: ${
            deviceOrientation.gamma}`,
        this._orientationSelectElement);
  }

  /**
   * @param {!Element} parentElement
   * @param {!Element} input
   * @param {string} label
   * @return {function(string)}
   */
  _createAxisInput(parentElement, input, label) {
    const div = parentElement.createChild('div', 'orientation-axis-input-container');
    div.appendChild(input);
    div.appendChild(UI.UIUtils.createLabel(label, /* className */ '', input));
    input.type = 'number';
    return UI.UIUtils.bindInput(
        input, this._applyDeviceOrientationUserInput.bind(this), SDK.EmulationModel.DeviceOrientation.validator, true);
  }

  /**
   * @param {!SDK.EmulationModel.DeviceOrientation} deviceOrientation
   * @return {!Element}
   */
  _createDeviceOrientationOverrideElement(deviceOrientation) {
    const fieldsetElement = createElement('fieldset');
    fieldsetElement.classList.add('device-orientation-override-section');
    const cellElement = fieldsetElement.createChild('td', 'orientation-inputs-cell');

    this._alphaElement = UI.UIUtils.createInput();
    this._alphaElement.setAttribute('step', 'any');
    this._alphaSetter =
        this._createAxisInput(cellElement, this._alphaElement, Common.UIString.UIString('\u03B1 (alpha)'));
    this._alphaSetter(String(deviceOrientation.alpha));

    this._betaElement = UI.UIUtils.createInput();
    this._betaElement.setAttribute('step', 'any');
    this._betaSetter = this._createAxisInput(cellElement, this._betaElement, Common.UIString.UIString('\u03B2 (beta)'));
    this._betaSetter(String(deviceOrientation.beta));

    this._gammaElement = UI.UIUtils.createInput();
    this._gammaElement.setAttribute('step', 'any');
    this._gammaSetter =
        this._createAxisInput(cellElement, this._gammaElement, Common.UIString.UIString('\u03B3 (gamma)'));
    this._gammaSetter(String(deviceOrientation.gamma));

    const resetButton = UI.UIUtils.createTextButton(
        Common.UIString.UIString('Reset'), this._resetDeviceOrientation.bind(this), 'orientation-reset-button');
    UI.ARIAUtils.setAccessibleName(resetButton, ls`Reset device orientation`);
    resetButton.setAttribute('type', 'reset');
    cellElement.appendChild(resetButton);
    return fieldsetElement;
  }

  /**
   * @param {!SDK.EmulationModel.DeviceOrientation} deviceOrientation
   * @param {boolean} animate
   */
  _setBoxOrientation(deviceOrientation, animate) {
    if (animate) {
      this._stageElement.classList.add('is-animating');
    } else {
      this._stageElement.classList.remove('is-animating');
    }

    // The CSS transform should not depend on matrix3d, which does not interpolate well.
    const matrix = new WebKitCSSMatrix();
    this._boxMatrix = matrix.rotate(-deviceOrientation.beta, deviceOrientation.gamma, -deviceOrientation.alpha);
    const eulerAngles =
        new UI.Geometry.EulerAngles(deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma);
    this._orientationLayer.style.transform = eulerAngles.toRotate3DString();
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _onBoxDrag(event) {
    const mouseMoveVector = this._calculateRadiusVector(event.x, event.y);
    if (!mouseMoveVector) {
      return true;
    }

    event.consume(true);
    let axis, angle;
    if (event.shiftKey) {
      axis = new UI.Geometry.Vector(0, 0, -1);
      angle = (this._mouseDownVector.x - mouseMoveVector.x) * ShiftDragOrientationSpeed;
    } else {
      axis = UI.Geometry.crossProduct(this._mouseDownVector, mouseMoveVector);
      angle = UI.Geometry.calculateAngle(this._mouseDownVector, mouseMoveVector);
    }

    // The mouse movement vectors occur in the screen space, which is offset by 90 degrees from
    // the actual device orientation.
    let currentMatrix = new WebKitCSSMatrix();
    currentMatrix = currentMatrix.rotate(-90, 0, 0)
                        .rotateAxisAngle(axis.x, axis.y, axis.z, angle)
                        .rotate(90, 0, 0)
                        .multiply(this._originalBoxMatrix);

    const eulerAngles = UI.Geometry.EulerAngles.fromRotationMatrix(currentMatrix);
    const newOrientation =
        new SDK.EmulationModel.DeviceOrientation(-eulerAngles.alpha, -eulerAngles.beta, eulerAngles.gamma);
    this._setDeviceOrientation(newOrientation, DeviceOrientationModificationSource.UserDrag);
    this._setSelectElementLabel(this._orientationSelectElement, NonPresetOptions.Custom);
    return false;
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _onBoxDragStart(event) {
    if (!this._deviceOrientationOverrideEnabled) {
      return false;
    }

    this._mouseDownVector = this._calculateRadiusVector(event.x, event.y);
    this._originalBoxMatrix = this._boxMatrix;

    if (!this._mouseDownVector) {
      return false;
    }

    event.consume(true);
    return true;
  }

  /**
   * @param {number} x
   * @param {number} y
   * @return {?UI.Geometry.Vector}
   */
  _calculateRadiusVector(x, y) {
    const rect = this._stageElement.getBoundingClientRect();
    const radius = Math.max(rect.width, rect.height) / 2;
    const sphereX = (x - rect.left - rect.width / 2) / radius;
    const sphereY = (y - rect.top - rect.height / 2) / radius;
    const sqrSum = sphereX * sphereX + sphereY * sphereY;
    if (sqrSum > 0.5) {
      return new UI.Geometry.Vector(sphereX, sphereY, 0.5 / Math.sqrt(sqrSum));
    }

    return new UI.Geometry.Vector(sphereX, sphereY, Math.sqrt(1 - sqrSum));
  }

  _appendTouchControl() {
    const groupElement = this.contentElement.createChild('div', 'sensors-group');
    const title = UI.UIUtils.createLabel(ls`Touch`, 'sensors-group-title');
    groupElement.appendChild(title);
    const fieldsElement = groupElement.createChild('div', 'sensors-group-fields');

    const select = fieldsElement.createChild('select', 'chrome-select');
    UI.ARIAUtils.bindLabelToControl(title, select);
    select.appendChild(new Option(Common.UIString.UIString('Device-based'), 'auto'));
    select.appendChild(new Option(Common.UIString.UIString('Force enabled'), 'enabled'));
    select.addEventListener('change', applyTouch, false);

    const reloadWarning = groupElement.createChild('div', 'reload-warning hidden');
    reloadWarning.textContent = Common.UIString.UIString('*Requires reload');
    UI.ARIAUtils.markAsAlert(reloadWarning);

    function applyTouch() {
      for (const emulationModel of SDK.SDKModel.TargetManager.instance().models(SDK.EmulationModel.EmulationModel)) {
        emulationModel.overrideEmulateTouch(select.value === 'enabled');
      }
      reloadWarning.classList.remove('hidden');
      const resourceTreeModel =
          SDK.SDKModel.TargetManager.instance().models(SDK.ResourceTreeModel.ResourceTreeModel)[0];
      if (resourceTreeModel) {
        resourceTreeModel.once(SDK.ResourceTreeModel.Events.MainFrameNavigated)
            .then(() => reloadWarning.classList.add('hidden'));
      }
    }
  }
}

/** @enum {string} */
export const DeviceOrientationModificationSource = {
  UserInput: 'userInput',
  UserDrag: 'userDrag',
  ResetButton: 'resetButton',
  SelectPreset: 'selectPreset'
};

/** {string} */
export const NonPresetOptions = {
  NoOverride: 'noOverride',
  Custom: 'custom',
  Unavailable: 'unavailable'
};

/** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */
export const PresetOrientations = [{
  title: ls`Presets`,
  value: [
    {title: Common.UIString.UIString('Portrait'), orientation: '[0, 90, 0]'},
    {title: Common.UIString.UIString('Portrait upside down'), orientation: '[180, -90, 0]'},
    {title: Common.UIString.UIString('Landscape left'), orientation: '[0, 90, -90]'},
    {title: Common.UIString.UIString('Landscape right'), orientation: '[0, 90, 90]'},
    {title: Common.UIString.UIString('Display up'), orientation: '[0, 0, 0]'},
    {title: Common.UIString.UIString('Display down'), orientation: '[0, 180, 0]'}
  ]
}];

/**
 * @implements {UI.ActionDelegate.ActionDelegate}
 * @unrestricted
 */
export class ShowActionDelegate {
  /**
   * @override
   * @param {!UI.Context.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    UI.ViewManager.ViewManager.instance().showView('sensors');
    return true;
  }
}

export const ShiftDragOrientationSpeed = 16;


text:
.class public Lcom/sec/android/app/CscFeatureTagGPS;
.super Ljava/lang/Object;
.source "CscFeatureTagGPS.java"

# static fields
.field public static final Bool_NoTag:Z = false

.field public static final Int_NoTag:I = 0x0

.field public static final Str_NoTag:Ljava/lang/String; = ""

.field public static final TAG_CSCFEATURE_GPS_CONFIGAGNSSPROTOCOL:Ljava/lang/String; = "CscFeature_GPS_ConfigAgnssProtocol"

.field public static final TAG_CSCFEATURE_GPS_CONFIGAGPSMODE:Ljava/lang/String; = "CscFeature_GPS_ConfigAgpsMode"

.field public static final TAG_CSCFEATURE_GPS_CONFIGAGPSSETTING:Ljava/lang/String; = "CscFeature_GPS_ConfigAgpsSetting"

.field public static final TAG_CSCFEATURE_GPS_CONFIGGPFD:Ljava/lang/String; = "CscFeature_GPS_ConfigGPFD"

.field public static final TAG_CSCFEATURE_GPS_CONFIGLPPPROFILE:Ljava/lang/String; = "CscFeature_GPS_ConfigLppProfile"

.field public static final TAG_CSCFEATURE_GPS_CONFIGOPERATIONMODE:Ljava/lang/String; = "CscFeature_GPS_ConfigOperationMode"

.field public static final TAG_CSCFEATURE_GPS_CONFIGSUPLHOST:Ljava/lang/String; = "CscFeature_GPS_ConfigSuplHost"

.field public static final TAG_CSCFEATURE_GPS_CONFIGSUPLVERSION:Ljava/lang/String; = "CscFeature_GPS_ConfigSuplVersion"

.field public static final TAG_CSCFEATURE_GPS_DISABLECSCALL:Ljava/lang/String; = "CscFeature_GPS_DisableCsCall"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTAGNSS:Ljava/lang/String; = "CscFeature_GPS_SupportAgnss"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTAPQONLY:Ljava/lang/String; = "CscFeature_GPS_SupportApqOnly"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTGOOGLESUPL2:Ljava/lang/String; = "CscFeature_GPS_SupportGoogleSupl2"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTGTP:Ljava/lang/String; = "CscFeature_GPS_SupportGTP"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTLPPCPONLY:Ljava/lang/String; = "CscFeature_GPS_SupportLppCpOnly"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTLPPCPUP:Ljava/lang/String; = "CscFeature_GPS_SupportLppCpUp"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTLPPUPONLY:Ljava/lang/String; = "CscFeature_GPS_SupportLppUpOnly"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTPRIVACYLOCK:Ljava/lang/String; = "CscFeature_GPS_SupportPrivacyLock"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTSUPL:Ljava/lang/String; = "CscFeature_GPS_SupportSupl"

.field public static final TAG_CSCFEATURE_GPS_SUPPORTTENCENTNLP:Ljava/lang/String; = "CscFeature_GPS_SupportTencentNLP"

# direct methods
.method public constructor <init>()V
    .locals 0

    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method

redpajama_set_name: RedPajamaGithub


text:
package liquid.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

/**
 * Created by Tao Ma on 5/27/15.
 */
@Controller
public class EndpointController {

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @RequestMapping(value = "/endpoint", method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("handlerMethods", requestMappingHandlerMapping.getHandlerMethods());
        return "endpoint";
    }
}


text:
package com.shaojun.utils.plog.formatter;

import android.text.TextUtils;

import com.shaojun.utils.plog.util.ObjectUtil;

/**
 * This class just formats msg
 * Created by muyangmin on Sep 09, 2016.
 *
 * @author muyangmin
 * @since 1.5.0
 */
public class StringFormatter implements Formatter {

    //For empty message but with object params
    private ObjectFormatter FMT_OBJECT = new ObjectFormatter();

    @Override
    public String format(String msg, Object... params) throws Exception {
        if (TextUtils.isEmpty(msg)) {
            if (params == null || params.length == 0) {
                throw new IllegalArgumentException("Neither msg nor params provided!");
            }
            return FMT_OBJECT.format(msg, params);
        }
        Object[] objects = new Object[params.length];
        for (int i = 0; i < params.length; i++) {
            Object obj = params[i];
            //Wrapper classes shouldn't change to String, because maybe we need format numbers;
            // e.g %.2f
            if (obj instanceof Boolean || obj instanceof Byte || obj instanceof Short
                    || obj instanceof Integer || obj instanceof Long || obj instanceof Float
                    || obj instanceof Double) { //Void is useless
                objects[i] = obj;
            } else {
                objects[i] = ObjectUtil.objectToString(params[i]);
            }
        }
        return String.format(msg, objects);
    }

    @Override
    public boolean isPreWrappedFormat() {
        return false;
    }
}


text:
(function () {
    var div = document.createElement("div");
    div.innerHTML = "Redirecting to website in 2 seconds";
    document.body.appendChild(div);
    var promise = new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(window.location = "http://www.tutorialspoint.com");
            // reject('something very bad happened')
        }, 2000);
    });

    spromise
        .then(function (data) {
            console.log(data);
        })
        .catch(function (error) {
            console.log(error);
        });
} ());


text:
var mainForm = document.getElementById("main-form");
mainForm.addEventListener("submit", function (event) {
event.preventDefault();
if (document.getElementById("username").value === "") {
alert("Username Harus di Isi!");
return false;
}
else if (document.getElementById("password").value === "") {
alert("Password Tidak Boleh Kosong!");
return false;
}
else if (document.getElementById("confirmpassword").value == "") {
alert("Konfirmasi Password Tidak Boleh Kosong!");
return false;
}
else if (document.getElementById("email").value === "") {
alert("Email Harus di Isi!");
return false;
}
else if (document.getElementById("confirmemail").value === "") {
alert("Konfirmasi Email Tidak Boleh Kosong!");
return false;
}
else if (document.getElementById("password").value != document.getElementById("confirmpassword").value) {
alert("Password dan Konfirmasi Password Harus di Isi Sama.");
return false;
}
else if (document.getElementById("email").value != document.getElementById("confirmemail").value) {
alert("Email dan Konfirmasi Email Harus di Isi Sama.");
return false;
}
else if (document.getElementById("username").value.length < 5) {
alert("Jumlah Karakter Username Minimal 5!");
return false;
}
else if (document.getElementById("password").value.length < 6) {
alert("Jumlah Karakter Password Minimal 6!");
return false;
}else{
document.getElementById("main-form").innerHTML = "Selamat, registrasi anda telah berhasil!";
document.getElementById("main-form").innerHTML += "
" + "
" + "Kembali ke halaman " + "sebelumnya";
return true;
}
});


text:
import string
from random import shuffle
from itertools import *
from math import *

def word14(wordlist):
    len14 = 0
    for word in wordlist:
        wordlength = len(word)
        if wordlength == 14:
            len14 += 1
    print("1 Number of words with 14 letters is: ", len14)

def wordlength(wordlist):
    longest = 0
    for word in wordlist:
        length_word = len(word)
        if length_word > longest:
            longest = len(word)
    return longest

def longestword(wordlist):
    longest = wordlength(wordlist)
    for word in wordlist:
        length_word = len(word)
        if length_word == longest:
            print("2 Longest word: ", word)

def fjword(wordlist):
    fjcount = 0
    for word in wordlist:
        if 'fj' in word:
            fjcount += 1
            print("Word with 'fj': ", word)
    if fjcount == 0:
        print("3 There is no 'fj' word.")

def fandj(wordlist):
    for word in wordlist:
        if 'f' in word and 'j' in word:
            print("4 Word with f and j: ",word)
        else:
            break
    print("4 There is no word with f and j.")

def fiveE(wordlist):
    for word in wordlist:
        countE = word.count('e')
        if countE >= 5:
            print("5 Word contains at least 5 'e's: ", word)

def vowels(wordlist):
    for word in wordlist:
        if 'a' in word and 'e' in word \
        and 'i' in word and 'o' in word and 'u' in word:
            print("6 Word with all vowels: ", word)

def returnhexword(word):
    for i in word:
        if i in string.hexdigits:
            continue
        if i not in string.hexdigits:
            return
    return word

def hexword(wordlist):
    hexhead = '0x'
    maxvalue = 0
    for word in wordlist:
        tail = returnhexword(word)
        if tail == None:
            continue
        else:
            hexcode = hexhead + word
            hexval = eval(hexcode)
            if hexval > maxvalue:
                maxvalue = hexval
    actualword = hex(maxvalue)
    realword = actualword[2:]
    print("7 The biggest letter is: ", realword)

def read_file():
    textfile = open("allTheWords.txt", 'r')
    readfile = textfile.read()
    wordlist = readfile.split()
    word14(wordlist)
    longestword(wordlist)
    fjword(wordlist)
    fandj(wordlist)
    fiveE(wordlist)
    vowels(wordlist)
    hexword(wordlist)

#precondition: alphabet letters only, no space, symbol or special characters
def dailyjumble2():
    textfile = open("allTheWords.txt", 'r')
    readfile = textfile.read()
    wordlist = readfile.split()
    letters = input("Please enter your string without space and symbol: ")
    for i in letters:
        if i not in string.ascii_letters:
            print("You did not follow instruction.")
            break
    letters = list(letters)
    print(letters)
    length_word = len(letters)
    shuffletime = factorial(length_word)
    print("Number of permutations:" , shuffletime)
    for i in range(shuffletime):
        letters = list(letters)
        shuffle(letters)
        letters = ''.join(letters)
        if letters in wordlist:
            print(letters)
        else:
            continue

#precondition: enter letters with comas in between
#no space between comas and letters
def final_dailyjumble():
    firstword = []
    secondword = []
    textfile = open("allTheWords.txt", 'r')
    readfile = textfile.read()
    wordlist = readfile.split()
    input_word = input("Please enter your letters, separated with comas, no space: ")
    input_length = len(input_word)
    input_word = input_word.split(',')
    print(input_word)
    for i in input_word:
        if i not in string.ascii_letters:
            print("You did not follow instruction.")
            break
    print(input_word)
    firstword_length = input("What's the first word's length?")
    firstword_length = eval(firstword_length)
    permute_word = int(factorial(input_length))
    permute_firstword = factorial(input_length)//factorial(input_length - firstword_length)
    permute_firstword = int(permute_firstword)
    permute_secondword = factorial(input_length)//factorial(firstword_length)
    permute_secondword = int(permute_secondword)
    for i in range(permute_word):        #substitute 100 with permute_firstword to see all results
        shuffle(input_word)
        a = input_word
        #print(input_word)
        #print(lt1)
        solution1 = ''.join(a)
        lt1 = input_word[:firstword_length]
        lt2 = input_word[firstword_length:]
        if (lt1 in wordlist) and (lt2 in wordlist):
           print("Solutions for the word is: ", lt1, lt2)
        else:
            continue

#read_file()
dailyjumble2()
dailyjumble2()
dailyjumble2()
dailyjumble2()
#final_dailyjumble()


text:
require 'addressable/uri'
require 'addressable/template'
require 'google/apis/core/http_command'
require 'google/apis/errors'
require 'json'
require 'retriable'
require "securerandom"

module Google
  module Apis
    module Core
      # Command for executing most basic API request with JSON requests/responses
      class ApiCommand < HttpCommand
        JSON_CONTENT_TYPE = 'application/json'
        FIELDS_PARAM = 'fields'
        ERROR_REASON_MAPPING = {
          'rateLimitExceeded' => Google::Apis::RateLimitError,
          'userRateLimitExceeded' => Google::Apis::RateLimitError,
          'projectNotLinked' => Google::Apis::ProjectNotLinkedError
        }

        # JSON serializer for request objects
        # @return [Google::Apis::Core::JsonRepresentation]
        attr_accessor :request_representation

        # Request body to serialize
        # @return [Object]
        attr_accessor :request_object

        # JSON serializer for response objects
        # @return [Google::Apis::Core::JsonRepresentation]
        attr_accessor :response_representation

        # Class to instantiate when de-serializing responses
        # @return [Object]
        attr_accessor :response_class

        # Client library version.
        # @return [String]
        attr_accessor :client_version

        # @param [symbol] method
        #   HTTP method
        # @param [String,Addressable::URI, Addressable::Template] url
        #   HTTP URL or template
        # @param [String, #read] body
        #   Request body
        def initialize(method, url, body: nil, client_version: nil)
          super(method, url, body: body)
          self.client_version = client_version || Core::VERSION
        end

        # Serialize the request body
        #
        # @return [void]
        def prepare!
          set_api_client_header
          set_user_project_header
          if options&.api_format_version
            header['X-Goog-Api-Format-Version'] = options.api_format_version.to_s
          end
          query[FIELDS_PARAM] = normalize_fields_param(query[FIELDS_PARAM]) if query.key?(FIELDS_PARAM)
          if request_representation && request_object
            header['Content-Type'] ||= JSON_CONTENT_TYPE
            if options && options.skip_serialization
              self.body = request_object
            else
              self.body = request_representation.new(request_object).to_json(user_options: { skip_undefined: true })
            end
          end
          super
        end

        # Deserialize the response body if present
        #
        # @param [String] content_type
        #  Content type of body
        # @param [String, #read] body
        #  Response body
        # @return [Object]
        #   Response object
        # noinspection RubyUnusedLocalVariable
        def decode_response_body(content_type, body)
          return super unless response_representation
          return super if options && options.skip_deserialization
          return super if content_type.nil?
          return nil unless content_type.start_with?(JSON_CONTENT_TYPE)
          body = "{}" if body.empty?
          instance = response_class.new
          response_representation.new(instance).from_json(body, unwrap: response_class)
          instance
        end

        # Check the response and raise error if needed
        #
        # @param [Fixnum] status
        #   HTTP status code of response
        # @param [Hash] header
        #   HTTP response headers
        # @param [String] body
        #   HTTP response body
        # @param [String] message
        #   Error message text
        # @return [void]
        # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
        # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
        # @raise [Google::Apis::AuthorizationError] Authorization is required
        def check_status(status, header = nil, body = nil, message = nil)
          case status
          when 400, 402...500
            reason, message = parse_error(body)
            if reason
              message = sprintf('%s: %s', reason, message)
              raise ERROR_REASON_MAPPING[reason].new(
                message,
                status_code: status,
                header: header,
                body: body
              ) if ERROR_REASON_MAPPING.key?(reason)
            end
            super(status, header, body, message)
          else
            super(status, header, body, message)
          end
        end

        def allow_form_encoding?
          request_representation.nil? && super
        end

        private

        def set_api_client_header
          old_xgac = header
            .find_all { |k, v| k.downcase == 'x-goog-api-client' }
            .map { |(a, b)| b }
            .join(' ')
            .split
            .find_all { |s| s !~ %r{^gl-ruby/|^gdcl/} }
            .join(' ')
          # Report 0.x.y versions that are in separate packages as 1.x.y.
          # Thus, reported gdcl/0.x.y versions are monopackage clients, while
          # reported gdcl/1.x.y versions are split clients.
          # In the unlikely event that we want to release post-1.0 versions of
          # these clients, we should start the versioning at 2.0 to avoid
          # confusion.
          munged_client_version = client_version.sub(/^0\./, "1.")
          xgac = "gl-ruby/#{RUBY_VERSION} gdcl/#{munged_client_version}"
          xgac = old_xgac.empty? ? xgac : "#{old_xgac} #{xgac}"
          header.delete_if { |k, v| k.downcase == 'x-goog-api-client' }
          xgac.concat(" ",invocation_id_header) if options.add_invocation_id_header
          header['X-Goog-Api-Client'] = xgac
        end

        def set_user_project_header
          quota_project_id = options.quota_project
          if !quota_project_id && options&.authorization.respond_to?(:quota_project_id)
            quota_project_id = options.authorization.quota_project_id
          end
          header['X-Goog-User-Project'] = quota_project_id if quota_project_id
        end

        def invocation_id_header
          "gccl-invocation-id/#{SecureRandom.uuid}"
        end

        # Attempt to parse a JSON error message
        # @param [String] body
        #  HTTP response body
        # @return [Array<(String, String)>]
        #   Error reason and message
        def parse_error(body)
          obj = JSON.load(body)
          error = obj['error']
          if error['details']
            return extract_v2_error_details(error)
          elsif error['errors']
            return extract_v1_error_details(error)
          else
            fail 'Can not parse error message. No "details" or "errors" detected'
          end
        rescue
          return [nil, nil]
        end

        # Extracts details from a v1 error message
        # @param [Hash] error
        #  Parsed JSON
        # @return [Array<(String, String)>]
        #   Error reason and message
        def extract_v1_error_details(error)
          reason = error['errors'].first['reason']
          message = error['message']
          return [reason, message]
        end

        # Extracts details from a v2error message
        # @param [Hash] error
        #  Parsed JSON
        # @return [Array<(String, String)>]
        #   Error reason and message
        def extract_v2_error_details(error)
          reason = error['status']
          message = error['message']
          return [reason, message]
        end

        # Convert field names from ruby conventions to original names in JSON
        #
        # @param [String] fields
        #   Value of 'fields' param
        # @return [String]
        #   Updated header value
        def normalize_fields_param(fields)
          # TODO: Generate map of parameter names during code gen. Small possibility that camelization fails
          fields.gsub(/:/, '').gsub(/\w+/) do |str|
            str.gsub(/(?:^|_)([a-z])/){ Regexp.last_match.begin(0) == 0 ? $1 : $1.upcase }
          end
        end
      end
    end
  end
end


text:
declare module Adaptive {
    /**
       @enum {Adaptive.IMessagingCallbackError} Adaptive.IMessagingCallbackError
       Enumeration IMessagingCallbackError
    */
    class IMessagingCallbackError {
        value: string;
        constructor(value: string);
        toString(): string;
        /**
           @property {Adaptive.IMessagingCallbackError} [SIMNotPresent='SIMNotPresent']
        */
        static SIMNotPresent: IMessagingCallbackError;
        /**
           @property {Adaptive.IMessagingCallbackError} [EmailAccountNotFound='EmailAccountNotFound']
        */
        static EmailAccountNotFound: IMessagingCallbackError;
        /**
           @property {Adaptive.IMessagingCallbackError} [NotSent='NotSent']
        */
        static NotSent: IMessagingCallbackError;
        /**
           @property {Adaptive.IMessagingCallbackError} [WrongParams='WrongParams']
        */
        static WrongParams: IMessagingCallbackError;
        /**
           @property {Adaptive.IMessagingCallbackError} [NotSupported='NotSupported']
        */
        static NotSupported: IMessagingCallbackError;
        /**
           @property {Adaptive.IMessagingCallbackError} [Unknown='Unknown']
        */
        static Unknown: IMessagingCallbackError;
        /**
           @method
           @static
           Convert JSON parsed object to enumeration.
           @return {Adaptive.IMessagingCallbackError}
        */
        static toObject(object: any): IMessagingCallbackError;
    }
}


text:
<?php

namespace Analog;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Psr\Log\InvalidArgumentException;

/**
 * Implements the PSR-3 standard as a wrapper to Analog. For more information,
 * see:
 *
 * https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 *
 * Usage:
 *
 *     <?php
 *
 *     require_once ('vendor/autoload.php');
 *
 *     $log = new Analog\Logger ();
 *
 *     $log->notice ('Things are really happening right now.');
 *
 *     ?>
 *
 * @package Analog
 * @author Johnny Broadway
 */
class Logger implements LoggerInterface {
	/**
	 * Converts from PSR-3 log levels to Analog log levels.
	 */
	public function convert_log_level ($level, $reverse = false) {
		if ($reverse) {
			switch ($level) {
				case Analog::URGENT:
					return LogLevel::EMERGENCY;
				case Analog::ALERT:
					return LogLevel::ALERT;
				case Analog::CRITICAL:
					return LogLevel::CRITICAL;
				case Analog::ERROR:
					return LogLevel::ERROR;
				case Analog::WARNING:
					return LogLevel::WARNING;
				case Analog::NOTICE:
					return LogLevel::NOTICE;
				case Analog::INFO:
					return LogLevel::INFO;
				case Analog::DEBUG:
					return LogLevel::DEBUG;
			}
			throw new InvalidArgumentException ('Level "' . $level . '" is not defined.');
		} else {
			switch ($level) {
				case LogLevel::EMERGENCY:
					return Analog::URGENT;
				case LogLevel::ALERT:
					return Analog::ALERT;
				case LogLevel::CRITICAL:
					return Analog::CRITICAL;
				case LogLevel::ERROR:
					return Analog::ERROR;
				case LogLevel::WARNING:
					return Analog::WARNING;
				case LogLevel::NOTICE:
					return Analog::NOTICE;
				case LogLevel::INFO:
					return Analog::INFO;
				case LogLevel::DEBUG:
					return Analog::DEBUG;
			}
			throw new InvalidArgumentException ('Level "' . $level . '" is not defined.');
		}
	}

	/**
	 * Interpolates context values into the message placeholders.
	 */
	private function interpolate ($message, array $context = array ()) {
		if (is_array ($message)) {
			return $message;
		}

		// build a replacement array with braces around the context keys
		$replace = array ();
		foreach ($context as $key => $val) {
			if (is_object ($val) && get_class ($val) === 'DateTime') {
				$val = $val->format ('Y-m-d H:i:s');
			} elseif (is_object ($val)) {
				$val = json_encode ($val);
			} elseif (is_array ($val)) {
				$val = json_encode ($val);
			} elseif (is_resource ($val)) {
				$val = (string) $val;
			}
			$replace['{' . $key . '}'] = $val;
		}

		// interpolate replacement values into the the message and return
		return strtr ($message, $replace);
	}

	/**
	 * Sets the Analog log handler.
	 */
	public function handler ($handler) {
		Analog::handler ($handler);
	}

	/**
	 * Sets the log message format.
	 */
	public function format ($format) {
		Analog::$format = $format;
	}

	/**
	 * System is unusable.
	 */
	public function emergency ($message, array $context = array ()) {
		$this->_log (Analog::URGENT, $message, $context);
	}

	/**
	 * Action must be taken immediately.
	 */
	public function alert ($message, array $context = array ()) {
		$this->_log (Analog::ALERT, $message, $context);
	}

	/**
	 * Critical conditions.
	 */
	public function critical ($message, array $context = array ()) {
		$this->_log (Analog::CRITICAL, $message, $context);
	}

	/**
	 * Runtime errors that do not require immediate action but should typically
	 * be logged and monitored.
	 */
	public function error ($message, array $context = array ()) {
		$this->_log (Analog::ERROR, $message, $context);
	}

	/**
	 * Exceptional occurrences that are not errors.
	 */
	public function warning ($message, array $context = array ()) {
		$this->_log (Analog::WARNING, $message, $context);
	}

	/**
	 * Normal but significant events.
	 */
	public function notice ($message, array $context = array ()) {
		$this->_log (Analog::NOTICE, $message, $context);
	}

	/**
	 * Interesting events.
	 */
	public function info ($message, array $context = array ()) {
		$this->_log (Analog::INFO, $message, $context);
	}

	/**
	 * Detailed debug information.
	 */
	public function debug ($message, array $context = array ()) {
		$this->_log (Analog::DEBUG, $message, $context);
	}

	/**
	 * Logs with an arbitrary level.
	 */
	public function log ($level, $message, array $context = array ()) {
		$this->_log (
			$this->convert_log_level ($level),
			$message,
			$context
		);
	}

	/**
	 * Perform the logging to Analog after the log level has been converted.
	 */
	private function _log ($level, $message, $context) {
		Analog::log (
			$this->interpolate ($message, $context),
			$level
		);
	}
}


text:
typedef NS_ENUM(NSInteger, YHObjectType) {
    YHObjectTypeUnknow,  // 未知
    YHObjectTypeNil,     // Nil
    YHObjectTypeNumber,  // 基本数据类型
    YHObjectTypeString,  // NSString
    YHObjectTypeArray    // 数组Array
};

// 操作符类型
typedef NS_ENUM(NSInteger, YHOperatorType) {
    YHOperatorTypeEq,       // =
    YHOperatorTypeNotEq,    // !=
    YHOperatorTypeGt,       // >
    YHOperatorTypeGtAndEq,  // >=
    YHOperatorTypeLt,       // <
    YHOperatorTypeLtAndEq,  // <=
    YHOperatorTypeLk,       // like
    YHOperatorTypeNotLk,    // not like
    YHOperatorTypeIn,       // in
    YHOperatorTypeNotIn,    // not in
    YHOperatorTypeAnd,      // and
    YHOperatorTypeOr        // or
};

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
// limit
static NSString *limit(NSNumber *value) { return [NSString stringWithFormat:@"LIMIT %@", value]; }

// order by
static NSString *order_by(NSString *col, ...) {
    if (!col) {
        return @"";
    }
    NSMutableArray *argsArray = @[].mutableCopy;
    va_list params;         //定义一个指向个数可变的参数列表指针;
    va_start(params, col);  // va_start 得到第一个可变参数地址,
    id arg;
    //将第一个参数添加到array
    id prev = col;
    [argsArray addObject:prev];
    // va_arg 指向下一个参数地址
    while ((arg = va_arg(params, id))) {
        if (arg) {
            [argsArray addObject:arg];
        }
    }
    //置空
    va_end(params);
    return [NSString stringWithFormat:@"ORDER BY %@", [argsArray componentsJoinedByString:@","]];
}

#pragma clang diagnostic pop

@interface NSString (SQL)

// =  equal
- (NSString * (^)(NSObject *value))eq;

// !=
- (NSString * (^)(NSObject *value)) not_eq ;

// >  gt  greater than
- (NSString * (^)(NSObject *value))gt;

// >=
- (NSString * (^)(NSObject *value))gt_and_eq;

// <  lt  less than
- (NSString * (^)(NSObject *value))lt;

// <=
- (NSString * (^)(NSObject *value))lt_and_eq;

// between and
- (NSString * (^)(NSArray *values))btw_and;

// not between and
- (NSString * (^)(NSArray *values))not_btw_and;

// is not null
- (NSString * (^)())is_not_null;

// is null
- (NSString * (^)())is_null;

// like
- (NSString * (^)(NSString *value))lk;

// not like
- (NSString * (^)(NSString *value))not_lk;

// in
- (NSString * (^)(NSObject *value))in;

// not in
- (NSString * (^)(NSObject *value))not_in;

// and
- (NSString * (^)(NSString *value))AND;

// or
- (NSString * (^)(NSString *value))OR;

// desc
- (NSString * (^)())desc;

// asc
- (NSString * (^)())asc;

// offset
- (NSString * (^)(NSNumber *offset))offset;

@end

@interface NSString (FMDBHelper)

#pragma mark 工具方法

// 生成UUID
+ (NSString *)generateUUID;

// 是否空字符串
+ (BOOL)isEmpty:(NSString *)string;

@end


text:
class I2p < Formula
  desc "Anonymous overlay network - a network within a network"
  homepage "https://geti2p.net"
  url "https://download.i2p2.de/releases/0.9.31/i2pinstall_0.9.31.jar"
  sha256 "dc26fb5c268dfe63b98bce66381c24c908f0b8265ddf731f4daf6fb82c4b7376"

  bottle :unneeded

  depends_on :java => "1.6+"

  def install
    (buildpath/"path.conf").write "INSTALL_PATH=#{libexec}"

    system "java", "-jar", "i2pinstall_#{version}.jar", "-options", "path.conf"

    wrapper_name = "i2psvc-macosx-universal-#{MacOS.prefer_64_bit? ? 64 : 32}"
    libexec.install_symlink libexec/wrapper_name => "i2psvc"
    bin.write_exec_script Dir["#{libexec}/{eepget,i2prouter}"]
    man1.install Dir["#{libexec}/man/*"]
  end

  test do
    assert_match "I2P Service is not running.", shell_output("#{bin}/i2prouter status", 1)
  end
end


text:
class Game;
class MapRendering;
class Renderer;

class InGameState : public AppState
{
public:
    InGameState();

    virtual bool initialize() override;
    virtual void deinitialize() override;

    virtual bool onKeyboardEvent(int key, int action, int mods) override;

    virtual void beginFrame() override;
    virtual void update(uint32_t dt) override;
    virtual void render() override;
    virtual void endFrame() override;

private:
    Game* m_game = nullptr;
    MapRendering* m_mapRendering = nullptr;
    yama::point3 m_camPos;
    yama::point3 m_camTarget;
    yama::point2 m_camMoveWeight;

    std::unique_ptr<Renderer> m_renderer;
};


text:
package org.gradle.api.specs;

/**
 * Represents some predicate against objects of type T.
 *
 * @param <T> The target type for this Spec
 */
public interface Spec<T> {
    boolean isSatisfiedBy(T element);
}


text:
module Killbill #:nodoc:
  module Yandex #:nodoc:
    class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin

      def initialize
        gateway_builder = Proc.new do |config|
          # Not supported
          nil
        end

        super(gateway_builder,
              :yandex,
              ::Killbill::Yandex::YandexPaymentMethod,
              ::Killbill::Yandex::YandexTransaction,
              ::Killbill::Yandex::YandexResponse)
      end

      def authorize_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
        # Pass extra parameters for the gateway here
        options = {}

        properties = merge_properties(properties, options)
        super(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
      end

      def capture_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
        # Pass extra parameters for the gateway here
        options = {}

        properties = merge_properties(properties, options)
        super(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
      end

      def void_payment(kb_account_id, kb_payment_id, kb_payment_method_id, properties, context)
        # Pass extra parameters for the gateway here
        options = {}

        properties = merge_properties(properties, options)
        super(kb_account_id, kb_payment_id, kb_payment_method_id, properties, context)
      end

      def process_payment(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
        # Pass extra parameters for the gateway here
        options = {}

        properties = merge_properties(properties, options)
        super(kb_account_id, kb_payment_id, kb_payment_method_id, amount, currency, properties, context)
      end

      def get_payment_info(kb_account_id, kb_payment_id, properties, context)
        super
      end

      def search_payments(search_key, offset, limit, properties, context)
        super
      end

      def process_refund(kb_account_id, kb_payment_id, refund_amount, currency, properties, context)
        # Pass extra parameters for the gateway here
        options = {}

        properties = merge_properties(properties, options)
        super(kb_account_id, kb_payment_id, refund_amount, currency, properties, context)
      end

      def get_refund_info(kb_account_id, kb_payment_id, properties, context)
        super
      end

      def search_refunds(search_key, offset, limit, properties, context)
        super
      end

      def add_payment_method(kb_account_id, kb_payment_method_id, payment_method_props, set_default, properties, context)
        # Nothing to do
      end

      def delete_payment_method(kb_account_id, kb_payment_method_id, properties, context)
        # Pass extra parameters for the gateway here
        options = {}

        properties = merge_properties(properties, options)
        super(kb_account_id, kb_payment_method_id, properties, context)
      end

      def get_payment_method_detail(kb_account_id, kb_payment_method_id, properties, context)
        super
      end

      def set_default_payment_method(kb_account_id, kb_payment_method_id, properties, context)
        # TODO
      end

      def get_payment_methods(kb_account_id, refresh_from_gateway, properties, context)
        super
      end

      def search_payment_methods(search_key, offset, limit, properties, context)
        super
      end

      def reset_payment_methods(kb_account_id, payment_methods, properties, context)
        super
      end

      def build_form_descriptor(kb_account_id, descriptor_fields, properties, context)
        # Pass extra parameters for the gateway here
        options = {}
        properties = merge_properties(properties, options)

        # Add your custom static hidden tags here
        options = {
            :scid => config[:yandex][:scid]
        }
        descriptor_fields = merge_properties(descriptor_fields, options)

        super(kb_account_id, descriptor_fields, properties, context)
      end

      def process_notification(notification, properties, context)
        # Pass extra parameters for the gateway here
        options = {}
        properties = merge_properties(properties, options)

        super(notification, properties, context)
      end
    end
  end
end