text:
goog.provide('acgraph.vector');
goog.provide('acgraph.vector.Anchor');
goog.provide('acgraph.vector.Cursor');
goog.provide('acgraph.vector.ILayer');

goog.require('acgraph.math');
goog.require('goog.math.AffineTransform');
goog.require('goog.math.Rect');

/**
 A namespace for working with vector graphics.
 @namespace
 @name acgraph.vector
 */

/**
 The list of positions for an anchor.
 @enum {string}
 */
acgraph.vector.Anchor = {
  /** The left-top anchor of the element. */
  LEFT_TOP: 'left-top',

  /** The left-center anchor of the element. */
  LEFT_CENTER: 'left-center',

  /** The left-bottom anchor of the element. */
  LEFT_BOTTOM: 'left-bottom',

  /** The center-top anchor of the element. */
  CENTER_TOP: 'center-top',

  /** The center anchor of the element. */
  CENTER: 'center',

  /** The center-bottom anchor of the element. */
  CENTER_BOTTOM: 'center-bottom',

  /** The right-top anchor of the element. */
  RIGHT_TOP: 'right-top',

  /** The right-center anchor of the element.*/
  RIGHT_CENTER: 'right-center',

  /** The right-bottom anchor of the element. */
  RIGHT_BOTTOM: 'right-bottom'
};

/**
 Defines the type of the cursor.

 To view the example, point the cursor at the description of the type.
 @enum {string}
 */
acgraph.vector.Cursor = {
  /** Default type */
  DEFAULT: 'default',

  /** Crosshair type */
  CROSSHAIR: 'crosshair',

  /** Pointer type */
  POINTER: 'pointer',

  /** Move type */
  MOVE: 'move',

  /** Text type */
  TEXT: 'text',

  /** Wait type */
  WAIT: 'wait',

  /** Help type */
  HELP: 'help',

  /** N-resize type */
  N_RESIZE: 'n-resize',

  /** NE-resize type */
  NE_RESIZE: 'ne-resize',

  /** E-resize type */
  E_RESIZE: 'e-resize',

  /** SE-resize type */
  SE_RESIZE: 'se-resize',

  /** S-resize type */
  S_RESIZE: 's-resize',

  /** SW-resize type */
  SW_RESIZE: 'sw-resize',

  /** W-resize type */
  W_RESIZE: 'w-resize',

  /** NW-resize type */
  NW_RESIZE: 'nw-resize',

  /** NS-resize type */
  NS_RESIZE: 'ns-resize',

  /** EW-resize type */
  EW_RESIZE: 'ew-resize',

  /** NWSE-resize type */
  NWSE_RESIZE: 'nwse-resize',

  /** NESW-resize type */
  NESW_RESIZE: 'nesw-resize'
};

/**
 * Gets the coordinates of the anchor at the bound.
 * @param {goog.math.Rect} bounds The bound rectangle.
 * @param {(acgraph.vector.Anchor|string)} anchor The anchor for which it is necessary to get the coordinates.
 * @return {Array.<number>} The coordinates of the anchor as [x, y].
 */
acgraph.vector.getCoordinateByAnchor = function(bounds, anchor) {
  var x = bounds.left;
  var y = bounds.top;
  anchor = anchor.toLowerCase();
  switch (anchor) {
    case acgraph.vector.Anchor.LEFT_TOP:
      break;
    case acgraph.vector.Anchor.LEFT_CENTER:
      y += bounds.height / 2;
      break;
    case acgraph.vector.Anchor.LEFT_BOTTOM:
      y += bounds.height;
      break;
    case acgraph.vector.Anchor.CENTER_TOP:
      x += bounds.width / 2;
      break;
    case acgraph.vector.Anchor.CENTER:
      x += bounds.width / 2;
      y += bounds.height / 2;
      break;
    case acgraph.vector.Anchor.CENTER_BOTTOM:
      x += bounds.width / 2;
      y += bounds.height;
      break;
    case acgraph.vector.Anchor.RIGHT_TOP:
      x += bounds.width;
      break;
    case acgraph.vector.Anchor.RIGHT_CENTER:
      x += bounds.width;
      y += bounds.height / 2;
      break;
    case acgraph.vector.Anchor.RIGHT_BOTTOM:
      x += bounds.width;
      y += bounds.height;
      break;
  }
  return [x, y];
};

/**
 * @interface
 */
acgraph.vector.ILayer = function() {
};

/**
 * @param {!acgraph.vector.Element} child .
 * @return {!acgraph.vector.ILayer} .
 */
acgraph.vector.ILayer.prototype.addChild;

/**
 * @param {acgraph.vector.Element} element Element to be removed.
 * @return {acgraph.vector.Element} Removed element or null.
 */
acgraph.vector.ILayer.prototype.removeChild;

/**
 * @param {acgraph.vector.Element} child .
 */
acgraph.vector.ILayer.prototype.notifyRemoved;

/**
 * @return {acgraph.vector.Stage} Stage (may be null).
 */
acgraph.vector.ILayer.prototype.getStage;

/**
 Gradient keys.
 @typedef {{
      offset: number,
      color: (string),
      opacity: (number|undefined)
    }}
 */
acgraph.vector.GradientKey;

/**
 Fill.
 @typedef {{
       color:string,
       opacity:(number|undefined)
     }}
 */
acgraph.vector.SolidFill;

/**
 Linear gradient.
 @typedef {{
      keys: !Array.<(acgraph.vector.GradientKey|string)>,
      angle: (number|undefined),
      mode: (boolean|!goog.math.Rect|undefined),
      opacity: (number|undefined)
    }}
 */
acgraph.vector.LinearGradientFill;

/**
 Radial gradient fill.
 @typedef {{
       keys: !Array.<(acgraph.vector.GradientKey|string)>,
       cx: number,
       cy: number,
       mode: (goog.math.Rect|undefined),
       fx: (number|undefined),
       fy: (number|undefined),
       opacity: (number|undefined)
     }}
 */
acgraph.vector.RadialGradientFill;

/**
 Image fill.
 @typedef {{
      src: string,
      mode: (acgraph.vector.ImageFillMode|undefined),
      opacity: (number|undefined)
    }}
 */
acgraph.vector.ImageFill;

/**
 Any color fill.
 @typedef {!(
       string |
       acgraph.vector.SolidFill |
       acgraph.vector.LinearGradientFill |
       acgraph.vector.RadialGradientFill
     )} acgraph.vector.ColoredFill
 */
acgraph.vector.ColoredFill;

/**
 Any fill.
 @typedef {!(
      string |
      acgraph.vector.ImageFill |
      acgraph.vector.SolidFill |
      acgraph.vector.LinearGradientFill |
      acgraph.vector.RadialGradientFill |
      acgraph.vector.PatternFill
    )} acgraph.vector.Fill
 */
acgraph.vector.Fill;

/**
 Solid color line.
 @typedef {{
      color: string,
      thickness: (number|undefined),
      opacity: (number|undefined),
      dash: (string|undefined),
      lineJoin: (string|undefined),
      lineCap: (string|undefined)
    }}
 */
acgraph.vector.SolidStroke;

/**
 Linear gradient stroke.
 @typedef {{
      keys: !Array.<(acgraph.vector.GradientKey|string)>,
      angle: (number|undefined),
      mode: (boolean|!goog.math.Rect|undefined),
      opacity: (number|undefined),
      thickness: (number|undefined),
      dash: (string|undefined),
      lineJoin: (string|undefined),
      lineCap: (string|undefined)
    }}
 */
acgraph.vector.LinearGradientStroke;

/**
 Radial gradient stroke.
 @typedef {{
      keys: !Array.<(acgraph.vector.GradientKey|string)>,
      cx: number,
      cy: number,
      mode: (goog.math.Rect|undefined),
      fx: (number|undefined),
      fy: (number|undefined),
      opacity: (number|undefined),
      thickness: (number|undefined),
      dash: (string|undefined),
      lineJoin: (string|undefined),
      lineCap: (string|undefined)
    }}
 */
acgraph.vector.RadialGradientStroke;

/**
 Any stroke.
 @typedef {!(
      string |
      acgraph.vector.SolidStroke |
      acgraph.vector.LinearGradientStroke |
      acgraph.vector.RadialGradientStroke
    )} acgraph.vector.Stroke
 */
acgraph.vector.Stroke;

/**
 Text shadow settings definition.
 @typedef {{
    offsetX: string,
    offsetY: string,
    blurRadius: string,
    color: string
 }}
 */
acgraph.vector.TextShadow;

/**
 * A shortcut for Fill or Stroke or PatternFill.
 * @typedef {acgraph.vector.Fill|acgraph.vector.Stroke|acgraph.vector.PatternFill}
 */
acgraph.vector.AnyColor;

/**
 Format of style the text. May be applied to plain and html texts.
 @typedef {{
    fontSize: (string|number|undefined),
    color: (string|undefined),
    fontFamily: (string|undefined),
    direction: (acgraph.vector.Text.Direction|string|undefined),
    fontStyle: (acgraph.vector.Text.FontStyle|string|undefined),
    fontVariant: (acgraph.vector.Text.FontVariant|string|undefined),
    fontWeight: (number|string|undefined),
    letterSpacing: (number|string|undefined),
    decoration: (acgraph.vector.Text.Decoration|string|undefined),
    opacity: (number|undefined),
    lineHeight: (string|number|undefined),
    textIndent: (number|undefined),
    textShadow: (string|undefined),
    vAlign: (acgraph.vector.Text.VAlign|string|undefined),
    hAlign: (acgraph.vector.Text.HAlign|string|undefined),
    width: (number|string|undefined),
    height: (number|string|undefined),
    wordWrap: (string|undefined),
    wordBreak: (string|undefined),
    textOverflow: (acgraph.vector.Text.TextOverflow|string|undefined),
    selectable: (boolean|undefined)
 }}
 */
acgraph.vector.TextStyle;

/**
 Text segment.
 @typedef {{
    fontStyle: (string|undefined),
    fontVariant: (string|undefined),
    fontFamily: (string|undefined),
    fontSize: (string|number|undefined),
    fontWeight: (number|string|undefined),
    color: (string|undefined),
    letterSpacing: (string|undefined),
    decoration: (string|undefined),
    opacity: (number|undefined)
 }}
 */
acgraph.vector.TextSegmentStyle;

/**
 Line joins.
 More at: StrokeLinejoinProperty
 @enum {string}
 */
acgraph.vector.StrokeLineJoin = {
  MITER: 'miter',
  ROUND: 'round',
  BEVEL: 'bevel'
};

/**
 Line caps.
 StrokeLinecapProperty
 @enum {string}
 */
acgraph.vector.StrokeLineCap = {
  BUTT: 'butt',
  ROUND: 'round',
  SQUARE: 'square'
};

/**
 * Image fill modes.
 * @enum {string}
 */
acgraph.vector.ImageFillMode = {
  /**
   * Stretches image, proportions are not kept.
   */
  STRETCH: 'stretch',
  /**
   * Fit by greater side.
   */
  FIT_MAX: 'fit-max',
  /**
   * Fit by lesser side.
   */
  FIT: 'fit',
  /**
   * Tiling.
   */
  TILE: 'tile'
};

/**
 * Paper sizes.
 * @enum {string}
 */
acgraph.vector.PaperSize = {
  /**
   * It measures 8.5 by 11 inches (215.9 mm x 279.4 mm). US Letter size is a recognized standard adopted by the American National Standards Institute (ANSI) whereas the A4 is the International Standard (ISO) used in most countries.
   */
  US_LETTER: 'us-letter',

  /**
   * The base A0 size of paper is defined as having an area of 1 m2. Rounded to the nearest millimetre, the A0 paper size is 841 by 1,189 millimetres (33.1 in × 46.8 in). Successive paper sizes in the series A1, A2, A3, and so forth, are defined by halving the preceding paper size across the larger dimension.
   */
  A0: 'a0',

  /**
   * A1 measures 594 × 841 millimeters or 23.4 × 33.1 inches.
   */
  A1: 'a1',

  /**
   * A2 measures 420 × 594 millimeters or 16.5 × 23.4 inches.
   */
  A2: 'a2',

  /**
   * The A3 size print measures 29.7 x 42.0cm, 11.69 x 16.53 inches, if mounted 40.6 x 50.8cm, 15.98 x 20 inches. The A4 size print measures 21.0 x 29.7cm, 8.27 x 11.69 inches, if mounted 30.3 x 40.6cm, 11.93 x 15.98 inches.
   */
  A3: 'a3',

  /**
   * A transitional size called PA4 (210 mm × 280 mm or 8.27 in × 11.02 in) was proposed for inclusion into the ISO 216 standard in 1975. It has the height of Canadian P4 paper (215 mm × 280 mm, about 8½ in × 11 in) and the width of international A4 paper (210 mm × 297 mm or 8.27 in × 11.69 in).
   */
  A4: 'a4',

  /**
   * A5 measures 148 × 210 millimeters or 5.83 × 8.27 inches.
   */
  A5: 'a5',

  /**
   * A6 measures 105 × 148 millimeters or 4.13 × 5.83 inches. In PostScript, its dimensions are rounded off to 298 × 420 points. The matching envelope format is C6 (114 × 162 mm).
   */
  A6: 'a6'
};

/**
 * Converts string representation of transformations to goog.math.AffineTransform object.
 * @param {string} value
 * @return {goog.math.AffineTransform}
 */
acgraph.vector.parseTransformationString = function(value) {
  var i, j, len, len_;

  var transforms = value.trim()
      .replace(/\(\s+/gi, '(')
      .replace(/\s+\)/gi, ')')
      .replace(/(\s+,\s+)|(\s+)/gi, ',')
      .replace(/(\)),*(\w)/gi, '$1 $2')
      .split(' ');

  var tx = new goog.math.AffineTransform();

  for (j = 0, len_ = transforms.length; j < len_; j++) {
    var transform = transforms[j];

    var r = /^(matrix|translate|rotate|scale|skewX|skewY)\(([e\d.,-]+)\)/i;
    var result = r.exec(transform);
    var type = result[1];
    var params = /** @type {Array.<number>} */(result[2].split(','));
    for (i = 0, len = params.length; i < len; i++) {
      params[i] = parseFloat(params[i]);
    }

    switch (type) {
      case 'matrix':
        var new_tx = new goog.math.AffineTransform(params[0], params[1], params[2], params[3], params[4], params[5]);
        tx.concatenate(new_tx);
        break;
      case 'translate':
        tx.translate(params[0], params[1] || 0);
        break;
      case 'rotate':
        tx.rotate(goog.math.toRadians(params[0]), params[1] || 0, params[2] || 0);
        break;
      case 'scale':
        tx.scale(params[0], params[1] || 0);
        break;
      case 'skewX':
        tx.shear(Math.tan(goog.math.toRadians(params[0])), 0);
        break;
      case 'skewY':
        tx.shear(0, Math.tan(goog.math.toRadians(params[0])));
        break;
    }
  }

  return tx;
};

/**
 * Normalizes stroke params. Look at vector.Shape.fill() params for details.
 * @param {(!acgraph.vector.Fill|!Array.<(acgraph.vector.GradientKey|string)>|null)=} opt_fillOrColorOrKeys .
 * @param {number=} opt_opacityOrAngleOrCx .
 * @param {(number|boolean|!goog.math.Rect|!{left:number,top:number,width:number,height:number})=} opt_modeOrCy .
 * @param {(number|!goog.math.Rect|!{left:number,top:number,width:number,height:number}|null)=} opt_opacityOrMode .
 * @param {number=} opt_opacity .
 * @param {number=} opt_fx .
 * @param {number=} opt_fy .
 * @return {!acgraph.vector.Fill} .
 */
acgraph.vector.normalizeFill = function(opt_fillOrColorOrKeys, opt_opacityOrAngleOrCx, opt_modeOrCy, opt_opacityOrMode,
                                        opt_opacity, opt_fx, opt_fy) {
  /** @type {acgraph.vector.Fill} */
  var newFill;
  /** @type {number} */
  var opacity;
  /** @type {!Array.<(acgraph.vector.GradientKey|string)>} */
  var keys;
  /** @type {acgraph.vector.GradientKey} */
  var key;
  /** @type {number} */
  var i;
  var color;
  var newKeys;
  var newKey;

  if (goog.isString(opt_fillOrColorOrKeys)) { // if that's a "function(color, opt_opacity);" case.
    newFill = acgraph.vector.parseColor(opt_fillOrColorOrKeys, false);
    if (goog.isString(newFill) && goog.isDef(opt_opacityOrAngleOrCx)) { // Simple color settings, e.g. fill('red', 0.5)
      opacity = parseFloat(opt_opacityOrAngleOrCx);
      newFill = {
        'color': opt_fillOrColorOrKeys,
        'opacity': isNaN(opacity) ? 1 : goog.math.clamp(opacity, 0, 1)
      };
    }
  } else if (goog.isArray(opt_fillOrColorOrKeys)) { // creating gradient (linear or radial)
    keys = goog.array.slice(opt_fillOrColorOrKeys, 0);
    for (i = keys.length; i--;) { // iterate keys and normalize them if set as simple color
      key = keys[i];
      if (goog.isString(key)) // key is set as string - need to normalize
        key = acgraph.vector.parseKey(key);
      if (isNaN(key['offset'])) // check all invalid offsets, including absence
        key['offset'] = i / ((keys.length - 1) || 1);
      keys[i] = /** @type {acgraph.vector.GradientKey} */(key);
    }
    newKeys = goog.array.slice(keys, 0);
    newKeys.sort(function(k1, k2) {
      return k1['offset'] - k2['offset'];
    });

    if (newKeys[0]['offset'] != 0) {
      newKey = /** @type {acgraph.vector.GradientKey} */ ({
        'offset': 0,
        'color': /** @type {string} */ (keys[0]['color'])
      });
      if (goog.isDef(keys[0]['opacity']) && !isNaN(keys[0]['opacity'])) {
        newKey['opacity'] = goog.math.clamp(keys[0]['opacity'], 0, 1);
      }
      keys.unshift(newKey);
    }

    if (newKeys[newKeys.length - 1]['offset'] != 1) {
      newKey = /** @type {acgraph.vector.GradientKey} */ ({
        'offset': 1,
        'color': /** @type {string} */ (keys[keys.length - 1]['color'])
      });
      if (goog.isDef(keys[keys.length - 1]['opacity']) && !isNaN(keys[keys.length - 1]['opacity'])) {
        newKey['opacity'] = goog.math.clamp(keys[keys.length - 1]['opacity'], 0, 1);
      }
      keys.push(newKey);
    }
    if (goog.isNumber(opt_opacityOrAngleOrCx) && !isNaN(opt_opacityOrAngleOrCx) &&
        goog.isNumber(opt_modeOrCy) && !isNaN(opt_modeOrCy)) { // radial gradient
      var cx = opt_opacityOrAngleOrCx || 0;
      var cy = opt_modeOrCy || 0;
      newFill = {
        'keys': keys,
        'cx': cx,
        'cy': cy,
        'mode': acgraph.vector.normalizeGradientMode(opt_opacityOrMode), // only rectangle
        'fx': isNaN(opt_fx) ? cx : +opt_fx,
        'fy': isNaN(opt_fy) ? cy : +opt_fy,
        'opacity': goog.math.clamp(goog.isDef(opt_opacity) ? opt_opacity : 1, 0, 1)
      };
    } else { // linear gradient
      newFill = {
        'keys': keys,
        'angle': (+opt_opacityOrAngleOrCx) || 0,
        'mode': acgraph.vector.normalizeGradientMode(opt_modeOrCy) || !!opt_modeOrCy, // can be boolean
        'opacity': goog.math.clamp(!isNaN(+opt_opacityOrMode) ? +opt_opacityOrMode : 1, 0, 1)
      };
    }
  } else if (goog.isObject(opt_fillOrColorOrKeys)) { // fill as an object
    if (acgraph.utils.instanceOf(opt_fillOrColorOrKeys, acgraph.vector.PatternFill)) {
      newFill = opt_fillOrColorOrKeys;
    } else if (opt_fillOrColorOrKeys['type'] == 'pattern') {
      delete opt_fillOrColorOrKeys['id'];
      var bounds = opt_fillOrColorOrKeys['bounds'];
      bounds = new goog.math.Rect(bounds['left'], bounds['top'], bounds['width'], bounds['height']);
      newFill = acgraph.patternFill(bounds);
      newFill.deserialize(opt_fillOrColorOrKeys);
    } else if ('keys' in opt_fillOrColorOrKeys) { // gradient
      keys = goog.array.slice(opt_fillOrColorOrKeys['keys'], 0);
      for (i = keys.length; i--;) { // iterate keys and normalize them if set as simple color
        key = keys[i];
        if (goog.isString(key)) // key is set as string - need to normalize
          newKey = acgraph.vector.parseKey(key);
        else { // copy as we can
          if (goog.isString(key['color']))
            color = key['color'];
          else if (goog.isArray(key['color']))
            color = goog.color.rgbArrayToHex(key['color']);
          else
            color = 'black';

          newKey = {
            'offset': key['offset'],
            'color': color
          };
          if (!isNaN(key['opacity']))
            newKey['opacity'] = goog.math.clamp(key['opacity'], 0, 1);
        }
        if (isNaN(newKey['offset'])) // check all invalid offsets, including absence
          newKey['offset'] = i / ((keys.length - 1) || 1);
        keys[i] = /** @type {acgraph.vector.GradientKey} */(newKey);
      }
      newKeys = goog.array.slice(keys, 0);
      newKeys.sort(function(k1, k2) {
        return k1['offset'] - k2['offset'];
      });

      if (newKeys[0]['offset'] != 0) {
        newKey = /** @type {acgraph.vector.GradientKey} */ ({
          'offset': 0,
          'color': /** @type {string} */ (keys[0]['color'])
        });
        if (goog.isDef(keys[0]['opacity']) && !isNaN(keys[0]['opacity'])) {
          newKey['opacity'] = goog.math.clamp(keys[0]['opacity'], 0, 1);
        }
        keys.unshift(newKey);
      }

      if (newKeys[newKeys.length - 1]['offset'] != 1) {
        newKey = /** @type {acgraph.vector.GradientKey} */ ({
          'offset': 1,
          'color': /** @type {string} */ (keys[keys.length - 1]['color'])
        });
        if (goog.isDef(keys[keys.length - 1]['opacity']) && !isNaN(keys[keys.length - 1]['opacity'])) {
          newKey['opacity'] = goog.math.clamp(keys[keys.length - 1]['opacity'], 0, 1);
        }
        keys.push(newKey);
      }

      opacity = goog.math.clamp(goog.isDef(opt_fillOrColorOrKeys['opacity']) ? opt_fillOrColorOrKeys['opacity'] : 1, 0, 1);
      var mode = acgraph.vector.normalizeGradientMode(opt_fillOrColorOrKeys['mode']);
      cx = opt_fillOrColorOrKeys['cx'];
      cy = opt_fillOrColorOrKeys['cy'];

      if (goog.isNumber(cx) && !isNaN(cx) && goog.isNumber(cy) && !isNaN(cy)) { // treat as radial gradient
        newFill = {
          'keys': keys,
          'cx': +cx,
          'cy': +cy,
          'mode': mode, // only rectangle is possible
          'fx': isNaN(opt_fillOrColorOrKeys['fx']) ? +opt_fillOrColorOrKeys['cx'] : +opt_fillOrColorOrKeys['fx'],
          'fy': isNaN(opt_fillOrColorOrKeys['fy']) ? +opt_fillOrColorOrKeys['cy'] : +opt_fillOrColorOrKeys['fy'],
          'opacity': opacity
        };
      } else {
        newFill = {
          'keys': keys,
          'angle': +opt_fillOrColorOrKeys['angle'] || 0,
          'mode': mode || !!opt_fillOrColorOrKeys['mode'], // can be boolean
          'opacity': opacity
        };
      }
      var transform = opt_fillOrColorOrKeys['transform'];
      if (goog.isDefAndNotNull(transform)) {
        if (acgraph.utils.instanceOf(transform, goog.math.AffineTransform)) {
          newFill['transform'] = transform;
        } else if (goog.isObject(transform)) {
          newFill['transform'] = new goog.math.AffineTransform();
          newFill['transform'].setTransform(
              transform['m00'],
              transform['m10'],
              transform['m01'],
              transform['m11'],
              transform['m02'],
              transform['m12']
          );
        } else if (goog.isString(transform)) {
          newFill['transform'] = acgraph.vector.parseTransformationString(transform);
        }
      }
    } else if ('src' in opt_fillOrColorOrKeys) {
      newFill = {
        'src': opt_fillOrColorOrKeys['src'],
        'mode': goog.isDef(opt_fillOrColorOrKeys['mode']) ? opt_fillOrColorOrKeys['mode'] : acgraph.vector.ImageFillMode.STRETCH,
        'opacity': goog.math.clamp(goog.isDef(opt_fillOrColorOrKeys['opacity']) ? opt_fillOrColorOrKeys['opacity'] : 1, 0, 1)
      };
    } else {
      color = goog.isString(opt_fillOrColorOrKeys['color']) ? opt_fillOrColorOrKeys['color'] : 'black';
      if (isNaN(opt_fillOrColorOrKeys['opacity']))
        newFill = color;
      else
        newFill = {
          'color': color,
          'opacity': goog.math.clamp(opt_fillOrColorOrKeys['opacity'], 0, 1)
        };
    }
  } else {
    newFill = 'none';
  }
  return newFill;
};

/**
 * Normalizes stroke params. Look at vector.Shape.stroke() params for details.
 * @param {(acgraph.vector.Stroke|acgraph.vector.ColoredFill|string|null)=} opt_strokeOrFill Stroke fill,
 *   if used as setter.
 * @param {number=} opt_thickness Line thickness. Defaults to 1.
 * @param {string=} opt_dashpattern Controls the pattern of dashes and gaps used to stroke paths.
 *    Dash array contains a list of comma and/or white space separated lengths and percentages that specify the
 *    lengths of alternating dashes and gaps. If an odd number of values is provided, then the list of values is
 *    repeated to yield an even number of values. Thus, stroke dashpattern: 5,3,2 is equivalent to dashpattern: 5,3,2,5,3,2.
 * @param {acgraph.vector.StrokeLineJoin=} opt_lineJoin Line join style.
 * @param {acgraph.vector.StrokeLineCap=} opt_lineCap Line cap style.
 * @return {!acgraph.vector.Stroke} .
 */
acgraph.vector.normalizeStroke = function(opt_strokeOrFill, opt_thickness, opt_dashpattern, opt_lineJoin, opt_lineCap) {
  var tmp;
  /** @type {acgraph.vector.Stroke} */
  var newStroke;
  if (goog.isNull(opt_strokeOrFill)) { // If stroke is null - nothing to pars
    newStroke = 'none';
  } else {
    if (goog.isString(opt_strokeOrFill)) { // is sting - can start from thickness ('1 red 0.2')
      tmp = goog.string.splitLimit(opt_strokeOrFill, ' ', 1);
      var tmpThickness = parseFloat(tmp[0]);
      if (!isNaN(tmpThickness)) { // if starts with thickness - it has priority over opt_thickness
        opt_strokeOrFill = tmp[1];
        opt_thickness = tmpThickness;
      }
    }
    var setAsComplexStroke = goog.isObject(opt_strokeOrFill);
    var thickness = parseFloat(
        (setAsComplexStroke && ('thickness' in opt_strokeOrFill)) ?
            opt_strokeOrFill['thickness'] :
            opt_thickness);
    if (!isNaN(thickness) && !thickness) // if thickness is set and set to 0
      return 'none';

    var hasDash = setAsComplexStroke && ('dash' in opt_strokeOrFill);
    var hasJoin = setAsComplexStroke && ('lineJoin' in opt_strokeOrFill);
    var hasCap = setAsComplexStroke && ('lineCap' in opt_strokeOrFill);

    // Get normalized fill.
    tmp = acgraph.vector.normalizeFill(/** @type {(acgraph.vector.Fill|string|null)} */(opt_strokeOrFill));
    if (tmp == 'none')
      return /** @type {string} */(tmp);
    // No pattern fill for stroke, unfortunately :D
    // Double typecast should be here, via ColoredFill,
    // but that's too much metadata, so let's go with this.
    newStroke = (acgraph.utils.instanceOf(tmp, acgraph.vector.PatternFill)) ? 'black' : /** @type {acgraph.vector.Stroke} */(tmp);

    // If nothing else we can use normalized fill as a stroke,
    // ot is compatible. Otherwise we need to add properties.
    if (!isNaN(thickness) || hasDash || hasJoin || hasCap ||
        goog.isDef(opt_dashpattern) || goog.isDef(opt_lineJoin) || goog.isDef(opt_lineCap)) {
      if (goog.isString(newStroke)) // If there is and color is set as string, we need to upgrade it to an object
        newStroke = /** @type {acgraph.vector.Stroke} */({
          'color': newStroke
        });
      if (!isNaN(thickness))
        newStroke['thickness'] = thickness;
      if (hasDash)
        newStroke['dash'] = opt_strokeOrFill['dash'] || 'none';
      else if (goog.isDefAndNotNull(opt_dashpattern))
        newStroke['dash'] = opt_dashpattern || 'none';
      if (hasJoin)
        newStroke['lineJoin'] = opt_strokeOrFill['lineJoin'] || 'none';
      else if (goog.isDefAndNotNull(opt_lineJoin))
        newStroke['lineJoin'] = opt_lineJoin || 'none';
      if (hasCap)
        newStroke['lineCap'] = opt_strokeOrFill['lineCap'] || 'none';
      else if (goog.isDefAndNotNull(opt_lineCap))
        newStroke['lineCap'] = opt_lineCap || 'none';
    }
  }

  return newStroke;
};

/**
 * Normalize hatch fill.
 * @param {(!acgraph.vector.HatchFill|!acgraph.vector.PatternFill|acgraph.vector.HatchFill.HatchFillType|string|Object|null)=} opt_patternFillOrType
 * @param {string=} opt_color
 * @param {(string|number)=} opt_thickness
 * @param {(string|number)=} opt_size
 * @return {acgraph.vector.PatternFill|acgraph.vector.HatchFill}
 */
acgraph.vector.normalizeHatchFill = function(opt_patternFillOrType, opt_color, opt_thickness, opt_size) {
  var newFill;
  if (goog.isString(opt_patternFillOrType) && opt_patternFillOrType.toLowerCase() == 'none') {
    return null;
  }

  if (goog.isString(opt_patternFillOrType) || goog.isNumber(opt_patternFillOrType)) {
    newFill = acgraph.hatchFill(
        // Type is normalized inside the constructor. Defaults to BACKWARD_DIAGONAL.
        /** @type {acgraph.vector.HatchFill.HatchFillType} */(opt_patternFillOrType),
        opt_color,
        goog.isDef(opt_thickness) ? parseFloat(opt_thickness) : undefined,
        goog.isDef(opt_size) ? parseFloat(opt_size) : undefined);
  } else if (acgraph.utils.instanceOf(opt_patternFillOrType, acgraph.vector.PatternFill)) {
    newFill = opt_patternFillOrType;
  } else if (goog.isObject(opt_patternFillOrType)) {
    if (opt_patternFillOrType['type'] == 'pattern') {
      delete opt_patternFillOrType['id'];
      var bounds = opt_patternFillOrType['bounds'];
      bounds = new goog.math.Rect(bounds['left'], bounds['top'], bounds['width'], bounds['height']);
      newFill = acgraph.patternFill(bounds);
      newFill.deserialize(opt_patternFillOrType);
    } else {
      newFill = acgraph.hatchFill(
          /** @type {acgraph.vector.HatchFill.HatchFillType} */(opt_patternFillOrType['type']),
          opt_patternFillOrType['color'],
          opt_patternFillOrType['thickness'],
          opt_patternFillOrType['size']);
    }
  } else
    newFill = null;
  return /** @type {acgraph.vector.PatternFill|acgraph.vector.HatchFill} */(newFill);
};

/**
 * Normalize paper size, consider following cases:
 *    normalizePageSize('a2');
 *    normalizePageSize('a2', true);
 *    normalizePageSize('900px');
 *    normalizePageSize('900px', '900px');
 * @param {(string|number)=} opt_paperSizeOrWidth
 * @param {(boolean|string|number)=} opt_landscapeOrHeight
 * @param {acgraph.vector.PaperSize=} opt_default
 * @return {{width: string, height: string}}
 */
acgraph.vector.normalizePageSize = function(opt_paperSizeOrWidth, opt_landscapeOrHeight, opt_default) {
  if (!goog.isDef(opt_default)) opt_default = acgraph.vector.PaperSize.A4;
  var result = acgraph.utils.exporting.PaperSize[opt_default];
  var size;

  //if both parameters passed, try to recognize by second param
  if (goog.isDef(opt_paperSizeOrWidth) && goog.isDef(opt_landscapeOrHeight)) {
    if (goog.isString(opt_paperSizeOrWidth) && goog.isBoolean(opt_landscapeOrHeight)) {
      opt_paperSizeOrWidth = opt_paperSizeOrWidth.toLowerCase();
      size = acgraph.utils.exporting.PaperSize[opt_paperSizeOrWidth];
      if (size) {
        if (opt_landscapeOrHeight) {
          result = {width: size.height, height: size.width};
        } else {
          result = size;
        }
      }
    } else {
      result.width = String(opt_paperSizeOrWidth);
      result.height = String(opt_landscapeOrHeight);
    }
  } else if (goog.isDef(opt_paperSizeOrWidth)) {
    size = acgraph.utils.exporting.PaperSize[String(opt_paperSizeOrWidth)];
    if (size) {
      result = size;
    }
  }

  if (!goog.string.endsWith(result.width, 'px') && !goog.string.endsWith(result.width, 'mm')) result.width += 'px';
  if (!goog.string.endsWith(result.height, 'px') && !goog.string.endsWith(result.height, 'mm')) result.height += 'px';

  return result;
};

/**
 * Reduce to a rectangle. If it is not possible (null or boolean), returns null.
 * @param {null|number|boolean|goog.math.Rect|{left:number,top:number,width:number,height:number}|undefined} mode Gradient
 *    mode to normalize.
 * @return {goog.math.Rect} Normalized gradient rectangle (no extra objects created).
 */
acgraph.vector.normalizeGradientMode = function(mode) {
  if (goog.isDefAndNotNull(mode)) { // mode is set
    if (acgraph.utils.instanceOf(mode, goog.math.Rect))
      return /** @type {goog.math.Rect} */(mode);
    else if (goog.isObject(mode) && !isNaN(mode['left']) && !isNaN(mode['top']) && !isNaN(mode['width']) && !isNaN(mode['height']))
      return new goog.math.Rect(mode['left'], mode['top'], mode['width'], mode['height']);
  }
  return null;
};

/**
 * Normalize textShadow style property into string.
 *
 * @param {*} textShadow - textShadow
 * @return {string} - String style representation.
 */
acgraph.vector.normalizeTextShadow = function(textShadow) {
  if (goog.typeOf(textShadow) === 'object' && 'offsetX' in textShadow && 'offsetY' in textShadow) {
    var offsetX = textShadow['offsetX'];
    var offsetY = textShadow['offsetY'];
    var blurRadius = textShadow['blurRadius'] || '0';
    var color = textShadow['color'] || ''; // If no color passed shadow color will be same as font color.

    return offsetX + ' ' + offsetY + ' ' + blurRadius + ' ' + color;
  } else if (goog.isString(textShadow)) {
    return textShadow;
  }

  return 'none';
};

/**
 * @param {string} color Color as 'red' or 'red 0.5'.
 * @param {boolean} forceObject Alwasy return as acgraph.vector.SolidFill object or a string
 *    in case of simple color.
 * @return {string|acgraph.vector.SolidFill} Normalized color.
 */
acgraph.vector.parseColor = function(color, forceObject) {
  /** @type {Array.<string>} */
  var tmp = color.split(' ');
  /** @type {number} */
  var opacity = (tmp.length > 1) ? goog.math.clamp(+tmp[tmp.length - 1], 0, 1) : NaN;
  if (!isNaN(opacity)) {
    tmp.pop();
    color = tmp.join(' ');
  } else if (forceObject) {
    // else gradient keys set as ['red', 'blue'] get opacity and block applying of
    // global opacity of gradient.
    return {'color': color};
  } else {
    opacity = 1;
  }
  return (forceObject || opacity != 1) ?
      {
        'color': color,
        'opacity': opacity
      } :
      color;
};

/**
 * @param {string} key Key is '[offset ]color[ opacity]': 'red', 'red 0.5', '0.5 red' or '0.5 red 0.5'.
 * @return {acgraph.vector.GradientKey} Normalized key.
 */
acgraph.vector.parseKey = function(key) {
  var tmp = goog.string.splitLimit(key, ' ', 1);
  var color;
  var offset = NaN;
  if (tmp.length > 1) {
    offset = parseFloat(tmp[0]);
    color = isNaN(offset) ? key : tmp[1];
  } else
    color = key;
  var result = acgraph.vector.parseColor(color, true);
  if (!isNaN(offset))
    result['offset'] = goog.math.clamp(offset, 0, 1);
  return /** @type {acgraph.vector.GradientKey} */(result);
};

/**
 * Retrieves thickness from the stroke object.
 * @param {?acgraph.vector.Stroke} stroke Stroke.
 * @return {number} Thickness of the stroke.
 */
acgraph.vector.getThickness = function(stroke) {
  var res;
  return (stroke && stroke != 'none') ?
      (isNaN(res = stroke['thickness']) || goog.isNull(res) ? 1 : res) :
      0;
};

//exports
(function() {
  goog.exportSymbol('acgraph.vector.normalizeFill', acgraph.vector.normalizeFill);
  goog.exportSymbol('acgraph.vector.normalizeStroke', acgraph.vector.normalizeStroke);
  goog.exportSymbol('acgraph.vector.normalizeHatchFill', acgraph.vector.normalizeHatchFill);
  goog.exportSymbol('acgraph.vector.normalizeTextShadow', acgraph.vector.normalizeTextShadow);
})();


text:
<?php
/*
Version: 1.0
Author: Artur Sułkowski
Website: http://artursulkowski.pl
*/

class ControllerModuleCookie extends Controller {
	private $error = array();

	public function index() {
		$this->language->load('module/cookie');

		$this->document->setTitle('Cookie');

		$this->load->model('setting/setting');

		// Dodawanie plików css i js do <head>
		$this->document->addStyle('view/stylesheet/cookie.css');

		// Multistore
		$data['stores'] = array();
		$this->load->model('setting/store');
		$results = $this->model_setting_store->getStores();

		$data['stores'][] = array(
			'name' => 'Default',
			'href' => '',
			'store_id' => 0
		);

		foreach ($results as $result) {
			$data['stores'][] = array(
				'name' => $result['name'],
				'href' => $result['url'],
				'store_id' => $result['store_id']
			);
		}

		// Zapisywanie modułu
		if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
			$this->model_setting_setting->editSetting('cookie', $this->request->post);

			$this->session->data['success'] = $this->language->get('text_success');

			$this->response->redirect($this->url->link('module/cookie', 'token=' . $this->session->data['token'], 'SSL'));
		}

		// Wyświetlanie powiadomień
 		if (isset($this->error['warning'])) {
			$data['error_warning'] = $this->error['warning'];
		} else {
			$data['error_warning'] = '';
		}

		if (isset($this->session->data['success'])) {
			$data['success'] = $this->session->data['success'];
		    unset($this->session->data['success']);
		} else {
			$data['success'] = '';
		}

		$data['action'] = $this->url->link('module/cookie', 'token=' . $this->session->data['token'], 'SSL');

		$data['token'] = $this->session->data['token'];

		// Ładowanie listy modułów
		$data['modules'] = array();

		if (isset($this->request->post['cookie_module'])) {
			$data['modules'] = $this->request->post['cookie_module'];
		} elseif ($this->config->get('cookie_module')) {
			$data['modules'] = $this->config->get('cookie_module');
		}

		// Layouts
		$this->load->model('design/layout');
		$data['layouts'] = $this->model_design_layout->getLayouts();

		// Languages
		$this->load->model('localisation/language');
		$data['languages'] = $this->model_localisation_language->getLanguages();

		// No image
		$this->load->model('tool/image');
		$data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100);

		$data['breadcrumbs'] = array();

		$data['breadcrumbs'][] = array(
			'text' => $this->language->get('text_home'),
			'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL')
		);

		$data['breadcrumbs'][] = array(
			'text' => 'Modules',
			'href' => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL')
		);

		$data['breadcrumbs'][] = array(
			'text' => 'Cookie',
			'href' => $this->url->link('module/cookie', 'token=' . $this->session->data['token'], 'SSL')
		);

		$data['header'] = $this->load->controller('common/header');
		$data['column_left'] = $this->load->controller('common/column_left');
		$data['footer'] = $this->load->controller('common/footer');

		$this->response->setOutput($this->load->view('module/cookie.tpl', $data));
	}

	protected function validate() {
		if (!$this->user->hasPermission('modify', 'module/cookie')) {
			$this->error['warning'] = $this->language->get('error_permission');
		}

		if (!$this->error) {
			return true;
		} else {
			return false;
		}
	}
}
?>

redpajama_set_name: RedPajamaGithub


text:
package mtr.render;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import mtr.MTRClient;
import mtr.block.BlockNode;
import mtr.block.BlockPlatform;
import mtr.block.BlockSignalLightBase;
import mtr.block.BlockSignalSemaphoreBase;
import mtr.client.*;
import mtr.data.*;
import mtr.entity.EntitySeat;
import mtr.item.ItemNodeModifierBase;
import mtr.mappings.EntityRendererMapper;
import mtr.mappings.Text;
import mtr.mappings.Utilities;
import mtr.mappings.UtilitiesClient;
import mtr.path.PathData;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.Vec3;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class RenderTrains extends EntityRendererMapper<EntitySeat> implements IGui {

	public static int maxTrainRenderDistance;
	public static ResourcePackCreatorProperties creatorProperties = new ResourcePackCreatorProperties();

	private static float lastRenderedTick;
	private static int prevPlatformCount;
	private static int prevSidingCount;
	private static UUID renderedUuid;

	public static final int PLAYER_RENDER_OFFSET = 1000;

	public static final Set<String> AVAILABLE_TEXTURES = new HashSet<>();
	public static final Set<String> UNAVAILABLE_TEXTURES = new HashSet<>();

	public static final int DETAIL_RADIUS = 32;
	public static final int DETAIL_RADIUS_SQUARED = DETAIL_RADIUS * DETAIL_RADIUS;
	private static final int MAX_RADIUS_REPLAY_MOD = 64 * 16;
	private static final int TICKS_PER_SECOND = 20;
	private static final int DISMOUNT_PROGRESS_BAR_LENGTH = 30;

	public RenderTrains(Object parameter) {
		super(parameter);
	}

	@Override
	public void render(EntitySeat entity, float entityYaw, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumers, int entityLight) {
		render(entity, tickDelta, matrices, vertexConsumers);
	}

	@Override
	public ResourceLocation getTextureLocation(EntitySeat entity) {
		return null;
	}

	public static void render(EntitySeat entity, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumers) {
		final Minecraft client = Minecraft.getInstance();
		final boolean backupRendering = entity == null;
		final boolean alreadyRendered = renderedUuid != null && (backupRendering || entity.getUUID() != renderedUuid);

		if (backupRendering) {
			renderedUuid = null;
		}

		final LocalPlayer player = client.player;
		final Level world = client.level;

		if (alreadyRendered || player == null || world == null) {
			return;
		}

		if (!backupRendering) {
			renderedUuid = entity.getUUID();
		}

		final int renderDistanceChunks = UtilitiesClient.getRenderDistance();
		final float lastFrameDuration = MTRClient.getLastFrameDuration();
		final boolean useAnnouncements = Config.useTTSAnnouncements() || Config.showAnnouncementMessages();

		if (Config.useDynamicFPS()) {
			if (lastFrameDuration > 0.5) {
				maxTrainRenderDistance = Math.max(maxTrainRenderDistance - (maxTrainRenderDistance - DETAIL_RADIUS) / 2, DETAIL_RADIUS);
			} else if (lastFrameDuration < 0.4) {
				maxTrainRenderDistance = Math.min(maxTrainRenderDistance + 1, renderDistanceChunks * (Config.trainRenderDistanceRatio() + 1));
			}
		} else {
			maxTrainRenderDistance = renderDistanceChunks * (Config.trainRenderDistanceRatio() + 1);
		}

		if (!backupRendering) {
			matrices.popPose();
			matrices.pushPose();
			final Vec3 cameraPosition = client.gameRenderer.getMainCamera().getPosition();
			matrices.translate(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z);
		}
		matrices.pushPose();

		TrainRendererBase.setupStaticInfo(matrices, vertexConsumers, entity, tickDelta);

		ClientData.TRAINS.forEach(train -> train.simulateTrain(world, client.isPaused() || lastRenderedTick == MTRClient.getGameTick() ? 0 : lastFrameDuration, (speed, stopIndex, routeIds) -> {
			final float shiftHoldingTicks = ClientData.getShiftHoldingTicks();
			if (shiftHoldingTicks > 0) {
				final int progressFilled = Mth.clamp((int) (shiftHoldingTicks * DISMOUNT_PROGRESS_BAR_LENGTH / RailwayDataCoolDownModule.SHIFT_ACTIVATE_TICKS), 0, DISMOUNT_PROGRESS_BAR_LENGTH);
				final String progressBar = String.format("§6%s§7%s", StringUtils.repeat('|', progressFilled), StringUtils.repeat('|', DISMOUNT_PROGRESS_BAR_LENGTH - progressFilled));
				player.displayClientMessage(Text.translatable("gui.mtr.dismount_hold", client.options.keyShift.getTranslatedKeyMessage(), progressBar), true);
			} else if ((!train.isCurrentlyManual() || !Train.isHoldingKey(player)) && !(speed <= 5 && RailwayData.useRoutesAndStationsFromIndex(stopIndex, routeIds, ClientData.DATA_CACHE, (currentStationIndex, thisRoute, nextRoute, thisStation, nextStation, lastStation) -> {
				final Component text;
				switch ((int) ((System.currentTimeMillis() / 1000) % 3)) {
					default:
						text = getStationText(thisStation, "this");
						break;
					case 1:
						if (nextStation == null) {
							text = getStationText(thisStation, "this");
						} else {
							text = getStationText(nextStation, "next");
						}
						break;
					case 2:
						text = getStationText(lastStation, "last_" + thisRoute.transportMode.toString().toLowerCase());
						break;
				}
				player.displayClientMessage(text, true);
			}))) {
				player.displayClientMessage(Text.translatable("gui.mtr.vehicle_speed", RailwayData.round(speed, 1), RailwayData.round(speed * 3.6F, 1)), true);
			}
		}, (stopIndex, routeIds) -> {
			if (useAnnouncements) {
				RailwayData.useRoutesAndStationsFromIndex(stopIndex, routeIds, ClientData.DATA_CACHE, (currentStationIndex, thisRoute, nextRoute, thisStation, nextStation, lastStation) -> {
					final List<String> messages = new ArrayList<>();
					final String thisRouteSplit = thisRoute.name.split("\\|\\|")[0];
					final String nextRouteSplit = nextRoute == null ? null : nextRoute.name.split("\\|\\|")[0];

					if (nextStation != null) {
						final boolean isLightRailRoute = thisRoute.isLightRailRoute;
						messages.add(IGui.insertTranslation(isLightRailRoute ? "gui.mtr.next_station_light_rail_announcement_cjk" : "gui.mtr.next_station_announcement_cjk", isLightRailRoute ? "gui.mtr.next_station_light_rail_announcement" : "gui.mtr.next_station_announcement", 1, nextStation.name));

						final Map<Integer, ClientCache.ColorNameTuple> routesInStation = ClientData.DATA_CACHE.stationIdToRoutes.get(nextStation.id);
						if (routesInStation != null) {
							final List<String> interchangeRoutes = routesInStation.values().stream().filter(interchangeRoute -> {
								final String routeName = interchangeRoute.name.split("\\|\\|")[0];
								return !routeName.equals(thisRouteSplit) && (nextRoute == null || !routeName.equals(nextRouteSplit));
							}).map(interchangeRoute -> interchangeRoute.name).collect(Collectors.toList());
							final String mergedStations = IGui.mergeStations(interchangeRoutes, ", ");
							if (!mergedStations.isEmpty()) {
								messages.add(IGui.insertTranslation("gui.mtr.interchange_announcement_cjk", "gui.mtr.interchange_announcement", 1, mergedStations));
							}
						}

						if (lastStation != null && nextStation.id == lastStation.id && nextRoute != null && !nextRoute.platformIds.isEmpty() && !nextRouteSplit.equals(thisRouteSplit)) {
							final Station nextFinalStation = ClientData.DATA_CACHE.platformIdToStation.get(nextRoute.platformIds.get(nextRoute.platformIds.size() - 1));
							if (nextFinalStation != null) {
								final String modeString = thisRoute.transportMode.toString().toLowerCase();
								if (nextRoute.isLightRailRoute) {
									messages.add(IGui.insertTranslation("gui.mtr.next_route_" + modeString + "_light_rail_announcement_cjk", "gui.mtr.next_route_" + modeString + "_light_rail_announcement", nextRoute.lightRailRouteNumber, 1, nextFinalStation.name.split("\\|\\|")[0]));
								} else {
									messages.add(IGui.insertTranslation("gui.mtr.next_route_" + modeString + "_announcement_cjk", "gui.mtr.next_route_" + modeString + "_announcement", 2, nextRouteSplit, nextFinalStation.name.split("\\|\\|")[0]));
								}
							}
						}
					}

					IDrawing.narrateOrAnnounce(IGui.mergeStations(messages, " "));
				});
			}
		}, (stopIndex, routeIds) -> {
			if (useAnnouncements) {
				RailwayData.useRoutesAndStationsFromIndex(stopIndex, routeIds, ClientData.DATA_CACHE, (currentStationIndex, thisRoute, nextRoute, thisStation, nextStation, lastStation) -> {
					if (thisRoute.isLightRailRoute && lastStation != null) {
						IDrawing.narrateOrAnnounce(IGui.insertTranslation("gui.mtr.light_rail_route_announcement_cjk", "gui.mtr.light_rail_route_announcement", thisRoute.lightRailRouteNumber, 1, lastStation.name));
					}
				});
			}
		}));
		if (!Config.hideTranslucentParts()) {
			ClientData.TRAINS.forEach(TrainClient::renderTranslucent);
		}

		final boolean renderColors = isHoldingRailRelated(player);
		final int maxRailDistance = renderDistanceChunks * 16;
		final Map<UUID, RailType> renderedRailMap = new HashMap<>();
		ClientData.RAILS.forEach((startPos, railMap) -> railMap.forEach((endPos, rail) -> {
			if (!RailwayData.isBetween(player.getX(), startPos.getX(), endPos.getX(), maxRailDistance) || !RailwayData.isBetween(player.getZ(), startPos.getZ(), endPos.getZ(), maxRailDistance)) {
				return;
			}

			final UUID railProduct = PathData.getRailProduct(startPos, endPos);
			if (renderedRailMap.containsKey(railProduct)) {
				if (renderedRailMap.get(railProduct) == rail.railType) {
					return;
				}
			} else {
				renderedRailMap.put(railProduct, rail.railType);
			}

			switch (rail.transportMode) {
				case TRAIN:
					renderRailStandard(world, matrices, vertexConsumers, rail, 0.0625F + SMALL_OFFSET, renderColors, 1);
					if (renderColors) {
						renderSignalsStandard(world, matrices, vertexConsumers, rail, startPos, endPos);
					}
					break;
				case BOAT:
					if (renderColors) {
						renderRailStandard(world, matrices, vertexConsumers, rail, 0.0625F + SMALL_OFFSET, true, 0.5F);
						renderSignalsStandard(world, matrices, vertexConsumers, rail, startPos, endPos);
					}
					break;
				case CABLE_CAR:
					if (rail.railType.hasSavedRail || rail.railType == RailType.CABLE_CAR_STATION) {
						renderRailStandard(world, matrices, vertexConsumers, rail, 0.25F + SMALL_OFFSET, renderColors, 0.25F, "mtr:textures/block/metal.png", 0.25F, 0, 0.75F, 1);
					}
					if (renderColors && !rail.railType.hasSavedRail) {
						renderRailStandard(world, matrices, vertexConsumers, rail, 0.5F + SMALL_OFFSET, true, 1, "mtr:textures/block/one_way_rail_arrow.png", 0, 0.75F, 1, 0.25F);
					}

					if (rail.railType != RailType.NONE) {
						rail.render((x1, z1, x2, z2, x3, z3, x4, z4, y1, y2) -> {
							final int r = renderColors ? (rail.railType.color >> 16) & 0xFF : 0;
							final int g = renderColors ? (rail.railType.color >> 8) & 0xFF : 0;
							final int b = renderColors ? rail.railType.color & 0xFF : 0;
							IDrawing.drawLine(matrices, vertexConsumers, (float) x1, (float) y1 + 0.5F, (float) z1, (float) x3, (float) y2 + 0.5F, (float) z3, r, g, b);
						}, 0, 0);
					}

					break;
			}
		}));

		matrices.popPose();
		lastRenderedTick = MTRClient.getGameTick();

		if (prevPlatformCount != ClientData.PLATFORMS.size() || prevSidingCount != ClientData.SIDINGS.size()) {
			ClientData.DATA_CACHE.sync();
		}
		prevPlatformCount = ClientData.PLATFORMS.size();
		prevSidingCount = ClientData.SIDINGS.size();
		ClientData.DATA_CACHE.clearDataIfNeeded();
	}

	public static boolean shouldNotRender(BlockPos pos, int maxDistance, Direction facing) {
		final Entity camera = Minecraft.getInstance().cameraEntity;
		return shouldNotRender(camera == null ? null : camera.position(), pos, maxDistance, facing);
	}

	public static void clearTextureAvailability() {
		AVAILABLE_TEXTURES.clear();
		UNAVAILABLE_TEXTURES.clear();
	}

	public static boolean isHoldingRailRelated(Player player) {
		return Utilities.isHolding(player,
				item -> item instanceof ItemNodeModifierBase ||
						Block.byItem(item) instanceof BlockSignalLightBase ||
						Block.byItem(item) instanceof BlockNode ||
						Block.byItem(item) instanceof BlockSignalSemaphoreBase ||
						Block.byItem(item) instanceof BlockPlatform
		);
	}

	private static double maxDistanceXZ(Vec3 pos1, BlockPos pos2) {
		return Math.max(Math.abs(pos1.x - pos2.getX()), Math.abs(pos1.z - pos2.getZ()));
	}

	private static boolean shouldNotRender(Vec3 cameraPos, BlockPos pos, int maxDistance, Direction facing) {
		final boolean playerFacingAway;
		if (cameraPos == null || facing == null) {
			playerFacingAway = false;
		} else {
			if (facing.getAxis() == Direction.Axis.X) {
				final double playerXOffset = cameraPos.x - pos.getX() - 0.5;
				playerFacingAway = Math.signum(playerXOffset) == facing.getStepX() && Math.abs(playerXOffset) >= 0.5;
			} else {
				final double playerZOffset = cameraPos.z - pos.getZ() - 0.5;
				playerFacingAway = Math.signum(playerZOffset) == facing.getStepZ() && Math.abs(playerZOffset) >= 0.5;
			}
		}
		return cameraPos == null || playerFacingAway || maxDistanceXZ(cameraPos, pos) > (MTRClient.isReplayMod() ? MAX_RADIUS_REPLAY_MOD : maxDistance);
	}

	private static void renderRailStandard(Level world, PoseStack matrices, MultiBufferSource vertexConsumers, Rail rail, float yOffset, boolean renderColors, float railWidth) {
		renderRailStandard(world, matrices, vertexConsumers, rail, yOffset, renderColors, railWidth, renderColors && rail.railType == RailType.QUARTZ ? "mtr:textures/block/rail_preview.png" : "textures/block/rail.png", -1, -1, -1, -1);
	}

	private static void renderRailStandard(Level world, PoseStack matrices, MultiBufferSource vertexConsumers, Rail rail, float yOffset, boolean renderColors, float railWidth, String texture, float u1, float v1, float u2, float v2) {
		final int maxRailDistance = UtilitiesClient.getRenderDistance() * 16;

		rail.render((x1, z1, x2, z2, x3, z3, x4, z4, y1, y2) -> {
			final BlockPos pos2 = new BlockPos(x1, y1, z1);
			if (shouldNotRender(pos2, maxRailDistance, null)) {
				return;
			}
			final int light2 = LightTexture.pack(world.getBrightness(LightLayer.BLOCK, pos2), world.getBrightness(LightLayer.SKY, pos2));

			if (rail.railType == RailType.NONE) {
				if (rail.transportMode != TransportMode.CABLE_CAR && renderColors) {
					final VertexConsumer vertexConsumerArrow = vertexConsumers.getBuffer(MoreRenderLayers.getExterior(new ResourceLocation("mtr:textures/block/one_way_rail_arrow.png")));
					IDrawing.drawTexture(matrices, vertexConsumerArrow, (float) x1, (float) y1 + yOffset, (float) z1, (float) x2, (float) y1 + yOffset + SMALL_OFFSET, (float) z2, (float) x3, (float) y2 + yOffset, (float) z3, (float) x4, (float) y2 + yOffset + SMALL_OFFSET, (float) z4, 0, 0.25F, 1, 0.75F, Direction.UP, -1, light2);
					IDrawing.drawTexture(matrices, vertexConsumerArrow, (float) x2, (float) y1 + yOffset + SMALL_OFFSET, (float) z2, (float) x1, (float) y1 + yOffset, (float) z1, (float) x4, (float) y2 + yOffset + SMALL_OFFSET, (float) z4, (float) x3, (float) y2 + yOffset, (float) z3, 0, 0.25F, 1, 0.75F, Direction.UP, -1, light2);
				}
			} else {
				final float textureOffset = (((int) (x1 + z1)) % 4) * 0.25F + (float) Config.trackTextureOffset() / Config.TRACK_OFFSET_COUNT;
				final int color = renderColors || !Config.hideSpecialRailColors() && rail.railType.hasSavedRail ? rail.railType.color : -1;
				final VertexConsumer vertexConsumer = vertexConsumers.getBuffer(MoreRenderLayers.getExterior(new ResourceLocation(texture)));
				IDrawing.drawTexture(matrices, vertexConsumer, (float) x1, (float) y1 + yOffset, (float) z1, (float) x2, (float) y1 + yOffset + SMALL_OFFSET, (float) z2, (float) x3, (float) y2 + yOffset, (float) z3, (float) x4, (float) y2 + yOffset + SMALL_OFFSET, (float) z4, u1 < 0 ? 0 : u1, v1 < 0 ? 0.1875F + textureOffset : v1, u2 < 0 ? 1 : u2, v2 < 0 ? 0.3125F + textureOffset : v2, Direction.UP, color, light2);
				IDrawing.drawTexture(matrices, vertexConsumer, (float) x2, (float) y1 + yOffset + SMALL_OFFSET, (float) z2, (float) x1, (float) y1 + yOffset, (float) z1, (float) x4, (float) y2 + yOffset + SMALL_OFFSET, (float) z4, (float) x3, (float) y2 + yOffset, (float) z3, u1 < 0 ? 0 : u1, v1 < 0 ? 0.1875F + textureOffset : v1, u2 < 0 ? 1 : u2, v2 < 0 ? 0.3125F + textureOffset : v2, Direction.UP, color, light2);
			}
		}, -railWidth, railWidth);
	}

	private static void renderSignalsStandard(Level world, PoseStack matrices, MultiBufferSource vertexConsumers, Rail rail, BlockPos startPos, BlockPos endPos) {
		final int maxRailDistance = UtilitiesClient.getRenderDistance() * 16;
		final List<SignalBlocks.SignalBlock> signalBlocks = ClientData.SIGNAL_BLOCKS.getSignalBlocksAtTrack(PathData.getRailProduct(startPos, endPos));
		final float width = 1F / DyeColor.values().length;

		for (int i = 0; i < signalBlocks.size(); i++) {
			final SignalBlocks.SignalBlock signalBlock = signalBlocks.get(i);
			final boolean shouldGlow = signalBlock.isOccupied() && (((int) Math.floor(MTRClient.getGameTick())) % TICKS_PER_SECOND) < TICKS_PER_SECOND / 2;
			final VertexConsumer vertexConsumer = shouldGlow ? vertexConsumers.getBuffer(MoreRenderLayers.getLight(new ResourceLocation("mtr:textures/block/white.png"), false)) : vertexConsumers.getBuffer(MoreRenderLayers.getExterior(new ResourceLocation("textures/block/white_wool.png")));
			final float u1 = width * i + 1 - width * signalBlocks.size() / 2;
			final float u2 = u1 + width;

			final int color = ARGB_BLACK | signalBlock.color.getMaterialColor().col;
			rail.render((x1, z1, x2, z2, x3, z3, x4, z4, y1, y2) -> {
				final BlockPos pos2 = new BlockPos(x1, y1, z1);
				if (shouldNotRender(pos2, maxRailDistance, null)) {
					return;
				}
				final int light2 = shouldGlow ? MAX_LIGHT_GLOWING : LightTexture.pack(world.getBrightness(LightLayer.BLOCK, pos2), world.getBrightness(LightLayer.SKY, pos2));

				IDrawing.drawTexture(matrices, vertexConsumer, (float) x1, (float) y1, (float) z1, (float) x2, (float) y1 + SMALL_OFFSET, (float) z2, (float) x3, (float) y2, (float) z3, (float) x4, (float) y2 + SMALL_OFFSET, (float) z4, u1, 0, u2, 1, Direction.UP, color, light2);
				IDrawing.drawTexture(matrices, vertexConsumer, (float) x4, (float) y2 + SMALL_OFFSET, (float) z4, (float) x3, (float) y2, (float) z3, (float) x2, (float) y1 + SMALL_OFFSET, (float) z2, (float) x1, (float) y1, (float) z1, u1, 0, u2, 1, Direction.UP, color, light2);
			}, u1 - 1, u2 - 1);
		}
	}

	private static Component getStationText(Station station, String textKey) {
		if (station != null) {
			return Text.literal(IGui.formatStationName(IGui.insertTranslation("gui.mtr." + textKey + "_station_cjk", "gui.mtr." + textKey + "_station", 1, IGui.textOrUntitled(station.name))));
		} else {
			return Text.literal("");
		}
	}

	@Deprecated // TODO remove
	public static float getGameTicks() {
		return MTRClient.getGameTick();
	}
}


text:
@protocol TestProtocol;

@protocol CustomRootObject
@end

@interface TestProperty : NSObject

@property(nonatomic, strong) NSString *stringProperty;
@property(nonatomic, strong) NSNumber * numberProperty;
@property(nonatomic, assign) int intProperty;
@property(nonatomic, assign) long longProperty;
@property(nonatomic, assign) float floatProperty;
@property(nonatomic, assign) double doubleProperty;
@property(nonatomic, assign) CGRect rectProperty;
@property(nonatomic, assign) BOOL boolProperty;
@property(nonatomic, strong) NSDate* dateProperty;
@property(nonatomic, strong) NSArray* arrayProperty;
@property(nonatomic, strong) NSMutableArray* mutableArrayProperty;

@end


text:
require 'rails_helper'

describe Organizer::RoomsController, type: :controller do
  let(:event) { create(:event) }
  before { login(create(:organizer, event: event)) }

  describe "DELETE 'destroy'" do
    it "destroys the room with ajax" do
      room = create(:room, event: event)
      expect {
        xhr :delete, :destroy, id: room, event_id: event
      }.to change(Room, :count).by(-1)
      expect(response).to be_success
    end
  end

end


text:
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.prestosql.plugin.hive.metastore.cache;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListeningExecutorService;
import io.airlift.units.Duration;
import io.prestosql.plugin.hive.HiveConfig;
import io.prestosql.plugin.hive.HiveMetastoreClosure;
import io.prestosql.plugin.hive.PartitionStatistics;
import io.prestosql.plugin.hive.authentication.HiveIdentity;
import io.prestosql.plugin.hive.metastore.Partition;
import io.prestosql.plugin.hive.metastore.Table;
import io.prestosql.plugin.hive.metastore.thrift.BridgingHiveMetastore;
import io.prestosql.plugin.hive.metastore.thrift.MetastoreLocator;
import io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient;
import io.prestosql.plugin.hive.metastore.thrift.ThriftHiveMetastore;
import io.prestosql.plugin.hive.metastore.thrift.ThriftMetastoreClient;
import io.prestosql.plugin.hive.metastore.thrift.ThriftMetastoreConfig;
import io.prestosql.plugin.hive.metastore.thrift.ThriftMetastoreStats;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.concurrent.TimeUnit;

import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
import static io.airlift.concurrent.Threads.daemonThreadsNamed;
import static io.prestosql.plugin.hive.HiveTestUtils.HDFS_ENVIRONMENT;
import static io.prestosql.plugin.hive.metastore.HiveColumnStatistics.createIntegerColumnStatistics;
import static io.prestosql.plugin.hive.metastore.cache.CachingHiveMetastore.cachingHiveMetastore;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.BAD_DATABASE;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.BAD_PARTITION;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_COLUMN;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_DATABASE;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_PARTITION1;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_PARTITION2;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_PARTITION_VALUES1;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_ROLES;
import static io.prestosql.plugin.hive.metastore.thrift.MockThriftMetastoreClient.TEST_TABLE;
import static io.prestosql.testing.TestingConnectorSession.SESSION;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static java.util.function.Function.identity;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

@Test(singleThreaded = true)
public class TestCachingHiveMetastore
{
    private static final HiveIdentity IDENTITY = new HiveIdentity(SESSION);
    private static final PartitionStatistics TEST_STATS = PartitionStatistics.builder()
            .setColumnStatistics(ImmutableMap.of(TEST_COLUMN, createIntegerColumnStatistics(OptionalLong.empty(), OptionalLong.empty(), OptionalLong.empty(), OptionalLong.empty())))
            .build();

    private MockThriftMetastoreClient mockClient;
    private CachingHiveMetastore metastore;
    private ThriftMetastoreStats stats;

    @BeforeMethod
    public void setUp()
    {
        mockClient = new MockThriftMetastoreClient();
        ThriftHiveMetastore thriftHiveMetastore = createThriftHiveMetastore();
        ListeningExecutorService executor = listeningDecorator(newCachedThreadPool(daemonThreadsNamed("test-%s")));
        metastore = (CachingHiveMetastore) cachingHiveMetastore(
                new BridgingHiveMetastore(thriftHiveMetastore),
                executor,
                new Duration(5, TimeUnit.MINUTES),
                Optional.of(new Duration(1, TimeUnit.MINUTES)),
                1000);
        stats = thriftHiveMetastore.getStats();
    }

    private ThriftHiveMetastore createThriftHiveMetastore()
    {
        MetastoreLocator metastoreLocator = new MockMetastoreLocator(mockClient);
        return new ThriftHiveMetastore(metastoreLocator, new HiveConfig(), new ThriftMetastoreConfig(), HDFS_ENVIRONMENT, false);
    }

    @Test
    public void testGetAllDatabases()
    {
        assertEquals(mockClient.getAccessCount(), 0);
        assertEquals(metastore.getAllDatabases(), ImmutableList.of(TEST_DATABASE));
        assertEquals(mockClient.getAccessCount(), 1);
        assertEquals(metastore.getAllDatabases(), ImmutableList.of(TEST_DATABASE));
        assertEquals(mockClient.getAccessCount(), 1);

        metastore.flushCache();

        assertEquals(metastore.getAllDatabases(), ImmutableList.of(TEST_DATABASE));
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testGetAllTable()
    {
        assertEquals(mockClient.getAccessCount(), 0);
        assertEquals(metastore.getAllTables(TEST_DATABASE), ImmutableList.of(TEST_TABLE));
        assertEquals(mockClient.getAccessCount(), 1);
        assertEquals(metastore.getAllTables(TEST_DATABASE), ImmutableList.of(TEST_TABLE));
        assertEquals(mockClient.getAccessCount(), 1);

        metastore.flushCache();

        assertEquals(metastore.getAllTables(TEST_DATABASE), ImmutableList.of(TEST_TABLE));
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testInvalidDbGetAllTAbles()
    {
        assertTrue(metastore.getAllTables(BAD_DATABASE).isEmpty());
    }

    @Test
    public void testGetTable()
    {
        assertEquals(mockClient.getAccessCount(), 0);
        assertNotNull(metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE));
        assertEquals(mockClient.getAccessCount(), 1);
        assertNotNull(metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE));
        assertEquals(mockClient.getAccessCount(), 1);

        metastore.flushCache();

        assertNotNull(metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE));
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testInvalidDbGetTable()
    {
        assertFalse(metastore.getTable(IDENTITY, BAD_DATABASE, TEST_TABLE).isPresent());

        assertEquals(stats.getGetTable().getThriftExceptions().getTotalCount(), 0);
        assertEquals(stats.getGetTable().getTotalFailures().getTotalCount(), 0);
    }

    @Test
    public void testGetPartitionNames()
    {
        ImmutableList<String> expectedPartitions = ImmutableList.of(TEST_PARTITION1, TEST_PARTITION2);
        assertEquals(mockClient.getAccessCount(), 0);
        assertEquals(metastore.getPartitionNames(IDENTITY, TEST_DATABASE, TEST_TABLE).get(), expectedPartitions);
        assertEquals(mockClient.getAccessCount(), 1);
        assertEquals(metastore.getPartitionNames(IDENTITY, TEST_DATABASE, TEST_TABLE).get(), expectedPartitions);
        assertEquals(mockClient.getAccessCount(), 1);

        metastore.flushCache();

        assertEquals(metastore.getPartitionNames(IDENTITY, TEST_DATABASE, TEST_TABLE).get(), expectedPartitions);
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testInvalidGetPartitionNames()
    {
        assertEquals(metastore.getPartitionNames(IDENTITY, BAD_DATABASE, TEST_TABLE).get(), ImmutableList.of());
    }

    @Test
    public void testGetPartitionNamesByParts()
    {
        ImmutableList<String> parts = ImmutableList.of();
        ImmutableList<String> expectedPartitions = ImmutableList.of(TEST_PARTITION1, TEST_PARTITION2);

        assertEquals(mockClient.getAccessCount(), 0);
        assertEquals(metastore.getPartitionNamesByParts(IDENTITY, TEST_DATABASE, TEST_TABLE, parts).get(), expectedPartitions);
        assertEquals(mockClient.getAccessCount(), 1);
        assertEquals(metastore.getPartitionNamesByParts(IDENTITY, TEST_DATABASE, TEST_TABLE, parts).get(), expectedPartitions);
        assertEquals(mockClient.getAccessCount(), 1);

        metastore.flushCache();

        assertEquals(metastore.getPartitionNamesByParts(IDENTITY, TEST_DATABASE, TEST_TABLE, parts).get(), expectedPartitions);
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testInvalidGetPartitionNamesByParts()
    {
        ImmutableList<String> parts = ImmutableList.of();
        assertFalse(metastore.getPartitionNamesByParts(IDENTITY, BAD_DATABASE, TEST_TABLE, parts).isPresent());
    }

    @Test
    public void testGetPartitionsByNames()
    {
        assertEquals(mockClient.getAccessCount(), 0);
        Table table = metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE).get();
        assertEquals(mockClient.getAccessCount(), 1);

        // Select half of the available partitions and load them into the cache
        assertEquals(metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(TEST_PARTITION1)).size(), 1);
        assertEquals(mockClient.getAccessCount(), 2);

        // Now select all of the partitions
        assertEquals(metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(TEST_PARTITION1, TEST_PARTITION2)).size(), 2);
        // There should be one more access to fetch the remaining partition
        assertEquals(mockClient.getAccessCount(), 3);

        // Now if we fetch any or both of them, they should not hit the client
        assertEquals(metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(TEST_PARTITION1)).size(), 1);
        assertEquals(metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(TEST_PARTITION2)).size(), 1);
        assertEquals(metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(TEST_PARTITION1, TEST_PARTITION2)).size(), 2);
        assertEquals(mockClient.getAccessCount(), 3);

        metastore.flushCache();

        // Fetching both should only result in one batched access
        assertEquals(metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(TEST_PARTITION1, TEST_PARTITION2)).size(), 2);
        assertEquals(mockClient.getAccessCount(), 5);
    }

    @Test
    public void testListRoles()
    {
        assertEquals(mockClient.getAccessCount(), 0);

        assertEquals(metastore.listRoles(), TEST_ROLES);
        assertEquals(mockClient.getAccessCount(), 1);

        assertEquals(metastore.listRoles(), TEST_ROLES);
        assertEquals(mockClient.getAccessCount(), 1);

        metastore.flushCache();

        assertEquals(metastore.listRoles(), TEST_ROLES);
        assertEquals(mockClient.getAccessCount(), 2);

        metastore.createRole("role", "grantor");

        assertEquals(metastore.listRoles(), TEST_ROLES);
        assertEquals(mockClient.getAccessCount(), 3);

        metastore.dropRole("testrole");

        assertEquals(metastore.listRoles(), TEST_ROLES);
        assertEquals(mockClient.getAccessCount(), 4);
    }

    @Test
    public void testGetTableStatistics()
    {
        assertEquals(mockClient.getAccessCount(), 0);

        Table table = metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE).get();
        assertEquals(mockClient.getAccessCount(), 1);

        assertEquals(metastore.getTableStatistics(IDENTITY, table), TEST_STATS);
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testGetPartitionStatistics()
    {
        assertEquals(mockClient.getAccessCount(), 0);

        Table table = metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE).get();
        assertEquals(mockClient.getAccessCount(), 1);

        Partition partition = metastore.getPartition(IDENTITY, table, TEST_PARTITION_VALUES1).get();
        assertEquals(mockClient.getAccessCount(), 2);

        assertEquals(metastore.getPartitionStatistics(IDENTITY, table, ImmutableList.of(partition)), ImmutableMap.of(TEST_PARTITION1, TEST_STATS));
        assertEquals(mockClient.getAccessCount(), 3);
    }

    @Test
    public void testUpdatePartitionStatistics()
    {
        assertEquals(mockClient.getAccessCount(), 0);

        HiveMetastoreClosure hiveMetastoreClosure = new HiveMetastoreClosure(metastore);

        Table table = hiveMetastoreClosure.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE).get();
        assertEquals(mockClient.getAccessCount(), 1);

        hiveMetastoreClosure.updatePartitionStatistics(IDENTITY, table.getDatabaseName(), table.getTableName(), TEST_PARTITION1, identity());
        assertEquals(mockClient.getAccessCount(), 5);
    }

    @Test
    public void testInvalidGetPartitionsByNames()
    {
        Table table = metastore.getTable(IDENTITY, TEST_DATABASE, TEST_TABLE).get();
        Map<String, Optional<Partition>> partitionsByNames = metastore.getPartitionsByNames(IDENTITY, table, ImmutableList.of(BAD_PARTITION));
        assertEquals(partitionsByNames.size(), 1);
        Optional<Partition> onlyElement = Iterables.getOnlyElement(partitionsByNames.values());
        assertFalse(onlyElement.isPresent());
    }

    @Test
    public void testNoCacheExceptions()
    {
        // Throw exceptions on usage
        mockClient.setThrowException(true);
        try {
            metastore.getAllDatabases();
        }
        catch (RuntimeException ignored) {
        }
        assertEquals(mockClient.getAccessCount(), 1);

        // Second try should hit the client again
        try {
            metastore.getAllDatabases();
        }
        catch (RuntimeException ignored) {
        }
        assertEquals(mockClient.getAccessCount(), 2);
    }

    @Test
    public void testCachingHiveMetastoreCreationWithTtlOnly()
    {
        CachingHiveMetastoreConfig config = new CachingHiveMetastoreConfig();
        config.setMetastoreCacheTtl(new Duration(10, TimeUnit.MILLISECONDS));

        CachingHiveMetastore metastore = createMetastoreWithDirectExecutor(config);

        assertThat(metastore).isNotNull();
    }

    private CachingHiveMetastore createMetastoreWithDirectExecutor(CachingHiveMetastoreConfig config)
    {
        return (CachingHiveMetastore) cachingHiveMetastore(
                new BridgingHiveMetastore(createThriftHiveMetastore()),
                directExecutor(),
                config);
    }

    private static class MockMetastoreLocator
            implements MetastoreLocator
    {
        private final ThriftMetastoreClient client;

        private MockMetastoreLocator(ThriftMetastoreClient client)
        {
            this.client = client;
        }

        @Override
        public ThriftMetastoreClient createMetastoreClient(Optional<String> delegationToken)
        {
            return client;
        }
    }
}


text:
struct	occi_authorization_item;

struct	occi_authorization_cache
{
	struct	occi_authorization_item * first;
	struct	occi_authorization_item * last;
	int				  ttl;
};

#endif


text:
BEGIN {
    $|=1;
    print "Content-type: text/html\n\n";
    use CGI::Carp('fatalsToBrowser');
}
use strict;
use CGI;
use CGI qw/:standard/;
use lib "Perl-modules";
use XML::Simple;
use HTML::TreeBuilder;

my $simple = XML::Simple->new( );  # initialize objects
my $cgi = new CGI;
my $xmldirectory = "../htdocs/smartpost/xml_files/";
my $files = dirlist($xmldirectory);
my @jobs = '';	#hyperlink array
my $baseurl = "http://02e8a4f.netsolhost.com/smartpost/jobs/";

# print "Content-type:text/html\n\n";	# required header for web output

## create job postings from xml files
foreach my $fileInDirectory (@$files) {
	my $tree = $simple->XMLin( '../htdocs/smartpost/xml_files/' . $fileInDirectory );   # read, store document in $tree

	## now that we have a copy of an XML file we can determine how many jobs it contains,
	## and create a posting for each unique req_id

	my $jobs = 	'';	# job description(s)
 	my $name = $tree->{ company } . '_' . $tree->{ job } . "_" . $tree->{ id } . '.html';	#name of individual job posting file

 	## populate global hyperlink array with: Company + ID + Title ... to be used later
	push(@jobs, a({-href=>$baseurl . $name},"$tree->{ company } - $tree->{ job } - $tree->{ id }") . '
');
	open (MYFILE, '>>' . $name);
	print MYFILE $cgi->start_html(  -title => $tree->{ id } . ' - ' . $tree->{ company } . ' - ' . $tree->{ title },
									-meta => {  'keywords' => $tree->{ job } . ', job',
												'description' => 'job description'},
									-style => { -src => '/css/main.css'} ) .
									'' . $tree->{ title } . '' .
									$tree->{ description } .
									a({-href=>"$tree->{ url }"},"$tree->{url}") .
									$cgi->end_html . "\n";

	# move files from cgi-bin to jobs folder and enable execute permissions # <-- uncomment for production
	rename($name, '../htdocs/smartpost/live/' . $name) || print "Lack permission to rename " . $name . " or file does not exist.

";
	chmod(0755, '../htdocs/smartpost/live/' . $name) || print $!;
}

rename('../htdocs/smartpost/xml_files/' . $fileInDirectory, '../htdocs/smartpost/xml_files/processed/' . $fileInDirectory); #move processed xml file(s)

# create array of newly created hyperlinks and add to exisitng ones on index.html
my $oldlinks = glob ();

## sort the list of hyperlinks
my @sorted = sort { $a cmp $b } @jobs;   # ASCII-betical sort

# creates an array of xml filenames
sub dirlist {
        my $dir = shift;
        my @filelist;
        opendir(DIR, $dir) or die "can't opendir $dir: $!";
        while (defined(my $file = readdir(DIR))) {

                # We only want files
		        next unless (-f "$dir/$file");

		        # Use a regular expression to find files ending in .xml
		        next unless ($file =~ m/\.xml$/);
                push(@filelist, $file);
        }
        closedir(DIR);
        return \@filelist;
}

# # create array of job posting filenames
sub joblist {
        my $dir = shift;
        my @filelist;
        opendir(DIR, $dir) or die "can't opendir $dir: $!";
        while (defined(my $file = readdir(DIR))) {
                # We only want files
		        next unless (-f "$dir/$file");
		        # Use a regular expression to find only webpages
		        next unless ($file =~ m/*.html/);
                push(@filelist, $file);
        }
        closedir(DIR);
        my @sorted = sort { $a cmp $b } @filelist;   # ASCII-betical sort
        return \@sorted;
}

# # create list of formatted hyperlinks for job postings
my $jobdirectory = "../htdocs/smartpost/jobs/";
my $linklist = joblist($jobdirectory);
my $joblinks = '';
foreach my $jobInDirectory (@$linklist) {
	next unless ($jobInDirectory =~ m/\.html$/);
	$joblinks .= '' . $jobInDirectory . '' . '
';
}

use HTML::LinkExtor;		# load the needed module

my $s = $baseurl . 'index.html';
print "These are the existing jobs on the webpage:\n";
my $p = HTML::LinkExtor->new();	# create a link extractor object
$p->parse_file($s) or die("\nOutput incomplete. Input file not found: $s\n");
foreach($p->links)	#  iterate over the hyperlink list and print each
{
	print "@$_\n";	# each list element is an array that must be dereferenced
}

## render job postings web page
open (LISTING, '../htdocs/smartpost/jobs/jobs.html');
print LISTING $cgi->start_html( -title => 'Job Postings',
								-meta => { 'keywords' => 'employment opportunities, jobs',
											'description' => 'job descriptions'},
								-style => { -src => '../css/main.css'}, ) .
								'
' .
									'
' . '
' .
									'

' .
									'
' . 'Active job postings:' . '
' .
									'
' . "@sorted" . '
' .
									'

' .
								'
' .
								$cgi->end_html . "\n";

# message to user upon execution of this file
print "Done

";
print "New job(s) posted: here

";
print "Jobs added:
";
print "@sorted";
### end of script


text:
<?xml version="1.0"?>
<Runs Version="1" Minor="0">
	<Run Id="ila_0_synth_1" LaunchDir="D:/Documentos/Documentos/CIDIC/vivado/picorv32_vivado/picorv32_vivado.runs/ila_0_synth_1" FlowId="Vivado_Synthesis" FromStepId="vivado" ToStepId="vivado"/>
</Runs>


text:
<?php

namespace CornyPhoenix\Tex\Log\ElementParser;

use CornyPhoenix\Tex\Log\LogElement;
use CornyPhoenix\Tex\Log\Message;

/**
 * @package CornyPhoenix\Tex\Log\ElementParser
 * @author moellers
 */
class BadBoxElementParser implements ElementParserInterface
{

    const BAD_BOX_REGEX = "/((Over|Under)full) \\\\(v|h)box \(([^\)]+)\)( in paragraph at lines (\d+))?/";

    /**
     * Parses a log element for some messages.
     *
     * @param LogElement $element
     * @return Message[]
     */
    public function parse(LogElement $element)
    {
        $messages = [];
        preg_match_all(self::BAD_BOX_REGEX, $element->getContent(), $matches, PREG_SET_ORDER);
        foreach ($matches as $match) {
            list(, $overfull, , $v, $details, , $line) = $match;

            $box = $v === 'v' ? 'vertical' : 'horizontal';

            $message = sprintf('%s %s %s box.', ucfirst($details), strtolower($overfull), $box);
            $messages[] = new Message('Bad Box', Message::BAD_BOX, $element->getFilename(), $line, $message);
        }

        return $messages;
    }
}


text:
using System.Runtime.Serialization;

namespace GoogleApi.Entities.Translate.Common.Enums
{
    /// <summary>
    /// The translation model.
    /// </summary>
    public enum Model
    {
        /// <summary>
        /// Base, Phrase-Based Machine Translation (PBMT) model
        /// </summary>
        [EnumMember(Value = "base")]
        Base,

        /// <summary>
        /// Nmt, Neural Machine Translation (NMT) model.
        /// </summary>
        [EnumMember(Value = "nmt")]
        Nmt
    }
}


text:
{% spaceless %}
{% if results %}

    {% autoescape off %}
    {% for result in results %}

                [{{ result.show_number }}]

                {{ result.title }}

{{ result.topic_name }}

            {% for entry in result.url_entries %}

{{ entry }}

            {% endfor %}
            {% if result.entry %}

{{ result.entry }}

            {% endif %}

{% endfor %}
{% endautoescape %}

{% endif %}
{% endspaceless %}


text:
package io.github.furti.beagleio.gpio.local;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.WatchService;
import java.util.concurrent.ScheduledExecutorService;

import io.github.furti.beagleio.Pin;
import io.github.furti.beagleio.gpio.file.FileSystemPinManager;

/**
 * @author Daniel
 *
 */
public class LocalPinManager extends FileSystemPinManager
{
  private static final String EXPORT_FILE = "export";
  private static final String UNEXPORT_FILE = "unexport";

  private Path exportPath;
  private Path unexportPath;

  /**
   * @param pin
   * @param baseDirectory
   * @param executor
   * @param watcher
   */
  public LocalPinManager(Pin pin, Path baseDirectory, ScheduledExecutorService executor,
      WatchService watcher)
  {
    super(pin, baseDirectory, executor, watcher);
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * io.github.furti.beagleio.gpio.file.FileSystemPinManager#releaseFileSystemPin(io.github.furti.
   * beagleio.Pin, java.nio.file.Path)
   */
  @Override
  protected void releaseFileSystemPin(Pin pin, Path pinDirectory) throws IOException
  {
    writeToFile(unexportPath, pin.getKernelNumber());
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * io.github.furti.beagleio.gpio.file.FileSystemPinManager#initialize(io.github.furti.beagleio.
   * Pin, java.nio.file.Path)
   */
  @Override
  protected Path initialize(Pin pin, Path baseDirectory)
  {
    this.exportPath = baseDirectory.resolve(EXPORT_FILE);
    this.unexportPath = baseDirectory.resolve(UNEXPORT_FILE);

    writeToFile(exportPath, pin.getKernelNumber());

    return baseDirectory.resolve(pin.getKernelNumber().toString());
  }
}