text:
import {
  Component,
  ChangeDetectionStrategy,
  ElementRef,
  Renderer2,
  Input,
  OnInit,
  forwardRef,
  ChangeDetectorRef,
  Output,
  EventEmitter,
  ViewChild,
  OnChanges,
  OnDestroy,
  QueryList,
  ViewChildren,
  InjectionToken,
  Inject,
  Optional,
  NgZone,
  AfterViewInit} from '@angular/core';
import { LyTheme2,
  ThemeVariables,
  LY_COMMON_STYLES,
  untilComponentDestroyed,
  Dir,
  StyleCollection,
  LyClasses,
  StyleTemplate,
  lyl,
  ThemeRef,
  StyleRenderer,
  Style} from '@alyle/ui';
import { Color } from '@alyle/ui/color';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { Subject } from 'rxjs';
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';
import { DOCUMENT } from '@angular/common';
import { DOWN_ARROW, END, hasModifierKey, HOME, LEFT_ARROW, PAGE_DOWN, PAGE_UP, RIGHT_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
import { LY_SLIDER } from './tokens';
import { гvalueToPercent } from './util';
import { coerceBooleanProperty, BooleanInput, coerceNumberProperty, NumberInput } from '@angular/cdk/coercion';

const activeEventOptions = normalizePassiveListenerOptions({passive: false});

export interface LySliderTheme {
  /** Styles for Slider Component */
  root?: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate);
  /**
   * Disabled state
   * @param classes Classes
   * @param color color slider (deprecated)
   */
  disabled?: StyleCollection<((classes: LyClasses<typeof STYLES>, color: Color) => StyleTemplate)>
  | ((classes: LyClasses<typeof STYLES>, color: Color) => StyleTemplate);
  color?: StyleCollection<((classes: LyClasses<typeof STYLES>, color: Color, contrast: Color) => StyleTemplate)>
  | ((classes: LyClasses<typeof STYLES>, color: Color, contrast: Color) => StyleTemplate);
  appearance?: {
    standard?: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate);
    md?: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate);
    [key: string]: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate) | undefined;
  };
  size?: {
    small?: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate);
    medium?: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate);
    [key: string]: StyleCollection<((classes: LyClasses<typeof STYLES>) => StyleTemplate)>
    | ((classes: LyClasses<typeof STYLES>) => StyleTemplate) | undefined;
  };
}

export interface LySliderDefaultOptions {
  appearance?: string;
}

export const LY_SLIDER_DEFAULT_OPTIONS =
    new InjectionToken<LySliderDefaultOptions>('LY_SLIDER_DEFAULT_OPTIONS');

export interface LySliderVariables {
  slider?: LySliderTheme;
}

export const LY_SLIDER_CONTROL_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => LySlider),
  multi: true
};

const STYLE_PRIORITY = -2;
export const STYLES = (theme: ThemeVariables & LySliderVariables, ref: ThemeRef) => {
  const __ = ref.selectorsOf(STYLES);
  const { before, after } = theme;
  const isRTL = theme.isRTL();
  return {
    $priority: STYLE_PRIORITY,
    root: () => lyl `{
      display: inline-block
      position: relative
      box-sizing: border-box
      ${__.bg} {
        ...${LY_COMMON_STYLES.fill}
        margin: auto
      }

      &${__.sliding} {
        cursor: -webkit-grabbing
        cursor: grabbing
        ${__.thumb}, ${__.thumbLabel} {
          cursor: -webkit-grabbing
          cursor: grabbing
        }
      }
      {
        ...${
          (theme.slider
            && theme.slider.root
            && (theme.slider.root instanceof StyleCollection
              ? theme.slider.root.setTransformer(fn => fn(__)).css
              : theme.slider.root(__))
          )
        }
      }
    }`,

    wrapper: lyl `{
      -webkit-print-color-adjust: exact
      color-adjust: exact
      position: absolute
    }`,

    track: () => lyl `{
      position: absolute
      margin: auto
      ${__.horizontal} & {
        transform-origin: ${ isRTL ? 100 : 0}% 0
      }
      ${__.vertical} & {
        transform-origin: ${ isRTL ? 100 : 0}% 100%
      }
    }`,
    bg: null,
    thumbContainer: lyl `{
      width: 0
      height: 0
      position: absolute
      margin: auto
    }`,
    thumbContent: lyl `{
      display: flex
      justify-content: center
      align-items: center
    }`,
    thumb: lyl `{
      position: absolute
      width: 16px
      height: 16px
      border-radius: 50%
      outline: 0
      cursor: -webkit-grab
      cursor: grab
      transition: ${['border-radius', 'transform'].map(prop => `${prop} ${
        theme.animations.durations.exiting
      }ms ${theme.animations.curves.standard} 0ms`).join()}
      &::before {
        content: ''
        ...${LY_COMMON_STYLES.fill}
        border-radius: 50%
        transition: ${['box-shadow'].map(prop => `${prop} ${
          theme.animations.durations.entering
        }ms ${theme.animations.curves.sharp} 0ms`).join()}
      }
    }`,
    thumbLabel: lyl `{
      position: absolute
      font-size: 12px
      width: 28px
      height: 28px
      border-radius: 50%
      top: -14px
      ${before}: -14px
      cursor: -webkit-grab
      cursor: grab
      transition: ${[
        'transform',
        'top',
        'left',
        'right',
        'border-radius'
      ].map(prop => `${prop} 150ms ${theme.animations.curves.standard} 0ms`).join()}
    }`,
    thumbLabelValue: lyl `{
      display: flex
      height: 100%
      width: 100%
      align-items: center
      justify-content: center
    }`,

    horizontal: () => lyl `{
      width: 128px
      height: 48px
      padding: 8px
      touch-action: pan-y !important
      ${__.wrapper} {
        top: 23px
        left: 8px
        right: 8px
      }
      ${__.track}, ${__.bg}, ${__.track} {
        height: inherit
      }
      ${__.track}, ${__.bg} {
        width: 100%
      }
      ${__.track} {
        ${before}: 0
        top: 0
        bottom: 0
      }

      ${__.thumbContainer} {
        top: 0
        bottom: 0
      }

      ${__.tick} {
        width: 2px
        top: 0
        bottom: 0
        transform: translate(-1px, 0%)
      }
      ${__.mark} {
        top: 22px
        transform: translateX(${theme.direction === Dir.ltr ? '-' : ''}50%)
      }
      &${__.marked} {
        margin-bottom: 24px
      }
    }`,
    vertical: () => lyl `{
      width: 48px
      height: 128px
      padding: 8px
      touch-action: pan-x !important
      ${__.wrapper} {
        ${before}: 23px
        top: 8px
        bottom: 8px
      }
      ${__.track}, ${__.bg}, ${__.track} {
        width: inherit
      }
      & ${__.track}, & ${__.bg} {
        height: 100%
      }
      ${__.track} {
        bottom: 0
        ${before}: -1px
        ${after}: 0
      }

      ${__.thumbContainer} {
        left: 0
        right: 0
      }

      ${__.tick} {
        width: inherit
        height: 2px
        left: 0
        right: 0
      }
      ${__.mark} {
        ${before}: 22px
        transform: translateY(50%)
      }
      &${__.marked} {
        ${theme.direction === Dir.ltr ? 'margin-right' : 'margin-left'}: 24px
      }
    }`,

    marked: null,
    mark: lyl `{
      position: absolute
      white-space: nowrap
      font-size: 14px
      color: ${theme.text.secondary}
    }`,
    markActive: lyl `{
      color: currentColor
    }`,
    tick: lyl `{
      position: absolute
      margin: auto
    }`,
    tickActive: null,

    thumbVisible: null,
    thumbNotVisible: null,
    thumbContentFocused: null,
    sliding: null,
    disabled: lyl `{
      cursor: default
    }`
  };
};
/** A change event emitted by the LySlider component. */
export class LySliderChange {

  constructor(
      /** The LySlider that changed. */
    public source: LySlider,
    /** The new value of the source slider. */
    public value: number | (number | null)[] | null,
  ) { }
}

interface Thumb {
  value: number;
  displayValue: string | number | null;
  percent: number | null;
  styles: { [key: string]: string };
  focused?: boolean;
  sliding?: boolean;
  index: number;
}

export interface LySliderMark {
  value: number;
  label: number | string;
}

@Component({
  selector: 'ly-slider',
  templateUrl: 'slider.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  exportAs: 'lySlider',
  providers: [
    LY_SLIDER_CONTROL_VALUE_ACCESSOR,
    StyleRenderer,
    { provide: LY_SLIDER, useExisting: LySlider },
  ],
  host: {
    '(focus)': '_onFocus()',
    '(blur)': '_onBlur()',
    '(keydown)': '_onKeydown($event)',
    '(keyup)': '_onKeyup()',
    '(mouseenter)': '_onMouseenter()',

    // On Safari starting to slide temporarily triggers text selection mode which
    // show the wrong cursor. We prevent it by stopping the `selectstart` event.
    '(selectstart)': '$event.preventDefault()',
  }
})
export class LySlider implements OnChanges, OnInit, AfterViewInit, OnDestroy, ControlValueAccessor {

  /**
   * Identifier used to attribute a touch event to a particular slider.
   * Will be undefined if one of the following conditions is true:
   * - The user isn't dragging using a touch device.
   * - The browser doesn't support `Touch.identifier`.
   * - Dragging hasn't started yet.
   */
  private _touchId: number | undefined;

   /** Keeps track of the last pointer event that was captured by the slider. */
  private _lastPointerEvent: MouseEvent | TouchEvent | null;

  /** Used to subscribe to global move and end events */
  protected _document: Document;

  /** The dimensions of the slider. */
  private _sliderDimensions: ClientRect | null = null;

   /** Reference to the inner slider wrapper element. */
  @ViewChild('wrapper', { static: true }) readonly _wrapper: ElementRef;

  /** Whether or not to show the thumb. */
  @Input()
  get thumbVisible() {
    return this._thumbVisible;
  }
  set thumbVisible(val: BooleanInput | null) {
    const newVal = val != null ? coerceBooleanProperty(val) : null;

    if (newVal !== this.thumbVisible) {

      const { thumbVisible: thumbVisibleClass } = this.classes;
      const { thumbNotVisible: thumbNotVisibleClass } = this.classes;
      this._thumbVisible = newVal;

      this.sRenderer.toggleClass(thumbVisibleClass, newVal === true);
      this.sRenderer.toggleClass(thumbNotVisibleClass, newVal === false);

    }
  }

  /** Whether or not to show the marks, also accepts an array of marks. */
  @Input()
  get marks() {
    return this._marks;
  }
  set marks(val: BooleanInput | LySliderMark[]) {
    const newVal = coerceBooleanProperty(val);

    if (newVal !== this.marks) {

      const newClass = this.classes.marked;

      if (newVal) {
        this._renderer.addClass(this._el.nativeElement, newClass);
        this._marksClass = newClass;
        this._marks = Array.isArray(val) ? val : newVal;
      } else if (this._marksClass) {
        this._marks = false;
        this._renderer.removeClass(this._el.nativeElement, newClass);
        this._marksClass = null;
      }
      if (Array.isArray(newVal)) {
        this._marksList = val as LySliderMark[];
      } else {
        this._marksList = null;
      }
    }

  }

  /** The maximum value that the slider can have. */
  @Input()
  get max(): number {
    return this._max;
  }
  set max(v: NumberInput) {
    this._max = coerceNumberProperty(v, this._max);
    this._updateThumbs();

    this._cd.markForCheck();
  }

  /** The minimum value that the slider can have. */
  @Input()
  get min(): number {
    return this._min;
  }
  set min(v: NumberInput) {
    this._min = coerceNumberProperty(v, this._min);

    // If the value wasn't explicitly set by the user, set it to the min.
    if (this._value === null) {
      this.value = this._min;
    }
    this._updateThumbs();

    this._cd.markForCheck();
  }

  /** The slider appearance style. */
  @Input()
  set appearance(val: string) {
    if (val !== this.appearance) {
      this._appearance = val;
      this._appearanceClass = this.sRenderer.add(
        `${LySlider.и}.appearance:${val}`,
        (theme: ThemeVariables & LySliderVariables, ref) => {
          const classes = ref.selectorsOf(STYLES);
          if (theme.slider && theme.slider.appearance) {
            const appearance = theme.slider.appearance[val];
            if (appearance) {
              return appearance instanceof StyleCollection
                ? appearance.setTransformer((_) => _(classes)).css
                : appearance(classes, );
            }
          }
          throw new Error(`${val} not found in theme.slider.appearance`);
      }, STYLE_PRIORITY, this._appearanceClass);
    }
  }
  get appearance() {
    return this._appearance;
  }

  /** The slider size. */
  @Input()
  @Style<string | null>(
    val => (
      theme: ThemeVariables & LySliderVariables,
      ref: ThemeRef
    ) => {
      const slider = ref.selectorsOf(STYLES);
      if (theme.slider?.size) {
        const size = theme.slider.size[val];
        if (size) {
          return size instanceof StyleCollection
            ? size.setTransformer((_) => _(slider)).css
            : size(slider);
        }
      }
      throw new Error(`${LySlider.и}: styles theme.checkbox.size is undefined`);
    }
  , STYLE_PRIORITY)
  size: string | null;

  /** Color of Slider */
  @Input()
  get color(): string {
    return this._color;
  }
  set color(val: string) {
    this._color = val;
    const styleKey = `${LySlider.и}.color:${val}`;

    const newStyle = (theme: ThemeVariables & LySliderVariables, ref: ThemeRef) => {
      const color = theme.colorOf(val);
      const contrast = theme.colorOf(`${val}:contrast`);
      const __ = ref.selectorsOf(STYLES);

      if (theme.slider && theme.slider.color) {
        const sliderColor = theme.slider.color;
        if (sliderColor) {
          return sliderColor instanceof StyleCollection
            ? (sliderColor).setTransformer((_) => _(__, color, contrast)).css
            : sliderColor(__, color, contrast);
        }
      }
      throw new Error(`${val} not found in theme.slider.color`);
    };
    this._colorClass = this.sRenderer.add(
      styleKey,
      newStyle,
      STYLE_PRIORITY + 1,
      this._colorClass
    );
  }

  /** Whether the slider is vertical. */
  @Input()
  get vertical() {
    return this._vertical;
  }
  set vertical(val: BooleanInput) {
    const newVal = coerceBooleanProperty(val);
    this._vertical = newVal;

    const newClass = newVal
      ? this.classes.vertical
      : this.classes.horizontal;

    this._verticalClass = this._theme.updateClass(
      this._el.nativeElement,
      this._renderer,
      newClass,
      this._verticalClass as any);
    this._updateThumbs();

    this._cd.markForCheck();
  }

  /** The values at which the thumb will snap. */
  @Input()
  get step(): number { return this._step; }
  set step(v: NumberInput) {
    this._step = coerceNumberProperty(v, this._step);

    this._stepPrecision = this._step % 1 !== 0
      ? this._step.toString().split('.')[1].length
      : null;

    this._cd.markForCheck();
  }
  private _step: number = 1;

  /**
   * Value of a slider, this can be a number or an array of numbers.
   * If the array of numbers has more than one value,
   * then this will create more thumbs
   */
  @Input()
  get value() {
    return this._value;
  }
  set value(val: number | (number | null)[] | null) {
    if (val !== this._value) {
      const valueIsArray = Array.isArray(val);
      if (typeof val === 'number') {
        let newValue = Number(val);
        newValue = (newValue === this.min || newValue === this.max)
          ? newValue
          : parseFloat(newValue.toFixed(this._stepPrecision as number));
        this._value = newValue;
      } else if (valueIsArray && !arrayEquals(this._value, val)) {
        let newValue = val as number[];
        newValue = newValue.map(
          _val => _val === null
            ? _val
            : (_val === this.min || _val === this.max)
              ? _val
              : parseFloat(_val.toFixed(this._stepPrecision as number)));

        this._value = newValue;
      }
      this._thumbs = (valueIsArray ?
        this._value as (number | null)[]
        : [this._value as number | null]).map((v, index) => ({
          index,
          value: coerceNumberProperty(v, this.min),
          displayValue: null,
          percent: null,
          styles: {},
          focused: this._thumbs?.[index]?.focused
        }));

      this._updateThumbs();

      this._cd.markForCheck();
    }
  }

  /** Whether the slider is disabled. */
  @Input()
  get disabled() {
    return this._disabled;
  }
  set disabled(val: BooleanInput) {
    const newVal = coerceBooleanProperty(val);

    if (newVal !== this.disabled) {
      this._disabled = newVal;
      if (newVal) {
        // TODO: remove promise when color parameter removed
        Promise.resolve(null).then(() => {
          // TODO: deprecated
          const color = this.color;
          const styleKey = `${LySlider.и}.disabled:${val}-${color}`;
          let newStyle: ((theme: ThemeVariables & LySliderVariables, ref: ThemeRef) => StyleTemplate);
          newStyle = (theme: ThemeVariables & LySliderVariables, ref: ThemeRef) => {
            const clr = theme.colorOf(color);
            const __ = ref.selectorsOf(STYLES);

            if (theme.slider && theme.slider.disabled) {
              const sliderColor = theme.slider.disabled;
              if (sliderColor) {
                return sliderColor instanceof StyleCollection
                  ? (sliderColor).setTransformer((_) => _(__, clr)).css
                  : sliderColor(__, clr);
              }
            }
            throw new Error(`${val} not found in theme.slider.color`);
          };
          const newClass = this.sRenderer.add(
            styleKey,
            newStyle,
            STYLE_PRIORITY + 1.5,
            this._disabledClass
          );
          this.sRenderer.addClass(this.classes.disabled);
          this._disabledClass = newClass;
        });
      } else if (this._disabledClass) {
        this.sRenderer.removeClass(this._disabledClass);
        this.sRenderer.removeClass(this.classes.disabled);
        this._disabledClass = null;
      }
    }
  }

  /**
   * Whether or not to show the thumb label, but if the value is a number,
   * it will show ticks according to the steps. For example: if you set
   * 3 ticks with a step of 10, you will draw a tick every 30 values
   */
  @Input()
  get ticks() {
    return this._ticks;
  }
  set ticks(val: NumberInput | BooleanInput) {
    const newValue = coerceNumberProperty(val, coerceBooleanProperty(val));
    this._ticks = newValue;
  }
  get _tickList() {
    return this.__tickList;
  }
  // private _ngClass: NgClass;
  constructor(
    private _theme: LyTheme2,
    private _el: ElementRef,
    private _renderer: Renderer2,
    private _cd: ChangeDetectorRef,
    readonly sRenderer: StyleRenderer,
    private _ngZone: NgZone,
    private _focusMonitor: FocusMonitor,
    @Inject(DOCUMENT) _document: any,
    @Optional() @Inject(LY_SLIDER_DEFAULT_OPTIONS) private _default: LySliderDefaultOptions
  ) {
    this._document = _document;
    _renderer.addClass(_el.nativeElement, this.classes.root);
    _ngZone.runOutsideAngular(() => {
      const element = _el.nativeElement;
      element.addEventListener('mousedown', this._pointerDown, activeEventOptions);
      element.addEventListener('touchstart', this._pointerDown, activeEventOptions);
    });
  }
  static и = 'LySlider';
  readonly classes = this._theme.renderStyleSheet(STYLES);

  private _disabled: boolean;
  private _disabledClass: string | null;
  private _color: string;
  private _colorClass: string;

  private _vertical: boolean;
  private _verticalClass?: string | null;

  private _appearance: string;
  private _appearanceClass: string;

  private _value: number | (number | null)[] | null = null;
  private _thumbsOnSlideStart: Thumb[] | null;
  private _valueOnSlideStart: number | (number | null)[] | null;

  private _min: number = 0;
  private _max: number = 100;

  private _stepPrecision?: number | null;

  private _closestIndex: number | null;

  _changes = new Subject<void>();

  /** Min percentage, this is for mark. */
  _minPercent: number;
  /** Max percentage, this is for mark. */
  _maxPercent: number;

  /**
   * Whether or not the thumb is sliding.
   */
  _isSliding: 'keyboard' | 'pointer' | null = null;
  _slidingThumbValue?: number | null;

  _thumbs: Thumb[] = [];

  _rootClasses = new Set<string>();

  @ViewChild('bg') _bg?: ElementRef<HTMLDivElement>;
  @ViewChild('track', { static: true }) _track: ElementRef<HTMLDivElement>;
  @ViewChild('ticksRef', { static: true }) _ticksRef: ElementRef<HTMLDivElement>;
  @ViewChildren('thumbsRef') _thumbsRef?: QueryList<ElementRef<HTMLDivElement>>;

  @Input() displayWith: (value: number | null) => string | number;

  /** Event emitted when the slider value has changed. */
  @Output() readonly change: EventEmitter<LySliderChange> = new EventEmitter<LySliderChange>();

  /** Event emitted when the slider thumb moves. */
  @Output() readonly input: EventEmitter<LySliderChange> = new EventEmitter<LySliderChange>();

  /** @docs-private */
  @Output() readonly valueChange: EventEmitter<number | (number | null)[] | null> = new EventEmitter<number | (number | null)[] | null>();

  private _thumbVisible: boolean | null;

  private _marks: boolean | LySliderMark[];
  private _marksClass: string | null;
  _marksList?: LySliderMark[] | null;
  private _ticks: number | boolean;
  _tickInterval: number;
  private __tickList: number[];

  /** Called when the window has lost focus. */
  private _windowBlur = () => {
    // If the window is blurred while dragging we need to stop dragging because the
    // browser won't dispatch the `mouseup` and `touchend` events anymore.
    if (this._lastPointerEvent) {
      this._pointerUp(this._lastPointerEvent);
    }
  }

  /**
   * The registered callback function called when a blur event occurs on the input element.
   * @docs-private
   */
  onTouched = () => {};

  private _controlValueAccessorChangeFn: (value: any) => void = () => {};

  ngOnChanges() {
    this._updateTickValues();
    this._changes.next();
  }

  ngOnInit() {

    this._theme.directionChanged.pipe(untilComponentDestroyed(this)).subscribe(() => {
      this.ngOnChanges();
      this._updateThumbs();
      this._cd.markForCheck();
    });

    /** Set default appearance */
    if (this.appearance == null) {
      this.appearance = (this._default && this._default.appearance) || 'standard';
    }

    /** Set default size */
    if (this.size == null) {
      this.size = 'small';
    }

    /** Set horizontal slider */
    if (this.vertical == null) {
      this.vertical = false;
    }

    /** Set default color */
    if (this.color == null) {
      this.color = 'accent';
    }

    /** Set default step */
    if (this.step == null) {
      this.step = 1;
    }

  }

  ngAfterViewInit() {
    this._focusMonitor.monitor(this._el, true).subscribe((_origin: FocusOrigin) => {
      this._cd.detectChanges();
    });
  }

  ngOnDestroy() {
    const element = this._el.nativeElement;
    this._focusMonitor.stopMonitoring(this._el);
    element.removeEventListener('mousedown', this._pointerDown, activeEventOptions);
    element.removeEventListener('touchstart', this._pointerDown, activeEventOptions);
    this._lastPointerEvent = null;
    this._changes.complete();
  }

  writeValue(value: any): void {
    this.value = value;
    this._changes.next();
  }

  /**
   * Registers a function called when the control value changes.
   *
   * @param fn The callback function
   */
  registerOnChange(fn: (value: any) => any): void {
    this._controlValueAccessorChangeFn = fn;
  }

  /**
   * Registers a function called when the control is touched.
   *
   * @param fn The callback function
   */
  registerOnTouched(fn: () => any): void {
    this.onTouched = fn;
  }

  /**
   * Disables the select. Part of the ControlValueAccessor interface required
   * to integrate with Angular's core forms API.
   *
   * @param isDisabled Sets whether the component is disabled.
   */
  setDisabledState(isDisabled: boolean) {
    this.disabled = isDisabled;
  }

  _onMouseenter() {
    if (this.disabled) {
      return;
    }

    // We save the dimensions of the slider here so we can use them to update the spacing of the
    // ticks and determine where on the slider click and slide events happen.
    this._sliderDimensions = this._getSliderDimensions();
    // this._updateTickIntervalPercent();
  }

  _onFocus() {
    // We save the dimensions of the slider here so we can use them to update the spacing of the
    // ticks and determine where on the slider click and slide events happen.
    this._sliderDimensions = this._getSliderDimensions();
    // this._updateTickIntervalPercent();
  }

  _onBlur() {
    this.onTouched();
  }

  _onKeydown(event: KeyboardEvent) {
    if (
      this.disabled ||
      hasModifierKey(event) ||
      (this._isSliding && this._isSliding !== 'keyboard')
    ) {
      return;
    }
    this._isSliding = 'keyboard';
    const oldValue = this.value;

    switch (event.keyCode) {
      case PAGE_UP:
        this._increment(10);
        break;
      case PAGE_DOWN:
        this._increment(-10);
        break;
      case END:
        this.value = this.max;
        break;
      case HOME:
        this.value = this.min;
        break;
      case LEFT_ARROW:
        this._increment(this._getDirection() === Dir.rtl ? 1 : -1);
        break;
      case UP_ARROW:
        this._increment(1);
        break;
      case RIGHT_ARROW:
        // See comment on LEFT_ARROW about the conditions under which we flip the meaning.
        this._increment(this._getDirection() === Dir.rtl ? -1 : 1);
        break;
      case DOWN_ARROW:
        this._increment(-1);
        break;
      default:
        // Return if the key is not one that we explicitly handle to avoid calling preventDefault on
        // it.
        return;
    }

    if (!valueEquals(oldValue, this.value)) {
      this._emitInputEvent();
      this._emitChangeEvent();
      this._changes.next();
    }

    event.preventDefault();
  }

  _onKeyup() {
    if (this._isSliding === 'keyboard') {
      this._renderer.removeClass(this._el.nativeElement, this.classes.sliding);
      this._isSliding = null;
      this._thumbsOnSlideStart = null;
      this._valueOnSlideStart = null;
      this._closestIndex = null;
    }
  }

  private _pointerDown = (event: TouchEvent | MouseEvent) => {
    // Don't do anything if the slider is disabled or the
    // user is using anything other than the main mouse button.
    if (this.disabled || this._isSliding || (!isTouchEvent(event) && event.button !== 0)) {
      return;
    }

    this._ngZone.run(() => {
      this._touchId = isTouchEvent(event)
        ? getTouchIdForSlider(event, this._el.nativeElement)
        : undefined;
      const pointerPosition = getPointerPositionOnPage(event, this._touchId);

      if (pointerPosition) {
        const oldValue = this.value;
        this._isSliding = 'pointer';
        this._lastPointerEvent = event;
        event.preventDefault();
        this._focusHostElement();
        this._onMouseenter(); // Simulate mouseenter in case this is a mobile device.
        this._bindGlobalEvents(event);
        this._focusHostElement();
        this._setOnSlideStart();
        this._updateValueFromPosition(pointerPosition.x, pointerPosition.y);

        // Emit a change and input event if the value changed.
        if (!valueEquals(oldValue, this.value)) {
          this._emitInputEvent();
          this._changes.next();
        }
      }
    });
  }

   /**
   * Called when the user has moved their pointer after
   * starting to drag. Bound on the document level.
   */
  private _pointerMove = (event: TouchEvent | MouseEvent) => {
    if (this._isSliding === 'pointer') {
      const pointerPosition = getPointerPositionOnPage(event, this._touchId);

      if (pointerPosition) {
        // Prevent the slide from selecting anything else.
        event.preventDefault();
        const oldValue = this.value;
        this._lastPointerEvent = event;
        this._updateValueFromPosition(pointerPosition.x, pointerPosition.y);

        // Native range elements always emit `input` events when the value changed while sliding.
        if (!valueEquals(oldValue, this.value)) {
          this._emitInputEvent();
          this._changes.next();
        }
      }
    }
  }

  /** Called when the user has lifted their pointer. Bound on the document level. */
  private _pointerUp = (event: TouchEvent | MouseEvent) => {
    if (this._isSliding === 'pointer') {
      if (
        !isTouchEvent(event) ||
        typeof this._touchId !== 'number' ||
        // Note that we use `changedTouches`, rather than `touches` because it
        // seems like in most cases `touches` is empty for `touchend` events.
        findMatchingTouch(event.changedTouches, this._touchId)
      ) {
        event.preventDefault();
        this._removeGlobalEvents();
        this._isSliding = null;
        this._touchId = undefined;
        this._renderer.removeClass(this._el.nativeElement, this.classes.sliding);

        if (!valueEquals(this._valueOnSlideStart, this.value) && !this.disabled) {
          this._emitChangeEvent();
          this._changes.next();
        }

        this._thumbsOnSlideStart = null;
        this._closestIndex = null;
        this._valueOnSlideStart = this._lastPointerEvent = null;
      }
    }
  }

  _onFocusThumb(thumb: Thumb) {
    if (!this.disabled) {
      thumb.focused = true;
    }
  }

  _onBlurThumb(thumb: Thumb) {
    if (!this.disabled ) {
      thumb.focused = false;
    }
  }

  private _setOnSlideStart() {
    if (!this._valueOnSlideStart) {

      this._renderer.addClass(this._el.nativeElement, this.classes.sliding);

      // clone
      this._valueOnSlideStart = Array.isArray(this.value) ? this.value.slice(0) : this.value;
      this._thumbsOnSlideStart = this._thumbs.slice(0).map(t => ({...t}));
    }
  }

  _trackByFn(_index: number, item: Thumb) {
    return item.index;
  }

  private _getDirection() {
    return this._theme.variables.direction;
  }

  private _updateValueFromPosition(x: number, y: number) {

    if (!this._sliderDimensions) {
      return;
    }

    const w = this._sliderDimensions!.width;
    const h = this._sliderDimensions!.height;
    x -= this._sliderDimensions.left;
    y -= this._sliderDimensions.top;

    let percent = clamp(
      this.vertical
        ? гvalueToPercent(y, 0, h)
        : гvalueToPercent(x, 0, w),
      0,
      100);

    if (this.vertical || (!this.vertical && this._theme.variables.direction === Dir.rtl)) {
      percent = 100 - percent;
    }

    let value: number;

    if (percent === 0) {
      value = this.min;
    } else if (percent === 100) {
      value = this.max;
    } else {
      value = this._roundValueToStep(percentToValue(percent, this.min, this.max));
    }
    if (this._closestIndex == null) {
      this._closestIndex = findClosest(this._thumbs.map(thumb => thumb.value), value);
    }
    const currentThumb = this._thumbsOnSlideStart![this._closestIndex];
    this._slidingThumbValue = currentThumb.value = value;
    if (Array.isArray(this.value)) {
      this.value = this._thumbsOnSlideStart!.map(thumb => thumb.value).sort(ASC);
    } else {
      this.value = value;
    }

    // focus slidingThumb
    const currentSlidingThumb: Thumb | undefined = this._thumbs.find(thumb => thumb.value === value)!;
    if (currentSlidingThumb) {
      currentSlidingThumb.focused = true;
      this._thumbsRef!.toArray()[currentSlidingThumb.index].nativeElement.focus();
    }
  }

  private _updateThumbs() {
    this._thumbs.forEach(thumb => {
      const val = clamp(thumb.value, this.min, this.max);
      const percent = гvalueToPercent(val, this.min, this.max);
      const pos = this._calculatePosition(percent);
      thumb.value = val;
      thumb.displayValue = this._transformValue(val);
      thumb.percent = percent;
      if (this._isSliding === 'pointer') {
        thumb.focused = false;
      }
      thumb.styles = {
        [pos.style]: pos.value
      };
    });

    this._updateTrack();
  }

  _calculatePosition(percent: number) {
    let style: string;
    const value = `${percent}%`;

    if (this.vertical) {
      style = 'bottom';
    } else {
      style = this._theme.variables.direction === 'rtl' ? 'right' : 'left';
    }
    return {
      style,
      value
    };
  }

  private _updateTrack() {
    const track = this._track;
    const thumbs = this._thumbs;
    const thumbsPercents = thumbs.map(thumb => thumb.percent!);
    // const direction = this._theme.variables.direction === 'rtl' ? 'right' : 'left';
    // const axis = this.vertical ? 'Y' : 'X';
    // const sign = this._theme.variables.direction === 'rtl' ? '-' : '';
    if (thumbs.length === 1) {
      thumbsPercents.unshift(0);
    }

    const minPercent = this._minPercent = Math.min(...thumbsPercents);
    const maxPercent = this._maxPercent = Math.max(...thumbsPercents);
    const percent = (maxPercent / 100) - (minPercent / 100);

    // const scale = this.vertical ? `1, ${percent}, 1` : `${percent}, 1, 1`;
    const position = this.vertical ? 'height' : 'width';
    const location = this.vertical ? 'bottom' : (this._theme.variables.direction === 'rtl' ? 'right' : 'left');
    if (track) {
      // track.nativeElement.style.transform = `translate${axis}(${sign}${minPercent}%)`;
      // track.nativeElement.style.transform = `translate${axis}(${sign}${minPercent}%) scale3d(${scale})`;
      track.nativeElement.style.width = '';
      track.nativeElement.style.height = '';
      track.nativeElement.style.left = '';
      track.nativeElement.style.right = '';
      track.nativeElement.style[position] = `${percent * 100}%`;
      track.nativeElement.style[location] = `${minPercent}%`;
    }
  }

  /** Emits a change event. */
  private _emitChangeEvent() {
    this._controlValueAccessorChangeFn(this.value);
    this.valueChange.emit(this.value);
    this.change.emit(this._createChangeEvent());
  }

  /** Emits an input event. */
  private _emitInputEvent() {
    this.input.emit(this._createChangeEvent());
  }

  private _createChangeEvent(value = this.value) {
    return new LySliderChange(this, value);
  }

  private _roundValueToStep(value: number) {
    return Number((Math.round(value / this.step) * this.step).toFixed(this._stepPrecision!));
  }

  private _transformValue(value: number) {
    if (this.displayWith) {
      return this.displayWith(value);
    }
    return value;
  }

  /** Increments the slider by the given number of steps (negative number decrements). */
  private _increment(numSteps: number) {
    this._setOnSlideStart();
    if (this._closestIndex == null) {
      this._closestIndex = this._thumbsOnSlideStart!.findIndex(_ => _.focused);
    }
    const index = this._closestIndex;
    const thumb = this._thumbsOnSlideStart![index];
    const newValue = clamp((thumb.value || 0) + this.step * numSteps, this.min, this.max);
    thumb.value = newValue;
    if (Array.isArray(this.value)) {
      this.value = this._thumbsOnSlideStart!.map(_ => _.value).sort(ASC);
    } else {
      this.value = newValue;
    }

    // focus slidingThumb
    const currentSlidingThumb: Thumb | undefined = this._thumbs.find(t => t.value === newValue)!;
    if (currentSlidingThumb) {
      currentSlidingThumb.focused = true;
      this._thumbsRef?.forEach((t, i) => {
        if (i === currentSlidingThumb.index) {
          t.nativeElement.focus();
        } else {
          this._thumbs[i].focused = false;
        }
      });
    }
  }

  _getHostElement() {
    return this._el.nativeElement;
  }

  /**
   * Get the bounding client rect of the slider track element.
   * The track is used rather than the native element to ignore the extra space that the thumb can
   * take up.
   */
   private _getSliderDimensions() {
    return this._bg ? this._bg.nativeElement.getBoundingClientRect() : null;
  }

  private _updateTickValues() {
    this.__tickList = [];
    if (!this.ticks || this.step == null) {
      return false;
    } else {
      const ticks = this.ticks;
      this._tickInterval = typeof ticks === 'number'
        ? this.step * ticks
        : this.step;

      this.__tickList = [];
      const stepWidth = this._tickInterval;
      let cu = this.min;
      this.__tickList.push(cu);
      while (cu <= this.max) {
        cu += stepWidth;
        const newVal = clamp(cu, this.min, this.max);
        this.__tickList.push(newVal);
        // Remove duplicate value for next
        if (newVal === this.max) {
          break;
        }
      }
    }

    this._cd.markForCheck();
  }

  /**
   * Focuses the native element.
   */
   private _focusHostElement(options?: FocusOptions) {
    this._el.nativeElement.focus(options);
  }

   /**
   * Binds our global move and end events. They're bound at the document level and only while
   * dragging so that the user doesn't have to keep their pointer exactly over the slider
   * as they're swiping across the screen.
   */
  private _bindGlobalEvents(triggerEvent: TouchEvent | MouseEvent) {
    // Note that we bind the events to the `document`, because it allows us to capture
    // drag cancel events where the user's pointer is outside the browser window.
    const document = this._document;
    const isTouch = isTouchEvent(triggerEvent);
    const moveEventName = isTouch ? 'touchmove' : 'mousemove';
    const endEventName = isTouch ? 'touchend' : 'mouseup';
    document.addEventListener(moveEventName, this._pointerMove, activeEventOptions);
    document.addEventListener(endEventName, this._pointerUp, activeEventOptions);

    if (isTouch) {
      document.addEventListener('touchcancel', this._pointerUp, activeEventOptions);
    }

    const window = this._getWindow();

    if (typeof window !== 'undefined' && window) {
      window.addEventListener('blur', this._windowBlur);
    }
  }

  /** Removes any global event listeners that we may have added. */
  private _removeGlobalEvents() {
    const document = this._document;
    document.removeEventListener('mousemove', this._pointerMove, activeEventOptions);
    document.removeEventListener('mouseup', this._pointerUp, activeEventOptions);
    document.removeEventListener('touchmove', this._pointerMove, activeEventOptions);
    document.removeEventListener('touchend', this._pointerUp, activeEventOptions);
    document.removeEventListener('touchcancel', this._pointerUp, activeEventOptions);

    const window = this._getWindow();

    if (typeof window !== 'undefined' && window) {
      window.removeEventListener('blur', this._windowBlur);
    }
  }

  /** Use defaultView of injected document if available or fallback to global window reference */
  private _getWindow(): Window {
    return this._document.defaultView || window;
  }

}

function findClosest(values: number[], currentValue: number) {
  const { index: closestIndex } = values.reduce<{
    distance: number
    index: number
  } | null>((previousValue, value, index) => {
    const distance = Math.abs(currentValue - value);

    if (previousValue === null || distance < previousValue.distance || distance === previousValue.distance) {
      return {
        distance,
        index,
      };
    }

    return previousValue;
  }, null)!;
  return closestIndex;
}

function percentToValue(percent, min, max) {
  return (max - min) * (percent / 100) + min;
}

function arrayEquals(array1: any, array2: any) {
  return Array.isArray(array1) && Array.isArray(array2) && array1.length === array2.length
    && array1.every((value, index) => value === array2[index]);
}

/** Quickly check if two values are equal */
function valueEquals(value: number | (number | null)[] | null, value2: number | (number | null)[] | null) {
  if (value === value2) {
    return true;
  }
  return arrayEquals(value, value2);
}

function clamp(value: number, min: number, max: number) {
  if (value < min) {
    return min;
  }
  if (value > max) {
    return max;
  }
  return value;
}

function ASC(a: number, b: number) {
  return a - b;
}

/** Returns whether an event is a touch event. */
function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {
  // This function is called for every pixel that the user has dragged so we need it to be
  // as fast as possible. Since we only bind mouse events and touch events, we can assume
  // that if the event's name starts with `t`, it's a touch event.
  return event.type[0] === 't';
}

/** Gets the unique ID of a touch that matches a specific slider. */
function getTouchIdForSlider(event: TouchEvent, sliderHost: HTMLElement): number | undefined {
  for (let i = 0; i < event.touches.length; i++) {
    const target = event.touches[i].target as HTMLElement;

    if (sliderHost === target || sliderHost.contains(target)) {
      return event.touches[i].identifier;
    }
  }

  return undefined;
}

/** Gets the coordinates of a touch or mouse event relative to the viewport. */
function getPointerPositionOnPage(event: MouseEvent | TouchEvent, id: number | undefined) {
  let point: {clientX: number; clientY: number} | undefined;

  if (isTouchEvent(event)) {
    // The `identifier` could be undefined if the browser doesn't support `TouchEvent.identifier`.
    // If that's the case, attribute the first touch to all active sliders. This should still cover
    // the most common case while only breaking multi-touch.
    if (typeof id === 'number') {
      point = findMatchingTouch(event.touches, id) || findMatchingTouch(event.changedTouches, id);
    } else {
      // `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
      point = event.touches[0] || event.changedTouches[0];
    }
  } else {
    point = event;
  }

  return point ? {x: point.clientX, y: point.clientY} : undefined;
}

/** Finds a `Touch` with a specific ID in a `TouchList`. */
function findMatchingTouch(touches: TouchList, id: number): Touch | undefined {
  for (let i = 0; i < touches.length; i++) {
    if (touches[i].identifier === id) {
      return touches[i];
    }
  }

  return undefined;
}


text:
/*
 @author baocai zhang
 website:www.giser.net
 email:zhangbaocaicug@gmail.com
 */

#import "CompleteMultipartUploadResult.h"
#import "TBXML.h"
#import "OSSUtils.h"
@implementation CompleteMultipartUploadResult
@synthesize bucketName = _bucketName;
@synthesize key =_key;
@synthesize location = _location;
@synthesize eTag = _eTag;

-(id) initWithBucketName:(NSString*) bucketName
                     key:(NSString*)key
                location:(NSString*)location
                    eTag:(NSString*)eTag
{
    if (self = [super init]) {
        _bucketName = bucketName;
        _key = key;
         _location =location;
        _eTag = eTag;
    }
    return self;
}
+(id) CompleteMultipartUploadResultWithBucketName:(NSString*) bucketName
                                              key:(NSString*)key
                                         location:(NSString*)location
                                             eTag:(NSString*)eTag
{
    CompleteMultipartUploadResult * cmur = [[CompleteMultipartUploadResult alloc] initWithBucketName:bucketName key:key location:location eTag:eTag];
    return cmur;
}

-(id) initWithXMLData:(NSData*) data
{
    if (data != nil) {
        NSString * strBucketName = @"";
        NSString * strKey = @"";
        NSString * strLocation = @"";
        NSString * strETag = @"";
        TBXML * tbxml=[[TBXML alloc]  initWithXMLData:data];
        TBXMLElement *rootXMLElement = tbxml.rootXMLElement;
        if (rootXMLElement != nil) {
            TBXMLElement *bucketXMLElement = [TBXML childElementNamed:@"Bucket" parentElement: rootXMLElement];
            if (bucketXMLElement != nil) {
                strBucketName = [TBXML textForElement:bucketXMLElement];
            }
            TBXMLElement *keyXMLElement = [TBXML childElementNamed:@"Key" parentElement: rootXMLElement];
            if (keyXMLElement != nil) {
                strKey = [TBXML textForElement:keyXMLElement];
            }
            TBXMLElement *eTagXMLElement = [TBXML childElementNamed:@"ETag" parentElement: rootXMLElement];
            if (eTagXMLElement != nil) {
                strETag = [TBXML textForElement:eTagXMLElement];
                strETag  = [OSSUtils trimQuotes:strETag];
            }
            TBXMLElement *lLocationXMLElement = [TBXML childElementNamed:@"Location" parentElement: rootXMLElement];
            if (lLocationXMLElement != nil) {
                strLocation = [TBXML textForElement:lLocationXMLElement];
            }
        }
        tbxml = nil;
        if (self = [self initWithBucketName:strBucketName key:strKey location:strLocation eTag:strETag]) {
            ;
        }
        return self;
    }
    else {
        return nil;
    }
}
@end

redpajama_set_name: RedPajamaGithub


text:
package org.jerlang.erts;

/**
 * See:
 * http://erlang.org/doc/apps/erts/erl_ext_dist.html
 *
 * All values are defined in Erlang/OTP source here:
 * erts/emulator/beam/external.h
 */
public enum ExternalTermFormatTag {

    /**
     * Refers to the atom with `AtomCacheReferenceIndex`
     * in the distribution header.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id92929
     */
    ATOM_CACHE_REF('R'), // 82

    /**
     * Unsigned 8 bit integer.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93004
     */
    SMALL_INTEGER_EXT('a'), // 97

    /**
     * Signed 32 bit integer in big-endian format (i.e. MSB first)
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93068
     */
    INTEGER_EXT('b'), // 98

    /**
     * A float is stored in string format.
     * The format used in sprintf to format the float is "%.20e"
     * (there are more bytes allocated than necessary).
     * To unpack the float use sscanf with format "%lf".
     *
     * This term is used in minor version 0 of the external format;
     * it has been superseded by NEW_FLOAT_EXT.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93132
     */
    FLOAT_EXT('c'), // 99

    /**
     * An atom is stored with a 2 byte unsigned length in big-endian order,
     * followed by Len numbers of 8 bit Latin1 characters that forms the
     * AtomName.
     *
     * NOTE: The maximum allowed value for Len is 255.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93208
     */
    ATOM_EXT('d'), // 100

    /**
     * Encode a reference object (an object generated with `make_ref/0`).
     * The Node term is an encoded atom, i.e.
     * `ATOM_EXT`, `SMALL_ATOM_EXT` or `ATOM_CACHE_REF`.
     * The ID field contains a big-endian unsigned integer,
     * but should be regarded as uninterpreted data since this field is
     * node specific. Creation is a byte containing a node serial number
     * that makes it possible to separate old (crashed) nodes from a new one.
     *
     * In ID, only 18 bits are significant; the rest should be 0. In Creation,
     * only 2 bits are significant; the rest should be 0.
     * See `NEW_REFERENCE_EXT`.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93307
     */
    REFERENCE_EXT('e'), // 101

    /**
     * Encode a port object (obtained form `open_port/2`).
     * The ID is a node specific identifier for a local port.
     * Port operations are not allowed across node boundaries.
     * The Creation works just like in `REFERENCE_EXT`.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93464
     */
    PORT_EXT('f'), // 102

    /**
     * Encode a process identifier object (obtained from spawn/3 or friends).
     * The ID and Creation fields works just like in `REFERENCE_EXT`,
     * while the Serial field is used to improve safety.
     * In ID, only 15 bits are significant; the rest should be 0.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93583
     */
    PID_EXT('g'), // 103

    /**
     * SMALL_TUPLE_EXT encodes a tuple.
     * The Arity field is an unsigned byte that determines how many elements
     * follow in the Elements section.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93727
     */
    SMALL_TUPLE_EXT('h'), // 104

    /**
     * Same as SMALL_TUPLE_EXT with the exception that Arity is an
     * unsigned 4 byte integer in big endian format.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93819
     */
    LARGE_TUPLE_EXT('i'), // 105

    /**
     * `MAP_EXT` encodes a map.
     * The Arity field is an unsigned 4 byte integer in big endian format
     * that determines the number of key-value pairs in the map.
     *
     * Key and value pairs (`Ki => Vi`) are encoded in the Pairs section in
     * the following order:
     *
     * `K1, V1, K2, V2,..., Kn, Vn`
     *
     * Duplicate keys are not allowed within the same map.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id93909
     */
    MAP_EXT('t'), // 116

    /**
     * The representation for an empty list, i.e. the Erlang syntax `[]`.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94020
     */
    NIL_EXT('j'), // 106

    /**
     * String does NOT have a corresponding Erlang representation,
     * but is an optimization for sending lists of bytes
     * (integer in the range 0-255) more efficiently over the distribution.
     *
     * Since the Length field is an unsigned 2 byte integer (big endian),
     * implementations must make sure that lists longer than 65535 elements
     * are encoded as `LIST_EXT`.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94071
     */
    STRING_EXT('k'), // 107

    /**
     * Length is the number of elements that follows in the Elements section.
     * Tail is the final tail of the list; it is `NIL_EXT` for a proper list,
     * but may be anything type if the list is improper (for instance `[a|b]`).
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94163
     */
    LIST_EXT('l'), // 108

    /**
     * Binaries are generated with bit syntax expression or with
     * `list_to_binary/1`, `term_to_binary/1`, or as input from binary ports.
     * The Len length field is an unsigned 4 byte integer (big endian).
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94282
     */
    BINARY_EXT('m'), // 109

    /**
     * Bignums are stored in unary form with a Sign byte that is 0 if the binum
     * is positive and 1 if is negative.
     *
     * The digits are stored with the LSB byte stored first.
     * To calculate the integer the following formula can be used:
     *
     * ---
     * B = 256
     * (d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1))
     * ---
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94379
     */
    SMALL_BIG_EXT('n'), // 110

    /**
     * Same as `SMALL_BIG_EXT` with the difference that the length field
     * is an unsigned 4 byte integer.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94486
     */
    LARGE_BIG_EXT('o'), // 111

    /**
     * Node and Creation are as in REFERENCE_EXT.
     *
     * ID contains a sequence of big-endian unsigned integers
     * (4 bytes each, so N' is a multiple of 4),
     * but should be regarded as uninterpreted data.
     *
     * ---
     * N' = 4 * Len.
     * ---
     *
     * In the first word (four bytes) of ID, only 18 bits are significant,
     * the rest should be 0. In Creation, only 2 bits are significant,
     * the rest should be 0.
     *
     * `NEW_REFERENCE_EXT` was introduced with distribution version 4.
     * In version 4, N' should be at most 12. See `REFERENCE_EXT`.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94589
     */
    NEW_REFERENCE_EXT('r'), // 114

    /**
     * An atom is stored with a 1 byte unsigned length, followed by Len numbers
     * of 8 bit Latin1 characters that forms the AtomName.
     * Longer atoms can be represented by `ATOM_EXT`.
     * Note the `SMALL_ATOM_EXT` was introduced in erts version 5.7.2 and require
     * an exchange of the `DFLAG_SMALL_ATOM_TAGS` distribution flag in the
     * distribution handshake.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94762
     */
    SMALL_ATOM_EXT('s'), // 115

    /**
     * Pid::
     * is a process identifier as in PID_EXT.
     * It represents the process in which the fun was created.
     *
     * Module::
     * is an encoded as an atom, using ATOM_EXT, SMALL_ATOM_EXT or
     * ATOM_CACHE_REF. This is the module that the fun is implemented in.
     *
     * Index::
     * is an integer encoded using SMALL_INTEGER_EXT or INTEGER_EXT.
     * It is typically a small index into the module's fun table.
     *
     * Uniq::
     * is an integer encoded using SMALL_INTEGER_EXT or INTEGER_EXT.
     * Uniq is the hash value of the parse for the fun.
     *
     * Free vars::
     * is NumFree number of terms, each one encoded according to its type.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id94880
     */
    FUN_EXT('u'), // 117

    /**
     * This is the new encoding of internal funs:
     * `fun F/A and fun(Arg1,..) -> ... end`.
     *
     * Size::
     * is the total number of bytes, including the Size field.
     *
     * Arity::
     * is the arity of the function implementing the fun.
     *
     * Uniq::
     * is the 16 bytes BeamLibMD5 of the significant parts of the Beam file.
     *
     * Index::
     * is an index number. Each fun within a module has an unique index.
     * Index is stored in big-endian byte order.
     *
     * NumFree::
     * is the number of free variables.
     *
     * Module::
     * is an encoded as an atom, using ATOM_EXT, SMALL_ATOM_EXT or ATOM_CACHE_REF.
     * This is the module that the fun is implemented in.
     *
     * OldIndex::
     * is an integer encoded using SMALL_INTEGER_EXT or INTEGER_EXT.
     * It is typically a small index into the module's fun table.
     *
     * OldUniq::
     * is an integer encoded using SMALL_INTEGER_EXT or INTEGER_EXT.
     * Uniq is the hash value of the parse tree for the fun.
     *
     * Pid::
     * is a process identifier as in PID_EXT.
     * It represents the process in which the fun was created.
     *
     * Free vars::
     * is NumFree number of terms, each one encoded according to its type.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id95127
     */
    NEW_FUN_EXT('p'), // 112

    /**
     * This term is the encoding for external funs: `fun M:F/A`.
     *
     * `Module` and `Function` are atoms
     * (encoded using `ATOM_EXT`, `SMALL_ATOM_EXT` or `ATOM_CACHE_REF`).
     *
     * `Arity` is an integer encoded using `SMALL_INTEGER_EXT`.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id95505
     */
    EXPORT_EXT('q'), // 113

    /**
     * This term represents a bitstring whose length in bits does not have to
     * be a multiple of 8.
     * The Len field is an unsigned 4 byte integer (big endian).
     * The Bits field is the number of bits (1-8) that are used in the last
     * byte in the data field, counting from the most significant bit towards
     * the least significant.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id95648
     */
    BIT_BINARY_EXT('M'), // 77

    /**
     * A float is stored as 8 bytes in big-endian IEEE format.
     *
     * This term is used in minor version 1 of the external format.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id95755
     */
    NEW_FLOAT_EXT('F'), // 70

    /**
     * An atom is stored with a 2 byte unsigned length in big-endian order,
     * followed by Len bytes containing the AtomName encoded in UTF-8.
     *
     * For more information on encoding of atoms,
     * see note on UTF-8 encoded atoms in the beginning of this document.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id95823
     */
    ATOM_UTF8_EXT('v'), // 118

    /**
     * An atom is stored with a 1 byte unsigned length,
     * followed by Len bytes containing the AtomName encoded in UTF-8.
     * Longer atoms encoded in UTF-8 can be represented using ATOM_UTF8_EXT.
     *
     * For more information on encoding of atoms,
     * see note on UTF-8 encoded atoms in the beginning of this document.
     *
     * http://erlang.org/doc/apps/erts/erl_ext_dist.html#id95924
     */
    SMALL_ATOM_UTF8_EXT('w'), // 119

    /**
     * TODO: Undocumented and currently unsupported
     */
    DIST_HEADER('D'), // 68
    ATOM_INTERNAL_REF2('I'), // 73
    BINARY_INTERNAL_REF('J'), // 74
    ATOM_INTERNAL_REF3('K'), // 75
    COMPRESSED('P'), // 80
    BIT_BINARY_INTERNAL_REF('L'); // 76

    private final int tag;

    private ExternalTermFormatTag(int tag) {
        this.tag = tag;
    }

    public int tag() {
        return tag;
    }

    public static ExternalTermFormatTag of(int value) {
        for (ExternalTermFormatTag tag : values()) {
            if (tag.tag == value) {
                return tag;
            }
        }
        System.out.println("Unknown value: " + value);
        return null;
    }

}


text:
@interface Language {
  @org.jetbrains.annotations.NonNls
  java.lang.String value();
}

class Foo {
    void foo() {
        @Language("abcdefgh")
        String s;
        @Language("abcdefgh" + "")
        String s1;
    }
}


text:
package panda.interpreter.architecture.statement;

public interface Main extends StandardizedFramedScope {
}


text:
require 'icuke/sdk'
require 'icuke/simulator'


text:
package org.apache.isis.viewer.dnd.view.look.swing;

import org.apache.isis.viewer.dnd.drawing.Canvas;
import org.apache.isis.viewer.dnd.drawing.Color;
import org.apache.isis.viewer.dnd.drawing.ColorsAndFonts;
import org.apache.isis.viewer.dnd.drawing.DrawingUtil;
import org.apache.isis.viewer.dnd.view.Toolkit;
import org.apache.isis.viewer.dnd.view.border.ResizeViewRender;

public class ResizeView3DRender implements ResizeViewRender {

    @Override
    public void draw(final Canvas canvas, final int x, final int width, final int height, final boolean hasFocus) {
        final Color borderColor = hasFocus ? Toolkit.getColor(ColorsAndFonts.COLOR_PRIMARY3) : Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY3);
        canvas.drawSolidRectangle(x, 0, width, height, borderColor);

        final Color secondary2 = Toolkit.getColor(ColorsAndFonts.COLOR_SECONDARY2);
        canvas.drawRectangle(x, -1, width, height + 2, secondary2);

        int h1 = 30;
        int h2 = 10;
        if (height < h1 + h2 * 2) {
            h1 = Math.min(0, height - h2 * 2);
        } else {
            h2 = (height - h1) / 2;
        }

        final Color color = hasFocus ? Toolkit.getColor(ColorsAndFonts.COLOR_PRIMARY2) : secondary2;
        DrawingUtil.drawHatching(canvas, x + 1, h2, width - 2, h1, color, Toolkit.getColor(ColorsAndFonts.COLOR_WHITE));
    }

}


text:
package com.gyf.ec.service;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gohuinuo.common.base.ServiceMybatis;
import com.gohuinuo.web.sys.utils.SysUserUtils;
import com.gyf.ec.mapper.EcTaskProductMapper;
import com.gyf.ec.model.EcTaskProduct;

@Service("ecTaskProductService")
public class EcTaskProductService extends ServiceMybatis<EcTaskProduct> {

	@Resource
	private EcTaskProductMapper mapper;
	@Resource
	private EcTaskOfferPriceService eoService;

	/**
	 * 列表
	* @param params
	* @return
	 */
	public PageInfo<EcTaskProduct> findPageInfo(Map<String, Object> params) {
		params.put("taskUser", SysUserUtils.getCacheLoginUser().getId());
		PageHelper.startPage(params);
		List<EcTaskProduct> list = mapper.findPageInfo(params);
		return new PageInfo<EcTaskProduct>(list);
	}
	public Integer findCountByShop(Long shopid){
		return mapper.findCountByShop(shopid);
	}
	public Integer findCountBySku(Long skuId){
		return mapper.findCountBySku(skuId);
	}
}


text:
class ExtensionTtsApiControllerTest : public testing::Test {
};

// Platform Tts implementation that does nothing.
class DummyExtensionTtsPlatformImpl : public ExtensionTtsPlatformImpl {
 public:
  DummyExtensionTtsPlatformImpl() {}
  virtual ~DummyExtensionTtsPlatformImpl() {}
  virtual bool PlatformImplAvailable() { return true; }
  virtual bool Speak(
      int utterance_id,
      const std::string& utterance,
      const std::string& lang,
      const UtteranceContinuousParameters& params) {
    return true;
  }
  virtual bool StopSpeaking() { return true; }
  virtual bool SendsEvent(TtsEventType event_type) { return false; }
  virtual std::string gender() { return std::string(); }
  virtual std::string error() { return std::string(); }
  virtual void clear_error() {}
  virtual void set_error(const std::string& error) {}
};

// Subclass of ExtensionTtsController with a public ctor and dtor.
class TestableExtensionTtsController : public ExtensionTtsController {
 public:
  TestableExtensionTtsController() {}
  virtual ~TestableExtensionTtsController() {}
};

TEST_F(ExtensionTtsApiControllerTest, TestTtsControllerShutdown) {
  DummyExtensionTtsPlatformImpl platform_impl;
  TestableExtensionTtsController* controller =
      new TestableExtensionTtsController();
  controller->SetPlatformImpl(&platform_impl);

  Utterance* utterance1 = new Utterance(NULL);
  utterance1->set_can_enqueue(true);
  utterance1->set_src_id(1);
  controller->SpeakOrEnqueue(utterance1);

  Utterance* utterance2 = new Utterance(NULL);
  utterance2->set_can_enqueue(true);
  utterance2->set_src_id(2);
  controller->SpeakOrEnqueue(utterance2);

  // Make sure that deleting the controller when there are pending
  // utterances doesn't cause a crash.
  delete controller;
}


text:
/*
 * File:   File.h
 * Module: text_editor
 * Author: James Kuczynski
 * Email: jkuczyns@cs.uml.edu
 * File Description: This class inherits from class QPlainTextEdit.  It
 *                   provides dynamic highlighting and auto-insertion of text
 *                   into the GUI representation of the file.
 *
 * see: http://qtsimplify.blogspot.com/2013/08/code-editor-in-making.html
 *
 * Created on May 2, 2015, 10:47 PM
 * Last Modified: 1/13/2016
 */

#ifndef FILE_GUI_H
#define	FILE_GUI_H

#include <QWidget>
#include <QApplication>
#include <QTextEdit>
#include <QPlainTextEdit>
#include <QTextCharFormat>
#include <QRegExp>
#include <QTextObject>
#include <QPainter>
#include <QCompleter>
#include <QTextCursor>
#include <QAbstractItemView>
#include <QAbstractItemModel>
#include <QStringListModel>
#include <QScrollBar>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QSize>
#include <QPixmap>
#include <QMessageBox>

#include <iostream>

#include "Highlighter.h"
#include "RosEnv.h"
#include "WindowsConsoleText.h"
#include "UnixConsoleText.h"

#ifdef _WIN32
namespace cct = WindowsConsoleText;
#elif __APPLE
namespace cct = UnixConsoleText;
#elif __linux
namespace cct = UnixConsoleText;
#endif

using std::cout;
using std::cerr;
using std::endl;

class FileGui : public QPlainTextEdit
{
    Q_OBJECT

public:
    QColor prevColor;
    int rectCounter;
    int maxGitHeight;
    /**
     * Constructor.
     *
     * @param parent reference to parent type.
     */
    explicit FileGui(QWidget* parent = 0);

    void miniCompleterFactory();

    QAbstractItemModel* modelFromFile(const QString& fileName);

    /**
     *
     *
     * @param c
     */
    void setCompleter(QCompleter* c);

    /**
     *
     *
     * @return
     */
    QCompleter* completer() const;

    /**
     * Paints the line number on the left margin
     *
     * @param event
     */
    void lineNumberAreaPaintEvent(QPaintEvent* event);

    /**
     * This method is similar to the previous one, except that it is for
     * the code folding instead of the line numbers.
     *
     * @param event
     */
    void codeFoldingAreaPaintEvent(QPaintEvent* event);

    /**
     *
     * @param event
     */
    void gitStatusAreaPaintEvent(QPaintEvent* event);

    /**
     *
     *
     * @return
     */
    int lineNumberAreaWidth();

    /**
     *
     *
     * @return
     */
    int codeFoldingAreaWidth();

    /**
     *
     *
     * @return
     */
    int gitStatusAreaWidth();

    /**
     *
     *
     * @param event
     */
    void resizeEvent(QResizeEvent* event);

    void closeEvent(QCloseEvent* event);

    void closeEvent(QCloseEvent* event, int tabIndex);

    /**
     * Classic toString method.
     *
     * @return class data.
     */
    QString* toString();

    /**
     * Destructor.
     */
    virtual ~FileGui();

protected:
    /**
     *
     *
     * @param e
     */
    void keyPressEvent(QKeyEvent* e);

    void mouseReleaseEvent(QMouseEvent* e);

private slots:
    /**
     * Inserts the completion of the word.
     *
     * @param completion
     */
    void insertCompletion(const QString& completion);

    /**
     *
     *
     * @param newBlockCount
     */
    void updateLineNumberAreaWidth(int newBlockCount);

    /**
     *
     */
    void highlightCurrentLine();

    /**
     *
     *
     * @param
     * @param
     */
    void updateLineNumberArea(const QRect&, int);

private:
    struct HighlightingRule
    {
        QRegExp pattern;
        QTextCharFormat format;
    };

    QWidget* lineNumberArea;
    QWidget* codeFoldArea;
    QWidget* gitStatusArea;
    QCompleter* completerPtr;
    Highlighter* highlighter;

    QString wordUnderCursor() const;

};

#endif	/* FILE_GUI_H */


text:
.fieldset-switch-toggle label {
	float: none;
}

@media only screen {
	.switch-light.switch-yoast-seo {
		margin-bottom: 0.2em;
	}

	.fieldset-switch-toggle legend,
	.switch-light.switch-yoast-seo > strong {
		display: block;
		box-sizing: border-box;
		min-width: 200px;
		margin-top: 10px;
		padding-right: 1em;
		font-weight: bold;
		line-height: 2em;
		vertical-align: middle;
	}

	.switch-toggle.switch-yoast-seo,
	.switch-light.switch-yoast-seo > span {
		width: 250px;
		border: 1px solid #ccc;
		border-radius: 0.5em;
		background-color: #dcdcdc;
		box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15);
	}

	.switch-toggle.switch-yoast-seo {
		float: left;
	}

	.switch-light.switch-yoast-seo > span {
		/* to contain floats instead of the original overflow: hidden; */
		display: inline-block;
		/* to make the focus style fully visible */
		overflow: visible;
		/*float: right;*/
	}

	.switch-toggle.switch-yoast-seo a,
	.switch-light.switch-yoast-seo a {
		border-color: #b5b5b5;
		border-radius: 0.5em;
		background: #a4286a none;
	}

/* reset and rebuild focus style */
	.switch-toggle.switch-yoast-seo input:focus ~ span a,
	.switch-light.switch-yoast-seo input:focus ~ span a,
	.switch-toggle.switch-yoast-seo input:focus + label,
	.switch-light.switch-yoast-seo input:focus + label {
		outline: none;
	}

	.switch-toggle.switch-yoast-seo input:focus ~ a,
	.switch-light.switch-yoast-seo input:focus ~ span a {
		border-color: #5b9dd9;
		box-shadow: 0 0 2px rgba(0, 115, 170, 0.8);
	}

	.switch-toggle.switch-yoast-seo input:checked ~ span a,
	.switch-light.switch-yoast-seo input:checked ~ span a {
		border-color: #b5b5b5;
		background: #a4286a none;
	}

	.switch-light.switch-yoast-seo span span,
	.switch-light.switch-yoast-seo input:checked ~ span span:first-child,
	.switch-toggle.switch-yoast-seo label {
		color: #333;
		text-shadow: none;
		font-weight: inherit;
	}

	.switch-candy.switch-yoast-seo input ~ span span:first-child,
	.switch-candy.switch-yoast-seo input:checked ~ span span:nth-child(2),
	.switch-candy.switch-yoast-seo input:checked + label {
		color: #fff;
		text-shadow: none;
	}

	.switch-light.switch-yoast-seo-reverse input:checked ~ span a {
		left: 0;
	}

	.switch-light.switch-yoast-seo-reverse a {
		left: 50%;
	}

	.switch-light.switch-yoast-seo-reverse span span {
		float: right;
	}

	label.switch-yoast-seo {
		margin-left: 0;
	}

	.switch-toggle.switch-yoast-seo label code,
	.switch-light.switch-yoast-seo label code {
		background-color: inherit;
		vertical-align: top;
	}

	.switch-container h4 {
		margin: 0.5em 0;
	}

	.switch-container {
		clear: both;
		margin: 0 0 1em 0;
	}

	.switch-container + .switch-container {
		margin-top: 0.5em;
	}

	.switch-container + p {
		margin: -0.5em 0 1em 0;
	}
}


text:
<?php

namespace Notifier;

use Ratchet\ConnectionInterface;
use Ratchet\Wamp\WampServerInterface;

define('TOPIC', 'html5_test_tool.dlna.org');

class Pusher implements WampServerInterface
{
    /**
     * A lookup of all the topics clients have subscribed to
     */
    protected $subscribedTopics = array();

    public function onSubscribe(ConnectionInterface $conn, $topic) {
        echo "onSubscribe! ({$conn->resourceId})\n";
        $this->subscribedTopics[$topic->getId()] = $topic;
    }
    public function onUnSubscribe(ConnectionInterface $conn, $topic) {
        echo "onUnSubscribe! ({$conn->resourceId})\n";
    }
    public function onOpen(ConnectionInterface $conn) {
        echo "New connection! ({$conn->resourceId})\n";
    }
    public function onClose(ConnectionInterface $conn) {
        echo "Connection {$conn->resourceId} has disconnected\n";
    }
    public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {
        // In this application if clients send data it's because the user hacked around in console
        $conn->callError($id, $topic, 'You are not allowed to make calls')->close();
    }
    public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
        // In this application if clients send data it's because the user hacked around in console
        $conn->close();
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }

    /**
     * @param string JSON'ified string we'll receive from ZeroMQ
     */
    public function onBlogEntry($entry)
    {
        $entryData = json_decode($entry, true);

        // If the lookup topic object isn't set there is no one to publish to
        if (!array_key_exists(TOPIC, $this->subscribedTopics)) {
            return;
        }

        $topic = $this->subscribedTopics[TOPIC];

        // re-send the data to all the clients subscribed to that action
        $topic->broadcast($entryData);
    }
}


text:
<?php

/**
 * @file
 * Definition of Drupal\system\Tests\System\DefaultMobileMetaTagsTest.
 */

namespace Drupal\system\Tests\System;

use Drupal\Component\Utility\String;
use Drupal\simpletest\WebTestBase;

/**
 * Confirm that the default mobile meta tags appear as expected.
 *
 * @group system
 */
class DefaultMobileMetaTagsTest extends WebTestBase {
  protected function setUp() {
    parent::setUp();
    $this->default_metatags = array(
      'viewport' => '<meta name="viewport" content="width=device-width, initial-scale=1.0" />',
    );
  }

  /**
   * Verifies that the default mobile meta tags are added.
   */
  public function testDefaultMetaTagsExist() {
    $this->drupalGet('');
    foreach ($this->default_metatags as $name => $metatag) {
      $this->assertRaw($metatag, String::format('Default Mobile meta tag "@name" displayed properly.', array('@name' => $name)), 'System');
    }
  }

  /**
   * Verifies that the default mobile meta tags can be removed.
   */
  public function testRemovingDefaultMetaTags() {
    \Drupal::service('module_installer')->install(array('system_module_test'));
    $this->drupalGet('');
    foreach ($this->default_metatags as $name => $metatag) {
      $this->assertNoRaw($metatag, String::format('Default Mobile meta tag "@name" removed properly.', array('@name' => $name)), 'System');
    }
  }
}


text:
<!-- this controls all the conversations and cutscenes if you're looking
	for the actual text said in conversations, look to default(_LANG).properties -->
<conversations>

	<conversation id="dev">
		<speech speaker="" text="conv.dev0" cutscene="stunning" />
		<speech speaker="" text="conv.dev1" cutscene="stunning2" />
		<speech speaker="" text="conv.dev2" cutscene="stunning" />
		<speech speaker="" text="conv.dev3" cutscene="stunning2" />
		<speech speaker="" text="conv.dev4" cutscene="stunning" />
	</conversation>

	<conversation id="newgame">
        <speech speaker="child" text="conv.newgame0" voice="child0" />
        <speech speaker="child" text="conv.newgame1" voice="child1" />
        <speech speaker="child" text="conv.newgame2" voice="child2" />
    </conversation>

	<conversation id="mapwip">
		<speech speaker="sign" text="conv.mapwip"  />
	</conversation>

	<conversation id="secretexit">
        <speech speaker="sign" text="conv.secretexit"  />
    </conversation>

	<conversation id="missing">
        <speech speaker="" text="conv.missingsign"  />
    </conversation>

	<conversation id="controls">
		<speech speaker="" text="conv.controls0" cutscene="controls0" />
		<speech speaker="" text="conv.controls1" cutscene="controls1" />
		<speech speaker="" text="conv.controls2" cutscene="controls2" />
	</conversation>

	<conversation id="beginning">
        <speech speaker="" text="conv.beginning0" cutscene="" />
        <speech speaker="" text="conv.beginning1" cutscene="" />
        <speech speaker="" text="conv.beginning2" cutscene="" />
        <speech speaker="" text="conv.empty" cutscene="scientistface" />
        <speech speaker="scientist" text="conv.beginning4" cutscene="scientistface" />
        <speech speaker="scientist" text="conv.beginning5" cutscene="scientistface" />
        <speech speaker="scientist" text="conv.beginning6" cutscene="scientistface" />
        <speech speaker="scientist" text="conv.beginning7" cutscene="scientistface" />
        <speech speaker="scientist" text="conv.beginning8" cutscene="scientistface" />
        <speech speaker="scientist" text="conv.beginning9" cutscene="scientistface" />
    </conversation>

</conversations>


text:
export default class ODataToEntitiesConverter {
    private readonly regEdmCollection;
    private readonly propertyTemplate;
    private readonly classTemplate;
    private readonly classWithInheritanceTemplate;
    private readonly typeTemplate;
    private readonly edmTemplate;
    private moduleName;
    private typeMapping;
    constructor(moduleName?: string);
    MapPrimitiveEdmTypes(): string;
    MapEdmClasses: (odataMetadata: string) => string;
    private MapEdmProperties;
    private GetEdmTypes;
}


text:
package com.tq.requisition.infrastructure.Specifications.transferMgt;

import java.util.ArrayList;
import java.util.List;

import com.tq.requisition.domain.Specification.Specification;
import com.tq.requisition.domain.Specification.expression.IHqlExpression;
import com.tq.requisition.domain.Specification.expression.OperationType;
import com.tq.requisition.domain.model.transferHouseholdInfo.TransferHouseholdInfo;
import com.tq.requisition.infrastructure.Specifications.Expression.HqlExpression;
import com.tq.requisition.presentation.dto.transferMgt.TransferInfoQueryModel;

/**
 * 转户批量新增前查询总行数规约
 * @author jjh
 * @time 2015-12-31 17:34
 */
public class TransferAddCountSpecification extends Specification<TransferHouseholdInfo>{
	private TransferInfoQueryModel queryModel;

	public TransferAddCountSpecification(Class<TransferHouseholdInfo> _t,TransferInfoQueryModel queryModel) {
		super(_t);
		this.queryModel = queryModel;
	}

	@Override
	public IHqlExpression getHqlExpression() {
		IHqlExpression expression = new HqlExpression();
		StringBuilder sb = new StringBuilder();
		List<Object> list = new ArrayList<Object>();
		sb.append("select count(1) from tb_family_item where is_transferd=0 ");
		if(queryModel.getProName()!=null)
		{
			sb.append(" and pro_name like " + "'%" + queryModel.getProName() + "%'");
		}
		if(queryModel.getCommunityId()!=null)
		{
			sb.append(" and community_id=?");
			list.add(queryModel.getCommunityId().toString());
		}
		if(queryModel.getStreetId()!=null)
		{
			sb.append(" and street_id=?");
			list.add(queryModel.getStreetId().toString());
		}
		if(queryModel.getIdNumber()!=null && !(queryModel.getIdNumber().trim().equals(""))){
			sb.append(" and id_number=?");
			list.add(queryModel.getIdNumber());
		}
		if(queryModel.getGroupId()!=null){
			sb.append(" and group_id=?");
			list.add(queryModel.getGroupId().toString());
		}

		Object[] objects = new Object[list.size()];
		for (int i = 0; i < list.size(); i++) {
			objects[i] = list.get(i);
		}
		expression.setParameters(objects);
		expression.setSql(sb.toString());
		expression.setType(OperationType.SQL);
		return expression;
	}

}


text:
\documentclass[12pt]{article}
\usepackage{latexsym}
\usepackage{fancyhdr}
\usepackage{amssymb,amsmath,amsthm}
\usepackage[pdftex]{graphicx}
\usepackage{pdfpages}
\usepackage[margin=1in]{geometry}

% Create answer counter to keep track of seperate responses
\newcounter{AnswerCounter}
\newcounter{SubAnswerCounter}
\setcounter{AnswerCounter}{1}
\setcounter{SubAnswerCounter}{1}

% Create answer environment which uses counter
\newenvironment{answer}[0]{
  \setcounter{SubAnswerCounter}{1}
  \bigskip
  \textbf{Solution \arabic{AnswerCounter}}
  \\
  \begin{small}
}{
  \end{small}
  \stepcounter{AnswerCounter}
}

\newenvironment{subanswer}[0]{
  (\alph{SubAnswerCounter})
}{
 \bigskip
  \stepcounter{SubAnswerCounter}
}

% Allows easy use of vectors
\newcommand{\vect}[1]{\vec{\boldsymbol{#1}}}

% Setting up the title
\title{Mathematics 131 \\
Topology I}
\author{
        Luis Antonio Perez \\
        HUID: 70871564 \\
        Harvard College \\
        \href{mailto:luisperez@college.harvard.edu}{luisperez@college}
}
\date{\today}

% Custom Header information on each page
\pagestyle{fancy}
\lhead{HUID: 70871564}
\rhead{Perez - \thepage}
\renewcommand{\headrulewidth}{0.1pt}
\renewcommand{\footrulewidth}{0.1pt}

% Title page is page 0
\setcounter{page}{0}

\begin{document}
\begin{answer}[Page 425, \#1]
We show that if $G = G_1 * G_2$, then $G/[G,G] \tilde{=} (G_1 / [G_1, G_2) \oplus (G_2/[G_2, G_2])$.
\begin{proof}
We ignore the hint, instead constructing the specified homomorphisms directly. First note that $G/[G, G]$, $G_1/[G_1,G_1]$, and $G_2 / [G_2, G_2]$ are abelian, by Lemma 69.3 in Munkres. Then define the homomorphism $\Phi: G/[G,G] \to G_1/[G_1,G_1] \oplus G_2/[G_2,G_2]$, as follows:
$$
xy[G,G] \mapsto x[G_1,G_1] + y[G_2,G_2]
$$
where $x \in G_1, y \in G_2$ which must be the case because $G = G_1 * G_2$.
Note that using the extension property, the above is well-defined and is clearly a surjective homomorphism. Now we just need to show that $\Phi$ is injective. First, let us be clear about the identity elements for each group.
$$
0_{G/[G,G]} = [G,G], 0_{G_1/[G_1,G_1]} = [G_1,G_1], 0_{G_2/[G_2,G_2]} = [G_2,G_2]
$$
Assume that $xyx^{-1}y^{-1} \mapsto [G_1, G_1] \oplus [G_2, G_2]$, with $xx^{-1} \in [G_1,G_1] \subset [G,G]$ and $yy^{-1} \in [G_2,G_2] \subset [G,G]$, so using the fact the the groups are abelian:
$$
xyx^{-1}y^{-1}[G,G] = xx^{-1}yy^{-1}[G,G] = [G,G] = 0_{G/[G,G]}
$$
Following similar logic, we have that if $\prod_i x_iy_i[G,G] \to [G_1,G_1] \oplus [G_2,G_2]$, using abelian properties:
$$
\prod_i x_i \in [G_1,G_1] \subset [G,G], \prod_i y_i \in [G_2,G_2] \subset [G,G]
$$
which simplifies to:
$$
\prod_i x_iy_i[G,G] = \left( \prod_i x_i \right)\left( \prod_i y_i \right)[G,G] = [G,G]
$$
Therefore, $\Phi$ must be injective, and is the desired isomorphism.
\end{proof}
Therefore $\Phi$ are injective, which defines the desired isomorphism.
\end{answer}

\begin{answer}[Page 425, \#4]
We show that if $G = G_1 \oplus G_2$, where $G_1,G_2$ are cyclic of orders $m,n$, respectively, then $m$  and $n$ are not uniquely determined by $G$ in general.
\begin{proof}
Following the hint, suppose $m,n$ are relatively prime. Then the order of $G$ is clearly $mn$. Consider an element $g = g_1 + g_2 \in G$ where $g_1,g_2$ are the generators of $G_1,G_2$ respectively. First, we have $mng = mn(g_1 + g_2) = mng_1 + mng_2 = n(mg_1) + m(ng_2) = n0 + m0 = 0$. Therefore, it must be the case that the order $d$ of $g$ must divide $mn$. Because $m,n$ are relative prime, it must be the case that $d = mn$. This implies that the order $d$ does not always directly determine the orders $m,n$ of $G_1,G_2$.
\end{proof}
\end{answer}

\begin{answer}[Page 433, \#1]
We suppose that the homomorphism $i_*$ induced by inclusion $i: U \cap V \to X$ is trivial. We will reference Diagram throughout this question.
\begin{figure}[h!]
\centering
\caption{Homomorphism Diagram}
\label{diag:homomorphisms}
\includegraphics{map_diagram.png}
\end{figure}
\begin{itemize}
\item We show that $j_1, j_2$ induces an epimorphism:
$$
h: (\pi_1(U,x_0)/N_1) * (\pi_1(V,x_0)/N_2) \to \pi_1(X,x_0)
$$
where $N_1$ is the least normal subgroup of $\pi_1(U,x_0)$ containing image $i_1$ and $N_2$ is the least normal subgroup of $\pi_1(V,x_0)$ containing image $i_2$.
\begin{proof}
First note that $i_* = j_1 \circ i_1$ and $i_* = j_2 \circ i_2$. Therefore, the image of $i_1$ is contained in both the $\text{ker}(j_1)$ and in $N_1$, and the image of $i_2$ is contained in both the $\text{ker}(j_2)$ and in $N_2$. This implies that $N_1$ is a subgroup of $\text{ker}(j_1)$, and similarly, $N_2$ is a subgroup of $\text{ker}(j_2)$. (They are both the least normal subgroups). Therefore, it must be possible to find homomorphisms $h_1: \pi_1(U,x_0)/N_1 \to \pi_1(X,x_0)$ and $h_2: \pi_1(V,x_0)/N_2 \to \pi_1(X,x_0)$ such that $j_1 = h_1 \circ \text{proj}_{\pi_1(U,x_0)/N_1}$ and $j_2 = h_2 \circ \text{proj}_{\pi_1(V,x_0)/N_2}$ since we lose no information in the projection that wouldn't have been lost by $j_*$ already. Then we can define:
$$
h: \pi_1(U,x_0)/N_1 * \pi_1(V,x_0)/N_1 \to \pi_1(X,x_0)
$$
as the extension of $h_1,h_2$ to the free product. Then consider the map induced by inclusions $j: \pi_1(U,x_0) * \pi_2(V,x_0) \to \pi(X,x_0)$, and note that it is an epimorphism (onto map). Then note, additionally, that we can write $j = h \circ \text{proj}_{\pi_1(U,x_0)/N_1 * \pi_1(V,x_0)/N_2}$ without loss of information. Therefore, $h$ must also be an epimorphism, as desired.
\end{proof}
\item We show that $h$ is an isomorphism.
\begin{proof}
We make use of Theorem 70.1. Let the assumptions of the theorem hold, with $H = \pi_1(U,x_0)/N_1 * \pi_2(V,x_0)/N_2$. Then note that $\phi_1$ is defined as the coset projection of $\pi(U,x_0)$ followed by inclusion into the free product. Similarly for $\phi_2$. And lastly, note that the equation $\phi_1 \circ i_i = \phi_2 \circ i_2$ is satisfied, as it is the coset projection of the intersection followed by inclusion. By Theorem 70.1, there exists a unique homomorphism $\Phi: \pi_1(X,x_0) \to  \pi_1(U,x_0)/N_1 * \pi_2(V,x_0)/N_2$ such that $\Phi \circ j_1 = \phi_1$ and $\Phi \circ j_2 = \phi_2$. We claim that $\Phi$ is the left inverse of $h$. To see this, note:
\begin{align*}
\Phi \circ h \circ \phi_1 &= \Phi \circ h \circ \text{inclusion}_{\pi_1(U,x_0)/N_1 * \pi_1(V,x_0)/N_2} \circ \text{proj}_{\pi_1(U,x_0)/N_1} \tag{definition of $\phi_1$} \\
&= \Phi \circ h_1 \circ \text{proj}_{\pi_1(U,x_0)/N_1} \tag{definition of $h$ as extension of $h_1,h_2$} \\
&= \Phi \circ j_1 \tag{see above} \\
&= \phi_1 \tag{definition of $\phi_1$}
\end{align*}
Similarly, for $\phi_2$ we have that $\Phi \circ h \circ \phi_2 = \phi_2$. Combining these two results with the fact that $\pi_1(U,x_0)/N_1 * \pi_1(V,x_0)/N_1$ is generated by $im (\phi_1)$ and $im(\phi_2)$, we must have that $\Phi \circ h = id$. Therefore, $\Phi$ is the left inverse of $h$, so $h$ must be injective. Combined with the results from above, this means that $h$ is an isomorphism.
\end{proof}
\end{itemize}
\end{answer}

\begin{answer}[Page 438, \#2]
We let $X$ be a space that is the union of closed subspaces $X_1, \cdots, X_n$, and let $p \in X$ be a point such that $X_1 \cap X_j = \{p\}$ for $i \neq j$.Then we call $X$ the wedge of the spaces $X_1, \cdots X_n$ and write $X = X_1 \lor \cdots \lor X_n$. We show that if for each $i$ the point $p$ is a deformation retract of an open set $W_i$ of $X_i$, then $\pi_1(X,p)$ is the external product of the groups $\pi_1(X_i,p)$ relative to the monomorphisms induced by inclusions.
\begin{proof}
The proof follows a format similar to Theorem 71.1. We proof by induction. Note that for the case of $n= 1$, the result follow trivially. \\

Now, let $X$ be the wedge of the spaces $X_1, \cdots, X_k$ with $p$ the common point. Then define the following two sets:
\begin{align*}
U &= X_1 \cup W_2 \cup \cdots \cup W_n \\
V &= W_1 \cup X_2 \cup \cdots X_n
\end{align*}
Then note that $U \cap V = W_1 \cup \cdots \cup W_n$. Let $F_i: W_i \times I \to W_i$ be the deformation retraction. The maps $F_i$ fit together to define a map $F: (U \cap V) \times I \to U \cap V$ that is a deformation retraction of $U \cap V$ onto $p$. To show continuity, note that $W_i$ are closed subspaces of $U \cap V$, so that $W_i \times I$ is a closed subspace of $(U \cap V) \times I$. Then the pasting lemma applies). It follows from this that $U \cap V$ is simply connected, so that $\pi_1(X,p)$ is the free product of the groups $\pi_1(U,p)$ and $\pi_1(V,p)$, relative to the mono-morphisms induced by inclusion. This implies that it is the external free product of these groups. \\

By a similar argument, note that the maps fit together to form $F_U: U \to U$, a reformation retract of $U$ onto $X_1$. Similarly, $X_2 \cup \cdots \cup X_n$ is a deformation retract of $V$. From this, it follows that $\pi_1(U,p)$ is is equivalent to $\pi_1(X_1,p)$. By the inductive hypothesis, it also follows that $\pi_1(V,p)$ is a the external product of the groups $\pi_1(X_2,p),\cdots, \pi_1(X_n,p)$. Therefore, we have that $\pi_1(X,p)$ is the external product of $\pi_1(X_i,p)$.
\end{proof}
\end{answer}

\begin{answer}[Page 445, \#1]
We find spaces whose fundamental groups are isomorphic to the following groups (where $\mathbb{Z}/n$ denote the additive group of integers modulo $n$).
\begin{enumerate}
\item $\mathbb{Z}/n \times \mathbb{Z}/m$: We let $X_n$ be the $n$-fold dunce cap and $X_m$ be the $m$-fold dunce cap. Then by Theorem 73.4, $\pi_1(X_n,x_0) \tilde{=} \mathbb{Z}/n$ and $\pi_1(X_m,x_1) \tilde{=} \mathbb{Z}/m$. Therefore, we let $X = X_1 \times X_2$. Then $\pi_1(X,(x_0,x_1)) \tilde{=} \pi_1(X_n,x_1) \times \pi_1(X_m,x_1) \tilde{=} \mathbb{Z}/n \times \mathbb{Z}/m$.
\item We can immediately see by induction on the above, that the space we need is $X = X_1 \times X_{n_{2}} \times  \cdots \times X_{n_k}$. Where $X_{n_i}$ is the $n_i$-fold dunce cap.
\item Using the results from Exercise 2 of Section 71, we can again let $X_n, X_m$ be the $n$ and $m$-fold dunce caps, respectively. Then by the results from Exercise 2 of Section 71, $\pi_1(X_n \lor X_m, x_0) \tilde{=} \pi_1(X_n,x_0) * \pi_1(X_m,x_0) \tilde{=} \mathbb{Z}/n \times \mathbb{Z}/m$.
\item Using the results from above, and by the fact the free product is associative, we can use induction to show that the space we need is $X = X_{n_1} \lor X_{n_2} \lor \cdots \lor X_{n_k}$ because then we have $\pi_1(X,x_0) \tilde{=} \pi_1(X_{n_1}, x_0) * \pi_1(X_{n_2},x_0) * \cdots * \pi_1(X_{n_k},x_0) \tilde{=} \mathbb{Z}/n_1 * \mathbb{Z}/n_2 * \cdots * \mathbb{Z}/n_k$.
\end{enumerate}
\end{answer}

\end{document}


text:
package xyz.lovemma.zhihudaily.ui.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.zhy.adapter.recyclerview.wrapper.LoadMoreWrapper;

import java.util.ArrayList;
import java.util.List;

import xyz.lovemma.zhihudaily.R;
import xyz.lovemma.zhihudaily.bean.BaseItem;
import xyz.lovemma.zhihudaily.bean.BeforeStories;
import xyz.lovemma.zhihudaily.bean.LatestStories;
import xyz.lovemma.zhihudaily.mvp.presenter.StoriesPresenter;
import xyz.lovemma.zhihudaily.mvp.view.IStoriesView;
import xyz.lovemma.zhihudaily.ui.adapter.home.StoriesHeader;
import xyz.lovemma.zhihudaily.ui.adapter.home.StoriesListAdapter;
import xyz.lovemma.zhihudaily.ui.adapter.home.StoriesSection;

public class DailyStoriesFragment extends Fragment implements IStoriesView {
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private RecyclerView mRecyclerView;
    private StoriesPresenter mPresenter;
    private final List<BaseItem> mItemList = new ArrayList<>();
    private LoadMoreWrapper mLoadMoreWrapper;
    private String date;
    private boolean isRefresh;

    public DailyStoriesFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_daily_stories, container, false);
        mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_layout);
        mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initData();
        initView();
    }

    private void initData() {
        mPresenter = new StoriesPresenter(this);
        StoriesListAdapter adapter = new StoriesListAdapter(getContext(), mItemList);
        mLoadMoreWrapper = new LoadMoreWrapper(adapter);
    }

    private void initView() {
        mLoadMoreWrapper.setLoadMoreView(R.layout.default_loading);
        mLoadMoreWrapper.setOnLoadMoreListener(new LoadMoreWrapper.OnLoadMoreListener() {
            @Override
            public void onLoadMoreRequested() {
                if (date != null) {
                    mPresenter.getBeforeDaily(date);
                }
            }
        });
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.setAdapter(mLoadMoreWrapper);
        mPresenter.getLatestStories();
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                isRefresh = true;
                mPresenter.getLatestStories();
            }
        });
    }

    @Override
    public void onDestroy() {
        mPresenter.unSubcrible();
        mItemList.clear();
        super.onDestroy();
    }

    @Override
    public void onRequestError(String msg) {
        Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void loadLatestStories(LatestStories latestStories) {
        if (isRefresh) {
            mItemList.clear();
            mLoadMoreWrapper.notifyDataSetChanged();
        }
        date = latestStories.getDate();
        mItemList.add(new StoriesHeader(latestStories.getTop_stories()));
        mItemList.add(new StoriesSection(latestStories.getDate()));
        mItemList.addAll(latestStories.getStories());
        mLoadMoreWrapper.notifyDataSetChanged();
        mSwipeRefreshLayout.setRefreshing(false);
        isRefresh = true;
    }

    @Override
    public void loadBeforeStories(BeforeStories beforeStories) {
        date = beforeStories.getDate();
        mItemList.add(new StoriesSection(beforeStories.getDate()));
        mItemList.addAll(beforeStories.getStories());
        mLoadMoreWrapper.notifyDataSetChanged();
    }
}


text:
/*************************************************************************/
/*  space_2d.h                                                           */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#ifndef SPACE_2D_H
#define SPACE_2D_H

#include "resource.h"
#include "servers/physics_2d_server.h"

class Space2D : public Resource {

	OBJ_TYPE(Space2D, Resource);
	bool active;
	RID space;

protected:
	static void _bind_methods();

public:
	void set_active(bool p_active);
	bool is_active() const;

	virtual RID get_rid() const;

	Space2D();
	~Space2D();
};

#endif // SPACE_2D_H


text:
<?php include "header.php"; ?>

			Our Projects

			Projects are an integral part of the living, learning experience at Computer Science House. This is a small sample of our notable projects that our members have created:

Drink/Snack

						Drink and snack are two of CSH's oldest projects. Networked vending machines allow members to order items from any internet browser using a credits system. A timer can also be specified to delay the release of a purchased item.

Schedule Maker

						Schedule Maker allows RIT students to plan their schedule for upcoming semesters. Users simply enter their course numbers and custom events and a list of all schedules that match their parameters will be shown. Because it is so easy and simple, Schedule Maker is now used by over 90% of RIT students.

CSH Arcade

						Two CSH members built this arcade cabinet from scratch. It emulates many classic arcade games from varying consoles and supports multiplayer. A second cabinet featuring a cusom-made platforming game was also built. Both machines, along with other arcade cabinets CSH has acquired, are housed in our Library.

Harold

						With Harold, every member of CSH gets their own personal theme song. Audio clips can be uploaded and selected via a simple web interface and are played when a user touches their iButton (received upon membership) to an appropriate reader.

InfoSys

						InfoSys is a multi-purpose display board located in our User Center. It is capable of displaying weather statistics, custom messages, and even real-time player data from video games.

Heroine

						An ongoing companion project to Drink, Heroine is a robot that will retrieve purchased drink items and bring them to the room of any specified member. The robot has the ability to navigate obstacles and can always determine its location on floor.

<?php include "footer.php"; ?>