text:
[//000000001]: # (valtype::creditcard::mastercard \- Validation types)
[//000000002]: # (Generated from file 'vtype\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright © 2011 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (valtype::creditcard::mastercard\(n\) 1 tcllib "Validation types")

 [ Main Table Of Contents | Table Of Contents | Keyword Index | Categories | Modules | Applications ]

# NAME

valtype::creditcard::mastercard \- Validation for Mastercard creditcard number

# Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [API](#section2)

  - [Error Codes](#section3)

  - [Bugs, Ideas, Feedback](#section4)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# SYNOPSIS

package require Tcl 8\.5
package require snit 2
package require valtype::common
package require valtype::luhn
package require valtype::creditcard::mastercard ?1?

[__valtype::creditcard::mastercard__ __validate__ *value*](#1)
[__valtype::creditcard::mastercard__ __checkdigit__ *value*](#2)

# DESCRIPTION

This package implements a snit validation type for a Mastercard creditcard
number\.

A validation type is an object that can be used to validate Tcl values of a
particular kind\. For example, __snit::integer__, a validation type defined
by the __[snit](\.\./snit/snit\.md)__ package is used to validate that a
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::mastercard validate .... ;# Does nothing
    valtype::creditcard::mastercard validate .... ;# Throws an error (bad Mastercard creditcard number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# API

The API provided by this package satisfies the specification of snit validation
types found in the documentation of *[Snit's Not Incr
Tcl](\.\./snit/snit\.md)*\.

  - __valtype::creditcard::mastercard__ __validate__ *value*

    This method validates the *value* and returns it, possibly in a canonical
    form, if it passes\. If the value does not pass the validation an error is
    thrown\.

  - __valtype::creditcard::mastercard__ __checkdigit__ *value*

    This method computes a check digit for the *value*\. Before doing so it is
    validated, except for a checkdigit\. If the value does not pass the
    validation no check digit is calculated and an error is thrown instead\.

# Error Codes

As said in the package description, the errors thrown by the commands of this
package in response to input validation failures use the __\-errorcode__
INVALID to distinguish themselves from package internal errors\.

To provide more detailed information about why the validation failed the
__\-errorCode__ goes actually beyond that\. First, it will contain a code
detailing the type itself\. Here this is __CREDITCARD MASTERCARD__\. This is
then followed by values detailing the reason for the failure\. The full set of
__\-errorCode__s which can be thrown by this package are:

  - INVALID CREDITCARD MASTERCARD CHARACTER

    The input value contained one or more bad characters, i\.e\. characters which
    must not occur in the input for it to be a Mastercard creditcard number\.

  - INVALID CREDITCARD MASTERCARD CHECK\-DIGIT

    The check digit of the input value is wrong\. This usually signals a
    data\-entry error, with digits transposed, forgotten, etc\. Of course, th
    input may be an outright fake too\.

  - INVALID CREDITCARD MASTERCARD LENGTH

    The input value is of the wrong length to be a Mastercard creditcard number\.

  - INVALID CREDITCARD MASTERCARD PREFIX

    The input value does not start with the magic value\(s\) required for it to be
    a Mastercard creditcard number\.

# Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *valtype* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of
__diff \-u__\.

Note further that *attachments* are strongly preferred over inlined patches\.
Attachments can be made by going to the __Edit__ form of the ticket
immediately after its creation, and then using the left\-most button in the
secondary navigation bar\.

# KEYWORDS

[Checking](\.\./\.\./\.\./\.\./index\.md\#checking),
[MasterCard](\.\./\.\./\.\./\.\./index\.md\#mastercard),
[Testing](\.\./\.\./\.\./\.\./index\.md\#testing), [Type
checking](\.\./\.\./\.\./\.\./index\.md\#type\_checking),
[Validation](\.\./\.\./\.\./\.\./index\.md\#validation), [Value
checking](\.\./\.\./\.\./\.\./index\.md\#value\_checking),
[bank](\.\./\.\./\.\./\.\./index\.md\#bank), [card for
credit](\.\./\.\./\.\./\.\./index\.md\#card\_for\_credit), [credit
card](\.\./\.\./\.\./\.\./index\.md\#credit\_card),
[finance](\.\./\.\./\.\./\.\./index\.md\#finance), [isA](\.\./\.\./\.\./\.\./index\.md\#isa)

# CATEGORY

Validation, Type checking

# COPYRIGHT

Copyright © 2011 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>


text:
using eScape.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;

namespace eScapeLLC.UWP.Charts {
	#region Evaluators2
	/// <summary>
	/// The package of <see cref="BindingEvaluator"/> in one place, evaluated once.
	/// This version is for 2D data.
	/// </summary>
	internal class Evaluators2 {
		#region data
		/// <summary>
		/// Category 1 (x-axis) index path; MUST NOT be NULL.
		/// </summary>
		public readonly BindingEvaluator bc1;
		/// <summary>
		/// Category 2 (y-axis) index path.  MUST NOT be NULL.
		/// </summary>
		public readonly BindingEvaluator bc2;
		/// <summary>
		/// Value path.  MUST NOT be NULL.
		/// </summary>
		public readonly BindingEvaluator by;
		/// <summary>
		/// Value label path.  MAY be NULL.
		/// </summary>
		public readonly BindingEvaluator byl;
		#endregion
		#region properties
		/// <summary>
		/// Return whether the <see cref="bc2"/> evaluator got initialized.
		/// </summary>
		public bool IsValid { get { return bc1 != null && bc2 != null && by != null; } }
		#endregion
		#region ctors
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="category1Path">Path to the category 1 index; MUST NOT be NULL.</param>
		/// <param name="category2Path">Path to the category 2 index; MUST NOT be NULL.</param>
		/// <param name="valuePath">Path to the value; MUST NOT be NULL.</param>
		/// <param name="valueLabelPath">Path to the value label; MAY be NULL.</param>
		public Evaluators2(String category1Path, String category2Path, String valuePath, String valueLabelPath) {
			bc2 = !String.IsNullOrEmpty(category2Path) ? new BindingEvaluator(category2Path) : null;
			bc1 = !String.IsNullOrEmpty(category1Path) ? new BindingEvaluator(category1Path) : null;
			by = !String.IsNullOrEmpty(valuePath) ? new BindingEvaluator(valuePath) : null;
			byl = !String.IsNullOrEmpty(valueLabelPath) ? new BindingEvaluator(valueLabelPath) : null;
		}
		/// <summary>
		/// Copy ctor.
		/// </summary>
		/// <param name="be1">Category 1 evaluator.</param>
		/// <param name="be2">Category 2 evaluator.</param>
		/// <param name="by">Value evaluator.</param>
		/// <param name="byl">Value label evaluator.</param>
		public Evaluators2(BindingEvaluator be1, BindingEvaluator be2, BindingEvaluator by, BindingEvaluator byl) { this.bc1 = be1; this.bc2 = be2; this.by = by; this.byl = byl; }
		#endregion
		#region public
		/// <summary>
		/// Use the <see cref="bc1"/> evaluator to return the x-axis value, or index if it is NULL.
		/// </summary>
		/// <param name="ox">Object to evaluate.</param>
		/// <returns></returns>
		public int Category1For(object ox) {
			var valuex = (int)bc1.For(ox);
			return valuex;
		}
		public int Category2For(object ox) {
			var valuex = (int)bc2.For(ox);
			return valuex;
		}
		/// <summary>
		/// Wrapper to call <see cref="DataSeries.CoerceValue(object, BindingEvaluator)"/>.
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		public double ValueFor(object item) {
			var valuey = DataSeries.CoerceValue(item, by);
			return valuey;
		}
		/// <summary>
		/// Evaluate the label or NULL.
		/// <para/>
		/// If NULL, either <see cref="byl"/> was NULL, OR the evaluation result was NULL.
		/// </summary>
		/// <param name="item">Source instance.</param>
		/// <returns>Evaluated value or NULL.</returns>
		public object LabelFor(object item) {
			return byl?.For(item);
		}
		/// <summary>
		/// Force (non-NULL) results to be a <see cref="String"/>.
		/// <para/>
		/// If <see cref="String.Empty"/>, <see cref="byl"/> was NULL. If NULL, the evaluation result was NULL.
		/// </summary>
		/// <param name="item">Source instance.</param>
		/// <returns>Evaluated string, NULL, or <see cref="String.Empty"/>.</returns>
		public String LabelStringFor(object item) {
			return byl != null ? byl.For(item)?.ToString() : String.Empty;
		}
		#endregion
	}
	#endregion
	#region Styles
	#region ICategory2StyleContext
	/// <summary>
	/// Context for formatting a 2-dimensional value.
	/// </summary>
	public interface ICategory2StyleContext {
		/// <summary>
		/// First axis.
		/// </summary>
		IChartAxis Category1Axis { get; }
		/// <summary>
		/// Second axis.
		/// </summary>
		IChartAxis Category2Axis { get; }
		/// <summary>
		/// Value extents.
		/// </summary>
		IProvideSeriesValueExtents ValueExtents { get; }
		/// <summary>
		/// [0] value, [1] c1v, [2] c2v
		/// OR Length == 0.
		/// </summary>
		double[] Values { get; }
	}
	/// <summary>
	/// Default impl.
	/// </summary>
	public class Category2StyleContext : ICategory2StyleContext {
		#region properties
		/// <summary>
		/// First axis.
		/// </summary>
		public IChartAxis Category1Axis { get; private set; }
		/// <summary>
		/// Second axis.
		/// </summary>
		public IChartAxis Category2Axis { get; private set; }
		/// <summary>
		/// Value extents.
		/// </summary>
		public IProvideSeriesValueExtents ValueExtents { get; private set; }
		/// <summary>
		/// [0] value, [1] c1v, [2] c2v
		/// OR Length == 0.
		/// </summary>
		public double[] Values { get; private set; }
		#endregion
		#region ctor
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="a1"></param>
		/// <param name="a2"></param>
		/// <param name="ipsve"></param>
		/// <param name="vxs"></param>
		public Category2StyleContext(IChartAxis a1, IChartAxis a2, IProvideSeriesValueExtents ipsve, double[] vxs) {
			Category1Axis = a1;
			Category2Axis = a2;
			ValueExtents = ipsve;
			Values = vxs;
		}
		#endregion
	}
	#endregion
	#region HeatmapStyleGenerator
	/// <summary>
	/// Abstract base for heatmap style generators.
	/// </summary>
	public abstract class HeatmapStyleGenerator {
		#region properties
		/// <summary>
		/// Style to base generated styles on.
		/// </summary>
		public Style BasedOn { get; set; }
		#endregion
		#region extension points
		/// <summary>
		/// Provide a style or NULL to revert.
		/// </summary>
		/// <param name="ic2sc">Value context.</param>
		/// <returns>Style or NULL.</returns>
		public abstract Style For(ICategory2StyleContext ic2sc);
		/// <summary>
		/// Reset any caches in use for a fresh run.
		/// </summary>
		public abstract void Reset();
		/// <summary>
		/// Generate the legend VM (with initial values).
		/// </summary>
		/// <param name="ic2sc">Context.</param>
		/// <param name="title">Series title.</param>
		/// <param name="pathstyle">Use for other style elements.</param>
		/// <returns>New instance, but with STABLE entries.</returns>
		public abstract IEnumerable<LegendBase> LegendFor(ICategory2StyleContext ic2sc, string title, Style pathstyle);
		/// <summary>
		/// Update legend VM.
		/// </summary>
		/// <param name="ic2sc">Context.</param>
		public abstract void UpdateLegend(ICategory2StyleContext ic2sc);
		#endregion
	}
	#endregion
	#region HeatmapStyle_Cached
	/// <summary>
	/// Base of generators that can cache styles based on the RGB color.
	/// </summary>
	public abstract class HeatmapStyle_Cached : HeatmapStyleGenerator {
		/// <summary>
		/// Cache styles already in use.
		/// </summary>
		protected Dictionary<string, Style> StyleMap { get; set; } = new Dictionary<string, Style>();
		/// <summary>
		/// Clear the map.
		/// </summary>
		public override void Reset() {
			StyleMap.Clear();
		}
		#region helpers
		/// <summary>
		/// Take incoming values and convert to HSV and then to RGB.
		/// Use for analogous.
		/// </summary>
		/// <param name="hstart">HSV Hue start.</param>
		/// <param name="hrange">Hue range.</param>
		/// <param name="frac">Normalized value [0..1].</param>
		/// <param name="sat">HSV Saturation.</param>
		/// <param name="svalue">HSV Value.</param>
		/// <param name="red">Output Red.</param>
		/// <param name="green">Output Green.</param>
		/// <param name="blue">Output Blue.</param>
		protected void InfoForHue(double hstart, double hrange, double frac, double sat, double svalue, out int red, out int green, out int blue) {
			double hue = hstart + (frac * hrange);
			// function will normalize hue [0..360)
			ColorSupport.HsvToRgb(hue, sat, svalue, out red, out green, out blue);
		}
		/// <summary>
		/// Take incoming values and convert to HSV and then to RGB.
		/// Use for monochrome.
		/// </summary>
		/// <param name="vstart">HSV Value start.</param>
		/// <param name="vrange">Value range.</param>
		/// <param name="frac">Normalized value [0..1].</param>
		/// <param name="hue">HSV Hue.</param>
		/// <param name="sat">HSV Saturation.</param>
		/// <param name="red">Output Red.</param>
		/// <param name="green">Output Green.</param>
		/// <param name="blue">Output Blue.</param>
		protected void InfoForValue(double vstart, double vrange, double frac, double hue, double sat, out int red, out int green, out int blue) {
			double svalue = vstart + (frac * vrange);
			// function will normalize hue [0..360)
			ColorSupport.HsvToRgb(hue, sat, svalue, out red, out green, out blue);
		}
		/// <summary>
		/// Normalize the value.
		/// </summary>
		/// <param name="min">Minimum value.</param>
		/// <param name="max">Maximum value.</param>
		/// <param name="value">Candidate.</param>
		/// <returns>[0..1]</returns>
		protected double Scale(double min, double max, double value) {
			double vx = double.IsNaN(value) ? min : value;
			double frac = (vx - min) / (double)(max - min + 1);
			frac = Math.Max(0.0, frac);
			frac = Math.Min(1.0, frac);
			return frac;
		}
		/// <summary>
		/// Create a brush for given RGBA.
		/// </summary>
		/// <param name="red"></param>
		/// <param name="green"></param>
		/// <param name="blue"></param>
		/// <param name="alpha"></param>
		/// <returns>New instance.</returns>
		protected Brush BrushFor(int red, int green, int blue, int alpha) {
			return new SolidColorBrush(Color.FromArgb((byte)alpha, (byte)red, (byte)green, (byte)blue));
		}
		#endregion
	}
	#endregion
	#region HeatmapStyle_Analogous
	/// <summary>
	/// Create a style that color varies HUE over the given HSV range.
	/// Each color is allocated only once and styles shared.
	/// </summary>
	public class HeatmapStyle_Analogous : HeatmapStyle_Cached {
		#region properties
		/// <summary>
		/// HSV Hue for starting range. [0..360).
		/// </summary>
		public double HueStart { get; set; }
		/// <summary>
		/// Hue range.  Make negative to go "backwards".
		/// Default value is 300.
		/// </summary>
		public double HueRange { get; set; } = 300;
		/// <summary>
		/// HSV Saturation.
		/// Default value is 1.
		/// </summary>
		public double Saturation { get; set; } = 1;
		/// <summary>
		/// HSV Value.
		/// Default value is 1.
		/// </summary>
		public double Value { get; set; } = 1;
		/// <summary>
		/// Alpha value 0..255.
		/// Default value is 255.
		/// </summary>
		public byte Alpha { get; set; } = 255;
		#endregion
		#region extensions
		/// <summary>
		/// Create a style or NULL.
		/// </summary>
		/// <param name="ic2sc">Item context.</param>
		/// <returns>Style or NULL.</returns>
		public override Style For(ICategory2StyleContext ic2sc) {
			if (BasedOn == null) return null;
			var v1 = Scale(ic2sc.ValueExtents.Minimum, ic2sc.ValueExtents.Maximum, ic2sc.Values[0]);
			InfoForHue(HueStart, HueRange, v1, Saturation, Value, out int red, out int green, out int blue);
			string skey = $"r{red}_g{green}_b{blue}";
			if (StyleMap.TryGetValue(skey, out Style stx)) {
				return stx;
			}
			var brush = BrushFor(red, green, blue, Alpha);
			var style = BasedOn.Override(Path.FillProperty, brush);
			StyleMap.Add(skey, style);
			return style;
		}
		/// <summary>
		/// Generate the legend VM (with initial values).
		/// </summary>
		/// <param name="ic2sc">Context.</param>
		/// <param name="title">Series title.</param>
		/// <param name="pathstyle">Use for other style elements.</param>
		/// <returns>New instance, but with STABLE entries.</returns>
		public override IEnumerable<LegendBase> LegendFor(ICategory2StyleContext ic2sc, string title, Style pathstyle) {
			return new LegendBase[] { EnsureLegend(ic2sc, title, pathstyle) };
		}
		/// <summary>
		/// Update legend VM.
		/// </summary>
		/// <param name="ic2sc">Context.</param>
		public override void UpdateLegend(ICategory2StyleContext ic2sc) {
			if (_legend == null) return;
			_legend.Fill = CreateBrush(ic2sc);
			_legend.Minimum = ic2sc.ValueExtents.Minimum;
			_legend.Maximum = ic2sc.ValueExtents.Maximum;
		}
		#endregion
		#region helpers
		private LegendValueRange _legend;
		Legend EnsureLegend(ICategory2StyleContext ic2sc, string title, Style pathstyle) {
			var brush = CreateBrush(ic2sc);
			if (_legend != null) {
				_legend.Fill = brush;
				return _legend;
			}
			_legend = new LegendValueRange() { Title = title, Minimum = ic2sc.ValueExtents.Minimum, Maximum = ic2sc.ValueExtents.Maximum, Fill = brush, Stroke = pathstyle.Find<Brush>(Path.StrokeProperty) };
			return _legend;
		}
		Brush CreateBrush(ICategory2StyleContext ic2sc) {
			var gsc = new GradientStopCollection();
			var v1 = Scale(ic2sc.ValueExtents.Minimum, ic2sc.ValueExtents.Maximum, ic2sc.ValueExtents.Minimum);
			var v2 = Scale(ic2sc.ValueExtents.Minimum, ic2sc.ValueExtents.Maximum, ic2sc.ValueExtents.Maximum);
			InfoForHue(HueStart, HueRange, v1, Saturation, Value, out int red, out int green, out int blue);
			gsc.Add(new GradientStop() { Color = Color.FromArgb(Alpha, (byte)red, (byte)green, (byte)blue), Offset = 1 });
			InfoForHue(HueStart, HueRange, v2, Saturation, Value, out red, out green, out blue);
			gsc.Add(new GradientStop() { Color = Color.FromArgb(Alpha, (byte)red, (byte)green, (byte)blue), Offset = 0 });
			return new LinearGradientBrush(gsc, 90);
		}
		#endregion
	}
	#endregion
	#region HeatmapStyle_Monochrome
	/// <summary>
	/// Create a style that color varies VALUE over the given HSV range.
	/// Each color is allocated only once and styles shared.
	/// </summary>
	public class HeatmapStyle_Monochrome : HeatmapStyle_Cached {
		#region properties
		/// <summary>
		/// HSV Hue for all colors. [0..360).
		/// </summary>
		public double Hue { get; set; }
		/// <summary>
		/// HSV Value start. [0..1].
		/// Default value is .25.
		/// </summary>
		public double ValueStart { get; set; } = 0.25;
		/// <summary>
		/// HSV Value range.  Make negative to go "backwards".
		/// Default value is .75.
		/// </summary>
		public double ValueRange { get; set; } = 0.75;
		/// <summary>
		/// HSV Saturation.
		/// Default value is 1.
		/// </summary>
		public double Saturation { get; set; } = 1;
		/// <summary>
		/// Alpha value 0..255.
		/// Default value is 255.
		/// </summary>
		public byte Alpha { get; set; } = 255;
		#endregion
		/// <summary>
		/// Construct a color based on value and range.
		/// </summary>
		/// <param name="ic2sc"></param>
		/// <returns></returns>
		public override Style For(ICategory2StyleContext ic2sc) {
			if (BasedOn == null) return null;
			var v1 = Scale(ic2sc.ValueExtents.Minimum, ic2sc.ValueExtents.Maximum, ic2sc.Values[0]);
			InfoForValue(ValueStart, ValueRange, v1, Hue, Saturation, out int red, out int green, out int blue);
			string skey = $"r{red}_g{green}_b{blue}";
			if (StyleMap.TryGetValue(skey, out Style stx)) {
				return stx;
			}
			var brush = BrushFor(red, green, blue, Alpha);
			var style = BasedOn.Override(Path.FillProperty, brush);
			StyleMap.Add(skey, style);
			return style;
		}
		/// <summary>
		/// Prepare and return the legend items.
		/// </summary>
		/// <param name="ic2sc"></param>
		/// <param name="title"></param>
		/// <param name="pathstyle"></param>
		/// <returns></returns>
		public override IEnumerable<LegendBase> LegendFor(ICategory2StyleContext ic2sc, string title, Style pathstyle) {
			return new LegendBase[] { EnsureLegend(ic2sc, title, pathstyle) };
		}
		/// <summary>
		/// Update extents in VM.
		/// </summary>
		/// <param name="ic2sc"></param>
		public override void UpdateLegend(ICategory2StyleContext ic2sc) {
			if (_legend == null) return;
			_legend.Fill = CreateBrush(ic2sc);
			_legend.Minimum = ic2sc.ValueExtents.Minimum;
			_legend.Maximum = ic2sc.ValueExtents.Maximum;
		}
		#region helpers
		private LegendValueRange _legend;
		Legend EnsureLegend(ICategory2StyleContext ic2sc, string title, Style pathstyle) {
			var brush = CreateBrush(ic2sc);
			if (_legend != null) {
				_legend.Fill = brush;
				return _legend;
			}
			_legend = new LegendValueRange() { Title = title, Minimum = ic2sc.ValueExtents.Minimum, Maximum = ic2sc.ValueExtents.Maximum, Fill = brush, Stroke = pathstyle.Find<Brush>(Path.StrokeProperty) };
			return _legend;
		}
		Brush CreateBrush(ICategory2StyleContext ic2sc) {
			var gsc = new GradientStopCollection();
			var v1 = Scale(ic2sc.ValueExtents.Minimum, ic2sc.ValueExtents.Maximum, ic2sc.ValueExtents.Minimum);
			var v2 = Scale(ic2sc.ValueExtents.Minimum, ic2sc.ValueExtents.Maximum, ic2sc.ValueExtents.Maximum);
			InfoForValue(ValueStart, ValueRange, v1, Hue, Saturation, out int red, out int green, out int blue);
			gsc.Add(new GradientStop() { Color = Color.FromArgb(Alpha, (byte)red, (byte)green, (byte)blue), Offset = 1 });
			InfoForValue(ValueStart, ValueRange, v2, Hue, Saturation, out red, out green, out blue);
			gsc.Add(new GradientStop() { Color = Color.FromArgb(Alpha, (byte)red, (byte)green, (byte)blue), Offset = 0 });
			return new LinearGradientBrush(gsc, 90);
		}
		#endregion
	}
	#endregion
	#region HeatmapStyle_Discrete
	/// <summary>
	/// Half-open interval [Min,Max) for selecting a color.
	/// Setting one end to <see cref="double.NaN"/> creates an open-ended range of the corresponding type.
	/// </summary>
	public class DiscreteLegendEntry {
		/// <summary>
		/// Low end of range (GTE).
		/// </summary>
		public double Minimum { get; set; } = double.NaN;
		/// <summary>
		/// High end of range (LT).
		/// </summary>
		public double Maximum { get; set; } = double.NaN;
		/// <summary>
		/// The color for this range.
		/// </summary>
		public Brush Color { get; set; }
		/// <summary>
		/// The "name" of this discrete range.
		/// </summary>
		public string Title { get; set; }
		/// <summary>
		/// Calculated description of the range.
		/// </summary>
		public string Description {
			get {
				if (double.IsNaN(Minimum) && double.IsNaN(Maximum)) return "-";
				return double.IsNaN(Minimum) ? $"< {Maximum}" : ( double.IsNaN(Maximum) ? $">= {Minimum}" : $"[{Minimum} .. {Maximum})");
			}
		}
		/// <summary>
		/// Determine whether value is in this range.
		/// </summary>
		/// <param name="value">Candidate.</param>
		/// <returns></returns>
		public bool Compare(double value) {
			if (double.IsNaN(Minimum) && double.IsNaN(Maximum)) return false;
			if(double.IsNaN(Minimum)) {
				return value < Maximum;
			}
			else if(double.IsNaN(Maximum)) {
				return value >= Minimum;
			}
			else {
				return value >= Minimum && value < Maximum;
			}
		}
	}
	/// <summary>
	/// Required for XAML consumption.
	/// </summary>
	public class DiscreteLegendEntryCollection : List<DiscreteLegendEntry> { }
	/// <summary>
	/// Discrete version of heatmap style generator.
	/// This consists of a list of ranges that are checked in order.
	/// </summary>
	[ContentProperty(Name = nameof(Entries))]
	public class HeatmapStyle_Discrete : HeatmapStyleGenerator {
		/// <summary>
		/// The list of range entries.
		/// </summary>
		public DiscreteLegendEntryCollection Entries { get; set; } = new DiscreteLegendEntryCollection();
		/// <summary>
		/// Produce a style for the given context.
		/// </summary>
		/// <param name="ic2sc">Context.</param>
		/// <returns>Style or NULL.</returns>
		public override Style For(ICategory2StyleContext ic2sc) {
			if (BasedOn == null) return null;
			var match = Entries.SingleOrDefault(xx => xx.Compare(ic2sc.Values[0]));
			if (match == null) return null;
			var style = BasedOn.Override(Path.FillProperty, match.Color);
			return style;
		}
		List<LegendBase> _legend;
		/// <summary>
		/// Establish the legend for this style generator.
		/// </summary>
		/// <param name="ic2sc">Context.</param>
		/// <param name="title">Series title.</param>
		/// <param name="pathstyle">Use for other style properties as required.</param>
		/// <returns>Cached list enumerator.</returns>
		public override IEnumerable<LegendBase> LegendFor(ICategory2StyleContext ic2sc, string title, Style pathstyle) {
			if(_legend == null) {
				_legend = new List<LegendBase>();
				foreach(var ex in Entries) {
					var leg = new LegendValueRange() { Title = ex.Title, Minimum = ex.Minimum, Maximum = ex.Maximum, Fill = ex.Color, Stroke = BasedOn.Find<Brush>(Path.StrokeProperty) };
					_legend.Add(leg);
				}
			}
			return _legend;
		}
		/// <summary>
		/// Not used.  Once built, the cache is statically valid.
		/// </summary>
		public override void Reset() { }
		/// <summary>
		/// Nothing to update; NOT dependent on value range.
		/// </summary>
		/// <param name="ic2sc"></param>
		public override void UpdateLegend(ICategory2StyleContext ic2sc) { }
	}
	#endregion
	#endregion
	#region HeatmapSeries
	/// <summary>
	/// Heatmap is two category axis presenting rectangular areas of a third (axis-less) value, usually with color-coding of the values.
	/// </summary>
	public class HeatmapSeries : DataSeries, IDataSourceRenderer, IProvideLegend, IProvideSeriesValueExtents, IProvideSeriesItemValues, IRequireChartTheme, IRequireEnterLeave, IRequireTransforms, IRequireCategoryAxis2, IRequireAfterAxesFinalized {
		static readonly LogTools.Flag _trace = LogTools.Add("HeatmapSeries", LogTools.Level.Error);
		#region item state
		/// <summary>
		/// Item offers explicit second dimension (use instead of Value).
		/// </summary>
		protected interface IProvideYValue {
			/// <summary>
			/// Second dimension.
			/// </summary>
			double YValue { get; }
		}
		/// <summary>
		/// Implementation for item state custom label.
		/// Provides placement information.
		/// TODO MAY have to reconstitute the "full" x-coordinates for <see cref="Placement"/> if those ever get used (currently not).
		/// This one is used when <see cref="DataSeriesWithValue.ValueLabelPath"/> is set.
		/// </summary>
		protected class SeriesItemState_Custom : ItemStateCustomWithPlacement<Path>, IProvideYValue {
			/// <summary>
			/// Second dimension.
			/// </summary>
			public double YValue { get; private set; }
			/// <summary>
			/// Extract the rectangle geometry and create placement.
			/// </summary>
			/// <returns></returns>
			protected override Placement CreatePlacement() { return new RectanglePlacement(Placement.DOWN_RIGHT, DataFor()); }
			internal SeriesItemState_Custom(int idx, double xv, double xvo, double c2v, double yv, object cs, Path ele) : base(idx, xv, xvo, yv, cs, ele, 0) { YValue = c2v; }
			WorldRect DataFor() {
				var p1 = new Point(XValue, YValue);
				var p2 = new Point(XValue + 1, YValue + 1);
				_trace.Verbose($"placement p1:{p1} p2:{p2} vx,vy:({XValue},{YValue}) v:{Value}");
				return new WorldRect(p1, p2);
			}
		}
		/// <summary>
		/// Implementation for item state.
		/// Provides placement information.
		/// This one is used when <see cref="DataSeriesWithValue.ValueLabelPath"/> is NOT set.
		/// </summary>
		protected class SeriesItemState_Double : ItemStateWithPlacement<Path>, IProvideYValue {
			/// <summary>
			/// Second dimension.
			/// </summary>
			public double YValue { get; private set; }
			/// <summary>
			/// Extract the rectangle geometry and create placement.
			/// </summary>
			/// <returns></returns>
			protected override Placement CreatePlacement() { return new RectanglePlacement(Placement.DOWN_RIGHT, DataFor()); }
			internal SeriesItemState_Double(int idx, double xv, double xvo, double c2v, double yv, Path ele) : base(idx, xv, xvo, yv, ele, 0) { YValue = c2v; }
			WorldRect DataFor() {
				var p1 = new Point(XValue, YValue);
				var p2 = new Point(XValue + 1, YValue + 1);
				_trace.Verbose($"placement p1:{p1} p2:{p2} vx,vy:({XValue},{YValue}) v:{Value}");
				return new WorldRect(p1, p2);
			}
		}
		#endregion
		#region properties
		/// <summary>
		/// Return current state as read-only.
		/// </summary>
		public IEnumerable<ISeriesItem> SeriesItemValues { get { return ItemState.AsReadOnly(); } }
		/// <summary>
		/// Holder for IRequireChartTheme interface.
		/// </summary>
		public IChartTheme Theme { get; set; }
		/// <summary>
		/// Component name of first <see cref="CategoryAxis"/>.
		/// Referenced component MUST implement <see cref="IChartAxis"/>.
		/// Referenced axis MUST be Horizontal.
		/// </summary>
		public String CategoryAxisName { get; set; }
		/// <summary>
		/// Component name of second <see cref="CategoryAxis"/>.
		/// Referenced component MUST implement <see cref="IChartAxis"/>.
		/// Referenced axis MUST be Vertical.
		/// </summary>
		public String CategoryAxis2Name { get; set; }
		/// <summary>
		/// Dereferenced category 1 axis.
		/// </summary>
		protected IChartAxis CategoryAxis1 { get; set; }
		/// <summary>
		/// Dereferenced category 2 axis.
		/// </summary>
		protected IChartAxis CategoryAxis2 { get; set; }
		/// <summary>
		/// Binding path to the <see cref="CategoryAxis"/> value.
		/// MAY be NULL, in which case the data-index is used instead.
		/// </summary>
		public String CategoryPath { get { return (String)GetValue(CategoryPathProperty); } set { SetValue(CategoryPathProperty, value); } }
		/// <summary>
		/// Binding path to the <see cref="CategoryAxis"/> value.
		/// MAY be NULL, in which case the data-index is used instead.
		/// </summary>
		public String Category2Path { get { return (String)GetValue(Category2PathProperty); } set { SetValue(Category2PathProperty, value); } }
		/// <summary>
		/// Binding path to the value axis value.
		/// MUST be non-NULL.
		/// </summary>
		public String ValuePath { get { return (String)GetValue(ValuePathProperty); } set { SetValue(ValuePathProperty, value); } }
		/// <summary>
		/// Binding path to the value axis label.
		/// MAY be NULL.
		/// If specified, this value will augment the one used for All Channels in <see cref="ISeriesItemValue"/>.
		/// </summary>
		public String ValueLabelPath { get { return (String)GetValue(ValueLabelPathProperty); } set { SetValue(ValueLabelPathProperty, value); } }
		/// <summary>
		/// The minimum value seen.
		/// </summary>
		public double Minimum { get; protected set; } = double.NaN;
		/// <summary>
		/// The maximum value seen.
		/// </summary>
		public double Maximum { get; protected set; } = double.NaN;
		/// <summary>
		/// The title for the values.
		/// </summary>
		public String Title { get { return (String)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } }
		/// <summary>
		/// Template to use for generated paths.
		/// If set, this overrides applying <see cref="PathStyle"/> (assumed <see cref="Style"/> inside the template).
		/// If this is not set, then <see cref="IChartTheme.PathTemplate"/> is used and <see cref="PathStyle"/> applied (if set).
		/// If Theme is not set, then <see cref="Path"/> is used (via ctor) and <see cref="PathStyle"/> applied (if set).
		/// </summary>
		public DataTemplate PathTemplate { get { return (DataTemplate)GetValue(PathTemplateProperty); } set { SetValue(PathTemplateProperty, value); } }
		/// <summary>
		/// The style to use for Path geometry.
		/// SHOULD be non-NULL.
		/// </summary>
		public Style PathStyle { get { return (Style)GetValue(PathStyleProperty); } set { SetValue(PathStyleProperty, value); } }
		/// <summary>
		/// Used to dynamically style the heatmap cells.
		/// </summary>
		public HeatmapStyleGenerator StyleGenerator { get; set; }
		/// <summary>
		/// The layer for components.
		/// </summary>
		protected IChartLayer Layer { get; set; }
		/// <summary>
		/// Data needed for current state.
		/// </summary>
		protected List<ItemState<Path>> ItemState { get; set; }
		/// <summary>
		/// Save the binding evaluators.
		/// TODO must re-create when any of the DPs change!
		/// </summary>
		Evaluators2 BindPaths { get; set; }
		#endregion
		#region DPs
		/// <summary>
		/// Identifies <see cref="PathTemplate"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty PathTemplateProperty = DependencyProperty.Register(
			nameof(PathTemplate), typeof(DataTemplate), typeof(HeatmapSeries), new PropertyMetadata(null)
		);
		/// <summary>
		/// Identifies <see cref="PathStyle"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty PathStyleProperty = DependencyProperty.Register(
			nameof(PathStyle), typeof(Style), typeof(HeatmapSeries), new PropertyMetadata(null)
		);
		/// <summary>
		/// Identifies <see cref="CategoryPath"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty CategoryPathProperty = DependencyProperty.Register(
			nameof(CategoryPath), typeof(string), typeof(HeatmapSeries), new PropertyMetadata(null, new PropertyChangedCallback(PropertyChanged_ValueDirty))
		);
		/// <summary>
		/// Identifies <see cref="Category2Path"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty Category2PathProperty = DependencyProperty.Register(
			nameof(Category2Path), typeof(string), typeof(HeatmapSeries), new PropertyMetadata(null, new PropertyChangedCallback(PropertyChanged_ValueDirty))
		);
		/// <summary>
		/// Identifies <see cref="ValuePath"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty ValuePathProperty = DependencyProperty.Register(
			nameof(ValuePath), typeof(string), typeof(HeatmapSeries), new PropertyMetadata(null, new PropertyChangedCallback(PropertyChanged_ValueDirty))
		);
		/// <summary>
		/// Identifies <see cref="ValueLabelPath"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty ValueLabelPathProperty = DependencyProperty.Register(
			nameof(ValueLabelPath), typeof(string), typeof(HeatmapSeries), new PropertyMetadata(null, new PropertyChangedCallback(PropertyChanged_ValueDirty))
		);
		/// <summary>
		/// Identifies <see cref="Title"/> dependency property.
		/// </summary>
		public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
			nameof(Title), typeof(String), typeof(HeatmapSeries), new PropertyMetadata("Title")
		);
		#endregion
		#region ctor
		/// <summary>
		/// Default ctor.
		/// </summary>
		public HeatmapSeries() {
			ItemState = new List<ItemState<Path>>();
		}
		#endregion
		#region helpers
		/// <summary>
		/// Resolve axis references with error info.
		/// </summary>
		/// <param name="icrc">The context.</param>
		protected void EnsureAxes(IChartComponentContext icrc) {
			IChartErrorInfo icei = icrc as IChartErrorInfo;
			if (CategoryAxis2 == null) {
				if (!String.IsNullOrEmpty(CategoryAxis2Name)) {
					CategoryAxis2 = icrc.Find(CategoryAxis2Name) as IChartAxis;
					if (CategoryAxis2 == null) {
						icei?.Report(new ChartValidationResult(NameOrType(), $"Value axis '{CategoryAxis2Name}' was not found", new[] { nameof(CategoryAxis2), nameof(CategoryAxis2Name) }));
					}
				}
				else {
					icei?.Report(new ChartValidationResult(NameOrType(), $"Property '{nameof(CategoryAxis2)}' was not set", new[] { nameof(CategoryAxis2), nameof(CategoryAxis2) }));
				}
			}
			if (CategoryAxis1 == null) {
				if (!String.IsNullOrEmpty(CategoryAxisName)) {
					CategoryAxis1 = icrc.Find(CategoryAxisName) as IChartAxis;
					if (CategoryAxis1 == null) {
						icei?.Report(new ChartValidationResult(NameOrType(), $"Value axis '{CategoryAxisName}' was not found", new[] { nameof(CategoryAxis1), nameof(CategoryAxisName) }));
					}
				}
				else {
					icei?.Report(new ChartValidationResult(NameOrType(), $"Property '{nameof(CategoryAxisName)}' was not set", new[] { nameof(CategoryAxis1), nameof(CategoryAxisName) }));
				}
			}
		}
		/// <summary>
		/// Report an error if the <see cref="ValuePath"/> was not configured.
		/// </summary>
		/// <param name="iccc"></param>
		protected void EnsureValuePath(IChartComponentContext iccc) {
			if (String.IsNullOrEmpty(ValuePath)) {
				(iccc as IChartErrorInfo)?.Report(new ChartValidationResult(NameOrType(), $"{nameof(ValuePath)} was not set, no values will generate", new[] { nameof(ValuePath) }));
			}
		}
		/// <summary>
		/// Reset the value and category limits to <see cref="double.NaN"/>.
		/// Sets <see cref="ChartComponent.Dirty"/> = true.
		/// </summary>
		protected void ResetLimits() {
			Minimum = double.NaN; Maximum = double.NaN;
			//CategoryMinimum = double.NaN; CategoryMaximum = double.NaN;
			Dirty = true;
		}
		/// <summary>
		/// Update value and category limits.
		/// If a value is <see cref="double.NaN"/>, it is effectively ignored because NaN is NOT GT/LT ANY number, even itself.
		/// </summary>
		/// <param name="vx">Value.  MAY be NaN.</param>
		protected void UpdateLimits(double vx) {
			if (double.IsNaN(Minimum) || vx < Minimum) { Minimum = vx; }
			if (double.IsNaN(Maximum) || vx > Maximum) { Maximum = vx; }
		}
		/// <summary>
		/// Path factory for recycler.
		/// </summary>
		/// <param name="isp">Not used.</param>
		/// <returns></returns>
		Path CreatePath(ItemState<Path> isp) {
			var path = default(Path);
			if (PathTemplate != null) {
				path = PathTemplate.LoadContent() as Path;
			}
			else if (Theme?.PathTemplate != null) {
				path = Theme.PathTemplate.LoadContent() as Path;
				if (PathStyle != null) {
					BindTo(this, nameof(PathStyle), path, FrameworkElement.StyleProperty);
				}
			}
			return path;
		}
		/// <summary>
		/// Core element processing.
		/// The <see cref="RectangleGeometry"/> inside the <see cref="Path"/> is now location-invariant wrt x-axis.
		/// This means that during incremental updates, no re-calculation is required, only adjusting the <see cref="Canvas.LeftProperty"/>.
		/// </summary>
		/// <param name="index">Data index.</param>
		/// <param name="valuec1">C1 (x-axis) index.</param>
		/// <param name="valuec2">C2 (y-axis) index.</param>
		/// <param name="value">Cell value.</param>
		/// <param name="item"></param>
		/// <param name="recycler"></param>
		/// <param name="byl"></param>
		/// <returns></returns>
		ItemState<Path> ElementPipeline(int index, int valuec1, int valuec2, double value,  object item, Recycler<Path, ItemState<Path>> recycler, BindingEvaluator byl) {
			var path = recycler.Next(null);
			if (path == null) return null;
			var shim = new GeometryWith2OffsetShim<RectangleGeometry>() {
				// MUST use invariant geometry here so it can translate.
				PathData = new RectangleGeometry() { Rect = new Rect(new Point(0, 0), new Point(1, 1)) }
			};
			path.Item2.DataContext = shim;
			// connect the shim to template root element's Visibility
			BindTo(shim, nameof(shim.Visibility), path.Item2, UIElement.VisibilityProperty);
			BindTo(shim, nameof(shim.Offset), path.Item2, Canvas.LeftProperty);
			BindTo(shim, nameof(shim.Offset2), path.Item2, Canvas.TopProperty);
			if (byl == null) {
				return new SeriesItemState_Double(index, valuec1, 0, valuec2, value, path.Item2);
			}
			else {
				var cs = byl.For(item);
				return new SeriesItemState_Custom(index, valuec1, 0, valuec2, value, cs, path.Item2);
			}
		}
		#endregion
		#region IProvideLegend
		private LegendBase _legend;
		IEnumerable<LegendBase> IProvideLegend.LegendItems {
			get {
				if(StyleGenerator != null) {
					return StyleGenerator.LegendFor(new Category2StyleContext(CategoryAxis1, CategoryAxis2, this, new double[0]), Title, PathStyle);
				}
				if (_legend == null) _legend = Legend(); return new[] { _legend };
			}
		}
		Legend Legend() {
			return new Legend() { Title = Title, Fill = PathStyle.Find<Brush>(Path.FillProperty), Stroke = PathStyle.Find<Brush>(Path.StrokeProperty) };
		}
		#endregion
		#region IRequireEnterLeave
		/// <summary>
		/// Initialize after entering VT.
		/// </summary>
		/// <param name="icelc"></param>
		void IRequireEnterLeave.Enter(IChartEnterLeaveContext icelc) {
			EnsureAxes(icelc as IChartComponentContext);
			EnsureValuePath(icelc as IChartComponentContext);
			Layer = icelc.CreateLayer();
			_trace.Verbose($"{Name} enter c2(v):{CategoryAxis2Name} {CategoryAxis2} c1:{CategoryAxisName} {CategoryAxis1} d:{DataSourceName}");
			if (PathTemplate == null) {
				if (Theme?.PathTemplate == null) {
					(icelc as IChartErrorInfo)?.Report(new ChartValidationResult(NameOrType(), $"No {nameof(PathTemplate)} and {nameof(Theme.PathTemplate)} was not found", new[] { nameof(PathTemplate), nameof(Theme.PathTemplate) }));
				}
			}
			AssignFromRef(icelc as IChartErrorInfo, NameOrType(), nameof(PathStyle), nameof(Theme.PathColumnSeries),
				PathStyle == null, Theme != null, Theme.PathColumnSeries != null,
				() => PathStyle = Theme.PathColumnSeries
			);
			BindPaths = new Evaluators2(CategoryPath, Category2Path, ValuePath, ValueLabelPath);
			if (!BindPaths.IsValid) {
				(icelc as IChartErrorInfo)?.Report(new ChartValidationResult(NameOrType(), $"ValuePath: must be specified", new[] { nameof(ValuePath) }));
			}
		}
		/// <summary>
		/// Undo effects of Enter().
		/// </summary>
		/// <param name="icelc"></param>
		void IRequireEnterLeave.Leave(IChartEnterLeaveContext icelc) {
			_trace.Verbose($"{Name} leave");
			BindPaths = null;
			CategoryAxis2 = null;
			CategoryAxis1 = null;
			icelc.DeleteLayer(Layer);
			Layer = null;
		}
		#endregion
		#region IRequireTransforms
		/// <summary>
		/// Adjust transforms for the various components.
		/// Geometry: scaled to actual values in cartesian coordinates as indicated by axes.
		/// </summary>
		/// <param name="icrc"></param>
		void IRequireTransforms.Transforms(IChartRenderContext icrc) {
			if (CategoryAxis1 == null || CategoryAxis2 == null) return;
			if (ItemState.Count == 0) return;
			// TODO quad depends on orientations of both axes this is assuming default orientations
			var mat = MatrixSupport.DataArea(CategoryAxis1, CategoryAxis2, icrc.SeriesArea, 4);
			var matmp = MatrixSupport.Multiply(mat.Item1, mat.Item2);
			_trace.Verbose($"{Name} matmp:{matmp} clip:{icrc.SeriesArea}");
			var mt = new MatrixTransform() { Matrix = matmp };
			foreach (var state in ItemState) {
				if (state.Element.DataContext is GeometryWith2OffsetShim<RectangleGeometry> gs) {
					gs.GeometryTransform = mt;
					var output = matmp.Transform(new Point(state.XValue, (state as IProvideYValue).YValue));
					gs.Offset = output.X - icrc.SeriesArea.Left;
					gs.Offset2 = output.Y - icrc.SeriesArea.Top;
				}
				else {
					state.Element.Data.Transform = mt;
				}
				if (ClipToDataRegion) {
					var cg = new RectangleGeometry() { Rect = icrc.SeriesArea };
					state.Element.Clip = cg;
				}
			}
		}
		#endregion
		#region IRequireAfterAxesFinalized
		void IRequireAfterAxesFinalized.AxesFinalized(IChartRenderContext icrc) {
			if (icrc.Type == RenderType.TransformsOnly) return;
			var mat = MatrixSupport.DataArea(CategoryAxis1, CategoryAxis2, icrc.SeriesArea, 4);
			var matmp = MatrixSupport.Multiply(mat.Item1, mat.Item2);
			_trace.Verbose($"{Name} matmp:{matmp} clip:{icrc.SeriesArea}");
			var mt = new MatrixTransform() { Matrix = matmp };
			StyleGenerator?.Reset();
			foreach (var istate in ItemState) {
				if (istate.Element.DataContext is GeometryWith2OffsetShim<RectangleGeometry> gs) {
					gs.GeometryTransform = mt;
				}
				else {
					istate.Element.Data.Transform = mt;
				}
				if(StyleGenerator != null) {
					var style = StyleGenerator.For(new Category2StyleContext(CategoryAxis1, CategoryAxis2, this, new double[3] { istate.Value, istate.XValue, (istate as IProvideYValue).YValue }));
					if(style != null) {
						istate.Element.Style = style;
					}
					else {
						if (PathStyle != null) {
							BindTo(this, nameof(PathStyle), istate.Element, FrameworkElement.StyleProperty);
						}
					}
				}
			}
			StyleGenerator?.UpdateLegend(new Category2StyleContext(CategoryAxis1, CategoryAxis2, this, new double[0]));
		}
		#endregion
		#region IDataSourceRenderer
		internal class RenderState_Heatmap<SIS, EL> : RenderStateCore<SIS, EL> where SIS : class where EL : FrameworkElement {
			/// <summary>
			/// Evaluators for core values.
			/// </summary>
			internal readonly Evaluators2 evs;
			/// <summary>
			/// Ctor.
			/// </summary>
			/// <param name="state">Starting state; SHOULD be empty.</param>
			/// <param name="rc">The recycler.</param>
			/// <param name="evs">Evaluators.</param>
			internal RenderState_Heatmap(List<SIS> state, Recycler<EL, SIS> rc, Evaluators2 evs) : base(state, rc) {
#pragma warning disable IDE0016 // Use 'throw' expression
				if (evs == null) throw new ArgumentNullException(nameof(evs));
				if (evs.by == null) throw new ArgumentNullException(nameof(evs.by));
#pragma warning restore IDE0016 // Use 'throw' expression
				this.evs = evs;
			}
		}
		object IDataSourceRenderer.Preamble(IChartRenderContext icrc) {
			if (CategoryAxis1 == null || CategoryAxis2 == null) return null;
			if (BindPaths == null || !BindPaths.IsValid) return null;
			ResetLimits();
			var paths = ItemState.Select(ms => ms.Element).Where(el => el != null);
			var recycler = new Recycler<Path, ItemState<Path>>(paths, CreatePath);
			return new RenderState_Heatmap<ItemState<Path>, Path>(new List<ItemState<Path>>(), recycler, BindPaths);
		}
		void IDataSourceRenderer.Render(object state, int index, object item) {
			var st = state as RenderState_Heatmap<ItemState<Path>, Path>;
			var valuec1 = st.evs.Category1For(item);
			var valuec2 = st.evs.Category2For(item);
			var value = st.evs.ValueFor(item);
			st.ix = index;
			// short-circuit if it's NaN
			if (double.IsNaN(value)) {
				return;
			}
			UpdateLimits(value);
			var istate = ElementPipeline(index, valuec1, valuec2, value, item, st.recycler, st.evs.byl);
			if (istate != null) st.itemstate.Add(istate);
		}
		void IDataSourceRenderer.RenderComplete(object state) {}
		void IDataSourceRenderer.Postamble(object state) {
			var st = state as RenderState_Heatmap<ItemState<Path>, Path>;
			ItemState = st.itemstate;
			Layer.Remove(st.recycler.Unused);
			Layer.Add(st.recycler.Created);
			Dirty = false;
		}
		#endregion
	}
	#endregion
}

redpajama_set_name: RedPajamaGithub


text:
class UNIX_ApplicationSystemHierarchyFixture :
	public CIMFixtureBase
{
public:
	UNIX_ApplicationSystemHierarchyFixture();
	~UNIX_ApplicationSystemHierarchyFixture();
	virtual void Run();

};


text:
<?php declare(strict_types = 1);

namespace Contributte\Wordcha\DataSource;

class Pair
{

	/** @var string */
	private $question;

	/** @var string */
	private $answer;

	public function __construct(string $question, string $answer)
	{
		$this->question = $question;
		$this->answer = $answer;
	}

	public function getQuestion(): string
	{
		return $this->question;
	}

	public function getAnswer(): string
	{
		return $this->answer;
	}

}


text:
package models

import akka.actor.{Actor, Props}
import models.Plotter.{PlotData, ChartPath}

import scalax.chart.api._

/**
  * mini actor to plot data
  */
object Plotter{
  val props = Props(new Plotter)
  val name = "plotter"

  case class PlotData(data: Seq[(Int,Int)])
  case class ChartPath(name: String)
}

class Plotter extends Actor{
  def receive: Receive = {
    case PlotData(data) =>
      implicit val theme = org.jfree.chart.StandardChartTheme.createLegacyTheme()
      val chart = XYLineChart(data,s"count of the ${data.map(_._2).sum} evals")
      val chartPath = s"/tmp/chart"+scala.math.random+".png"
      chart.saveAsPNG(chartPath)
      sender ! ChartPath(chartPath)
  }
}


text:
namespace llvm {
class TargetMachine;

namespace AMDGPUIntrinsic {
enum ID {
  last_non_AMDGPU_intrinsic = Intrinsic::num_intrinsics - 1,
#define GET_INTRINSIC_ENUM_VALUES
#include "AMDGPUGenIntrinsics.inc"
#undef GET_INTRINSIC_ENUM_VALUES
      , num_AMDGPU_intrinsics
};

} // end namespace AMDGPUIntrinsic

class AMDGPUIntrinsicInfo final : public TargetIntrinsicInfo {
public:
  AMDGPUIntrinsicInfo();

  StringRef getName(unsigned IntrId, ArrayRef<Type *> Tys = None) const;

  std::string getName(unsigned IntrId, Type **Tys = nullptr,
                      unsigned NumTys = 0) const override;

  unsigned lookupName(const char *Name, unsigned Len) const override;
  bool isOverloaded(unsigned IID) const override;
  Function *getDeclaration(Module *M, unsigned ID,
                           Type **Tys = nullptr,
                           unsigned NumTys = 0) const override;

  Function *getDeclaration(Module *M, unsigned ID,
                           ArrayRef<Type *> = None) const;

  FunctionType *getType(LLVMContext &Context, unsigned ID,
                        ArrayRef<Type*> Tys = None) const;
};

} // end namespace llvm

#endif


text:
<?php

namespace Magento\Customer\Test\Unit\Model\Customer\Attribute\Backend;

use Magento\Customer\Model\Customer\Attribute\Backend\Billing;

class BillingTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var Billing
     */
    protected $testable;

    protected function setUp()
    {
        $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
        /** @var \Psr\Log\LoggerInterface $logger */
        $this->testable = new \Magento\Customer\Model\Customer\Attribute\Backend\Billing($logger);
    }

    public function testBeforeSave()
    {
        $object = $this->getMockBuilder('Magento\Framework\DataObject')
            ->disableOriginalConstructor()
            ->setMethods(['getDefaultBilling', 'unsetDefaultBilling'])
            ->getMock();

        $object->expects($this->once())->method('getDefaultBilling')->will($this->returnValue(null));
        $object->expects($this->once())->method('unsetDefaultBilling')->will($this->returnSelf());
        /** @var \Magento\Framework\DataObject $object */

        $this->testable->beforeSave($object);
    }

    public function testAfterSave()
    {
        $addressId = 1;
        $attributeCode = 'attribute_code';
        $defaultBilling = 'default billing address';
        $object = $this->getMockBuilder('Magento\Framework\DataObject')
            ->disableOriginalConstructor()
            ->setMethods(['getDefaultBilling', 'getAddresses', 'setDefaultBilling'])
            ->getMock();

        $address = $this->getMockBuilder('Magento\Framework\DataObject')
            ->disableOriginalConstructor()
            ->setMethods(['getPostIndex', 'getId'])
            ->getMock();

        $attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
            ->setMethods(['__wakeup', 'getEntity', 'getAttributeCode'])
            ->disableOriginalConstructor()
            ->getMockForAbstractClass();

        $entity = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
            ->setMethods(['saveAttribute'])
            ->disableOriginalConstructor()
            ->getMockForAbstractClass();

        $attribute->expects($this->once())->method('getEntity')->will($this->returnValue($entity));
        $attribute->expects($this->once())->method('getAttributeCode')->will($this->returnValue($attributeCode));
        $entity->expects($this->once())->method('saveAttribute')->with($this->logicalOr($object, $attributeCode));
        $address->expects($this->once())->method('getPostIndex')->will($this->returnValue($defaultBilling));
        $address->expects($this->once())->method('getId')->will($this->returnValue($addressId));
        $object->expects($this->once())->method('getDefaultBilling')->will($this->returnValue($defaultBilling));
        $object->expects($this->once())->method('setDefaultBilling')->with($addressId)->will($this->returnSelf());
        $object->expects($this->once())->method('getAddresses')->will($this->returnValue([$address]));
        /** @var \Magento\Framework\DataObject $object */
        /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */

        $this->testable->setAttribute($attribute);
        $this->testable->afterSave($object);
    }
}


text:
import {computed, customElement, property} from '@polymer/decorators';
import {html, PolymerElement} from '@polymer/polymer';
import * as _ from 'lodash';
import {LegacyElementMixin} from '../../../components/polymer/legacy_element_mixin';
import {getTags} from '../../../components/tf_backend/backend';
import {RequestManager} from '../../../components/tf_backend/requestManager';
import {getRouter} from '../../../components/tf_backend/router';
import {categorizeRunTagCombinations} from '../../../components/tf_categorization_utils/categorizationUtils';
import '../../../components/tf_categorization_utils/tf-tag-filterer';
import '../../../components/tf_dashboard_common/dashboard-style';
import '../../../components/tf_dashboard_common/tf-dashboard-layout';
import '../../../components/tf_paginated_view/tf-category-paginated-view';
import '../../../components/tf_runs_selector/tf-runs-selector';
import './tf-audio-loader';
import {AudioTagInfo, TfAudioLoader} from './tf-audio-loader';

/*
tf-audio-dashboard displays a dashboard that loads audio from a TensorFlow run.
*/
@customElement('tf-audio-dashboard')
class TfAudioDashboard extends LegacyElementMixin(PolymerElement) {
  static readonly template = html`
    <tf-dashboard-layout>

          <tf-runs-selector
            id="runs-selector"
            selected-runs="{{_selectedRuns}}"
          ></tf-runs-selector>

        <template is="dom-if" if="[[_dataNotFound]]">

No audio data was found.

Probable causes:

You haven't written any audio data to your event files.

TensorBoard can't find your event files.

              If you're new to using TensorBoard, and want to find out how to
              add data and set up your event files, check out the
              README
              and perhaps the
              TensorBoard tutorial.

              If you think TensorBoard is configured properly, please see
              the section of the README devoted to missing data problems
              and consider filing an issue on GitHub.

        </template>
        <template is="dom-if" if="[[!_dataNotFound]]">
          <tf-tag-filterer tag-filter="{{_tagFilter}}"></tf-tag-filterer>
          <template is="dom-repeat" items="[[_categories]]" as="category">
            <tf-category-paginated-view
              category="[[category]]"
              initial-opened="[[_shouldOpen(index)]]"
            >
              <template>
                <tf-audio-loader
                  active="[[active]]"
                  run="[[item.run]]"
                  tag="[[item.tag]]"
                  sample="[[item.sample]]"
                  total-samples="[[item.totalSamples]]"
                  tag-metadata="[[_tagMetadata(_runToTagInfo, item.run, item.tag)]]"
                  request-manager="[[_requestManager]]"
                ></tf-audio-loader>
              </template>
            </tf-category-paginated-view>
          </template>
        </template>

    </tf-dashboard-layout>

  `;

  @property({type: Boolean})
  reloadOnReady: boolean = true;

  @property({type: Array})
  _selectedRuns: string[];

  @property({type: Object})
  _runToTagInfo: {[run: string]: {[tag: string]: AudioTagInfo}};

  @property({type: Boolean})
  _dataNotFound: boolean;

  @property({type: String})
  _tagFilter: string = '';

  @property({type: Object})
  _requestManager: RequestManager = new RequestManager();

  ready() {
    super.ready();
    if (this.reloadOnReady) this.reload();
  }

  reload() {
    this._fetchTags().then(() => {
      this._reloadAudio();
    });
  }

  _fetchTags() {
    const url = getRouter().pluginRoute('audio', '/tags');
    return this._requestManager.request(url).then((runToTagInfo) => {
      if (_.isEqual(runToTagInfo, this._runToTagInfo)) {
        // No need to update anything if there are no changes.
        return;
      }
      const runToTag = _.mapValues(runToTagInfo, (x) => Object.keys(x));
      const tags = getTags(runToTag);
      this.set('_dataNotFound', tags.length === 0);
      this.set('_runToTagInfo', runToTagInfo);
    });
  }

  _reloadAudio() {
    this.root?.querySelectorAll('tf-audio-loader').forEach((audio) => {
      (audio as TfAudioLoader).reload();
    });
  }

  _shouldOpen(index) {
    return index <= 2;
  }

  @computed('_runToTagInfo', '_selectedRuns', '_tagFilter')
  get _categories(): unknown[] {
    var runToTagInfo = this._runToTagInfo;
    var selectedRuns = this._selectedRuns;
    var tagFilter = this._tagFilter;
    const runToTag = _.mapValues(runToTagInfo, (x) => Object.keys(x));
    const baseCategories = categorizeRunTagCombinations(
      runToTag,
      selectedRuns,
      tagFilter
    );
    function explodeItem(item) {
      const samples = runToTagInfo[item.run][item.tag].samples;
      return _.range(samples).map((i) =>
        Object.assign({}, item, {
          sample: i,
          totalSamples: samples,
        })
      );
    }
    const withSamples = baseCategories.map((category) =>
      Object.assign({}, category, {
        items: [].concat.apply([], category.items.map(explodeItem)),
      })
    );
    return withSamples;
  }

  _tagMetadata(runToTagInfo, run, tag) {
    return runToTagInfo[run][tag];
  }
}


text:
/**
 * Created by exodia on 14-8-28.
 */
void function (define, undefined) {

    define(
        function (require) {
            var MEMBERS = '__eooPrivateMembers__';

            function simpleGetter(name) {
                var body = 'return typeof this.' + MEMBERS + ' === \'object\' ? this.'
                    + MEMBERS + '[\'' + name + '\'] : undefined;';
                return new Function(body);
            }

            function simpleSetter(name) {
                var body = 'this.' + MEMBERS + ' = this.' + MEMBERS + ' || {};\n'
                    + 'this.' + MEMBERS + '[\'' + name + '\'] = value;' ;
                return new Function('value', body);
            }

            /**
             * 根据指定的属性名生成对应的accessor
             *
             * @param {Object | Function} obj 需要生成 accessor 的对象
             * @param {string} name 需要生成 accessor 的属性名称
             * @param {Object | Function} [accessor] 自定义的 getter 和 setter 配置
             * @param {Function} [accessor.get] 自定义的 getter 函数, 配置了accessor,但未设置 get,则不会生成 getter
             * @param {Function} [accessor.set] 自定义的 setter 函数, 配置了accessor,但未设置 set,则不会生成 setter
             */
            return function (obj, name, accessor) {
                var upperName = name.charAt(0).toUpperCase() + name.slice(1);
                var getter = 'get' + upperName;
                var setter = 'set' + upperName;

                if (!accessor) {
                    obj[getter] = !accessor || typeof accessor.get !== 'function' ? simpleGetter(name) : accessor.get;
                    obj[setter] = !accessor || typeof accessor.set !== 'function' ? simpleSetter(name) : accessor.set;
                }
                else {
                    typeof accessor.get === 'function' && (obj[getter] = accessor.get);
                    typeof accessor.set === 'function' && (obj[setter] = accessor.set);
                }
            };
        }
    );

}(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });


text:
title: Spline Area Charts
page_title: Spline Area Charts - UI for WinForms Documentation
description: Spline Area Charts
slug: winforms/chart/understanding-radchart-types/spline-area-charts
tags: spline,area,charts
published: True
position: 10
previous_url: chart-undestanding-radchart-types-spline-area-charts
---

# Spline Area Charts

##

Spline charts allow you to take a limited set of known data points and approximate intervening values. In the Spline Area Chart the area defined by the spline curve is filled. In practice you define a series of chart items and RadChart does the rest. Each series overlays the preceding, from back to front.

To create a simple vertical Spline Area Chart set the __SeriesOrientation__ property to __Vertical__. Set the RadChart __DefaultType__ property or __ChartSeries.Type__ to __SplineArea__. Create one or more series and add chart items with Y or X and Y values.
>caption

![chart-undestanding-radchart-types-spline-area-charts 002](images/chart-undestanding-radchart-types-spline-area-charts002.png)

To create a simple vertical Spline Area Chart set the __SeriesOrientation__ property to __Horizontal__. Set the RadChart __DefaultType__ property or __ChartSeries.Type__ to __SplineArea__. Create one or more series and add chart items with Y or X and Y values.
>caption

![chart-undestanding-radchart-types-spline-area-charts 001](images/chart-undestanding-radchart-types-spline-area-charts001.png)


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xunit.Extensions;
using Xunit.Sdk;

namespace BCLExtensions.Tests.TestHelpers
{
    public class EnumerablePermutationDataAttribute : DataAttribute
    {
        private readonly List<IDataProvider> _providers = new List<IDataProvider>();

        public EnumerablePermutationDataAttribute()
        {
            _providers.Add(new EnumerableProvider<string>(new StringProvider()));
            _providers.Add(new EnumerableProvider<int>(new IntProvider()));
            _providers.Add(new ArrayProvider<string>(new StringProvider()));
            _providers.Add(new ArrayProvider<int>(new IntProvider()));
            _providers.Add(new ListProvider<string>(new StringProvider()));
            _providers.Add(new ListProvider<int>(new IntProvider()));
            _providers.Add(new CollectionProvider<string>(new StringProvider()));
            _providers.Add(new CollectionProvider<int>(new IntProvider()));
            _providers.Add(new CustomICollectionProvider<string>(new StringProvider()));
            _providers.Add(new CustomICollectionProvider<int>(new IntProvider()));
            _providers.Add(new DictionaryProvider<string>(new StringProvider()));
            _providers.Add(new DictionaryProvider<int>(new IntProvider()));
        }

        public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest)
        {
            return _providers.Select(provider => new object[] {provider.GetPlaceholder(), provider});
        }
    }
}


text:
<link rel="icon" type="images/png" href="images/favicon.png">

		<link rel="stylesheet" href="../style.css">
		<link rel="stylesheet" type="text/css" href="engine1/style.css" />

		 <?php include('../header.php');?>
		<?php include('../left_header.php');?>
		<?php include('../right_header.php');?>

Dedication

I would sincerely like to thank my parents. They are the one without whom I would not have be in correct path.

						I would sincerely like to thank my father Md. Mustafa Alam, who was silently there holding my back both emotionally as well as financially. Hey dad I have never said this to you but I always wanted to..
 "I really love you dad.. You are the best dad every child would want. I hope one day I would become humble and sincere like you"

						The next person is my mother Shaista Mustafa. She is my strength. Mom this is for you..
						You are my best friend. Thank you for support.

The next person is my sister Farhin Naaz Khan and my Naushebhai Imran Khan. I am blessed to have a sister like you. Sometimes there are lot of things one cannot share with parents. Sisters are the perfect friend to share. Thank you Appi for always being there. Thank you Naushebhai. Missing you all.

The next person is my sweet brother Nasir Mustafa. One should never go by his sweetness, the naughtiest in our family. Hey bro if you are reading this, I am lucky you being a part of my life. You know our love is like brothers in fight, you too appi. We always use to fight in petty things. Once I am out here without you all.. missing those fights, missing those good moments and you too bro. God Bless you.

						Love You All,

						Amir Mustafa.

			<?php include_once('../footer.php'); ?>


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>CronWTF!</title>

    <form>

        <textarea id="cron">0 0 0 0 0 COMMAND</textarea>

instructions, tests, code

    </form>


text:
<?php

class Bitanical_Newsflash_IndexController extends Mage_Core_Controller_Front_Action
{
    /**
     * Shows a list of available items
     */
    public function indexAction()
    {
        $this->loadLayout();
        $this->renderLayout();
        return $this;
    }

    /**
     * Show a list of testimonials
     */
    public function testimonialsAction()
    {
        $this->loadLayout();
        $this->renderLayout();
        return $this;
    }

    /**
     * Show a list of articles
     */
    public function articlesAction()
    {
        $this->loadLayout();
        $this->renderLayout();
        return $this;
    }

    /**
     * Shows an individual news item
     */
    public function viewAction()
    {
        $itemId = $this->getItemId();
        if ($itemId) {
            $item = $this->loadModel($itemId);
            if ($item->getId()) {

                $preview = $this->getRequest()->getParam('preview');

                $isActive = ($item->getId() && $item->getIsActive());
                $today = new DateTime();
                $itemDate = new DateTime($item->getItemDate());
                $isAvail = ($today >= $itemDate);

                if (($isActive && $isAvail) || $preview)
                {
                    Mage::register('newsflash_current_item', $item);
                    $this->loadLayout();
                    $this->_initLayoutMessages('customer/session');
                    $this->renderLayout();
                    return $this;
                }

            }
        }
        $this->_forward('noroute');
        return $this;
    }

    /**
     * Retrieve the itemId, which is either
     * an id or a slug
     *
     * @return string|false
     */
    private function getItemId()
    {
        $itemId   = $this->getRequest()->getParam('id');
        $itemSlug = $this->getRequest()->getParam('slug');
        if ($itemId) return $itemId;
        elseif ($itemSlug) return $itemSlug;
        else return false;
    }

    /**
     * Loads the model by id or slug
     *
     * @param $itemId The id or slug
     * @return Bitanical_Newsflash_Model_Item|null
     */
    private function loadModel($itemId)
    {
        $item = Mage::getModel('bitanical_newsflash/item');
        if (is_numeric($itemId))
        {
            return $item->load($itemId);
        }
        else
        {
            return $item = $item->loadBySlug($itemId);
        }
    }

}


text:
<?php

namespace Zend\Session\Validator;

use Zend\Session\Validator as SessionValidator;

/**
 * @uses       Zend\Session\Validator
 * @category   Zend
 * @package    Zend_Session
 * @subpackage Validator
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class HttpUserAgent implements SessionValidator
{
    /**
     * Constructor - get the current user agent and store it in the session
     * as 'valid data'
     *
     * @return void
     */
    public function __construct($data = null)
    {
        if (empty($data)) {
            $data = isset($_SERVER['HTTP_USER_AGENT'])
                  ? $_SERVER['HTTP_USER_AGENT']
                  : null;
        }
        $this->_data = $data;
    }

    /**
     * isValid() - this method will determine if the current user agent matches the
     * user agent we stored when we initialized this variable.
     *
     * @return bool
     */
    public function isValid()
    {
        $userAgent = isset($_SERVER['HTTP_USER_AGENT'])
                   ? $_SERVER['HTTP_USER_AGENT']
                   : null;

        return $userAgent === $this->getData();
    }

    /**
     * Retrieve token for validating call
     *
     * @return string
     */
    public function getData()
    {
        return $this->_data;
    }

    /**
     * Return validator name
     *
     * @return string
     */
    public function getName()
    {
        return __CLASS__;
    }
}


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 org.apache.aries.cdi.container.internal.util;

import java.io.PrintWriter;
import java.io.StringWriter;

public class Throw {

	private Throw() {
		// no instances
	}

	public static <T> T exception(Throwable throwable) {
		return Throw.<T, RuntimeException>_exception(throwable);
	}

	@SuppressWarnings("unchecked")
	private static <T, E extends Throwable> T _exception(Throwable throwable) throws E {
		throw (E)throwable;
	}

	public static String asString(Throwable t) {
		StringWriter sw = new StringWriter();
		t.printStackTrace(new PrintWriter(sw));
		return sw.toString();
	}

}


text:
<?xml version="1.0" encoding="UTF-8" ?>
<project name="Codiad" basedir="." default="phpcs">

	<fileset id="components" dir="./components">
		<include name="**/*.php" />
	</fileset>

	<target name="phpcs">
		<phpcodesniffer
			standard="PSR2"
			showSniffs="false"
			showWarnings="true"
		 haltonerror="${build.haltonanalysiserror}">
			<fileset refid="components" />
			<formatter type="full" usefile="false" />
		</phpcodesniffer>
	</target>

</project>


text:
package info.iconmaster.typhon.linker;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import info.iconmaster.typhon.errors.UnresolvedImportError;
import info.iconmaster.typhon.model.Import;
import info.iconmaster.typhon.model.Package;
import info.iconmaster.typhon.model.TyphonModelReader;
import info.iconmaster.typhon.model.Import.PackageImport;
import info.iconmaster.typhon.model.Import.RawImport;
import info.iconmaster.typhon.model.libs.CorePackage;

/**
 * This class contains methods for resolving imports in Typhon code.
 *
 * @author iconmaster
 *
 */
public class TyphonLinker {
	private TyphonLinker() {}

	/**
	 * Resolves all imports in a package.
	 *
	 * @param p
	 */
	public static void link(Package p) {
		// gather imports
		ArrayList<Import> imports = new ArrayList<>();
		gatherImports(imports, p);

		// attempt to resolve imports.
		// to handle cyclic imports, etc. we do this in a loop until they're all either resolved or unresolved.
		boolean allUnresolved = false;

		do {
			for (Import i : imports) {
				link(i);
			}

			allUnresolved = imports.isEmpty() ? false : imports.stream().allMatch((i)->!i.isResolved());

			int n = imports.size();
			imports = imports.stream().filter((i)->!i.isResolved()).collect(Collectors.toCollection(()->new ArrayList<>(n)));
		} while (!imports.isEmpty() && !allUnresolved);

		// if allUnresolved, then add the errors for unresolved imports
		if (allUnresolved) {
			for (Import i : imports) {
				p.tni.errors.add(new UnresolvedImportError(i));
			}
		}
	}

	/**
	 * Attempts to resolve an import.
	 * This function will update the fields in the import for you, and will move around packages to implement package aliases.
	 *
	 * @param toResolve The import to resolve.
	 */
	public static void link(Import toResolve) {
		if (toResolve.isResolved()) {
			return;
		}

		// resolve the import
		if (toResolve instanceof PackageImport) {
			PackageImport i = (PackageImport) toResolve;

			Package base = i.getParent();
			outOfLoop: {
				while (base != null) {
					List<Package> matches = new ArrayList<>();
					matches.add(base);

					for (String s : i.getPackageName()) {
						List<Package> newMatches = new ArrayList<>();

						for (Package match : matches) {
							if (match instanceof CorePackage) {
								// if we're looking at the core package, we need to check for library names
								newMatches.addAll(((CorePackage)match).getCoreSubpackagesWithName(s));
							} else {
								// Else, look at subpackages
								newMatches.addAll(match.getSubpackagesWithName(s));
							}
						}

						matches = newMatches;
					}

					if (!matches.isEmpty()) {
						i.getResolvedTo().addAll(matches);
						i.isResolved(true);
						break outOfLoop;
					}

					base = base.getParent();
				}
			}
		} else if (toResolve instanceof RawImport) {
			RawImport i = (RawImport) toResolve;

			Package resolvedTo = null;
			for (File file : i.tni.rawImportLookupPaths) {
				File toCheck = Paths.get(file.toString(), i.getImportData()).toFile();
				if (toCheck.exists()) {
					try {
						resolvedTo = TyphonModelReader.parseFile(i.tni, toCheck);
						break;
					} catch (IOException e) {
						// ignore; we'll assume there's another viable candidate in the lookup paths
					}
				}
			}

			if (resolvedTo != null) {
				i.getResolvedTo().add(resolvedTo);
				i.isResolved(true);
			}
		} else {
			throw new IllegalArgumentException("Unknown sublclass of Import");
		}

		// handle the alias (but only if resolved, so we only do this once)
		if (toResolve.isResolved() && !toResolve.getAliasName().isEmpty()) {
			Package base = toResolve.getParent();
			for (String s : toResolve.getAliasName()) {
				base = new Package(toResolve.source, s, base);
			}
			base.addImport(toResolve);
			toResolve.getAliasName().clear();
		}
	}

	/**
	 * Given a package, finds all the imports in the package and all subpackages.
	 *
	 * @param imports
	 * @param p
	 */
	private static void gatherImports(ArrayList<Import> imports, Package p) {
		for (Import i : p.getImports()) {
			if (!i.isResolved()) {
				imports.add(i);
			}
		}

		for (Package pp : p.getSubpackges()) {
			gatherImports(imports, pp);
		}
	}
}


text:
<!DOCTYPE html>
<svg><g>foo</g><g>bar</g></svg>


text:
package org.apache.olingo.odata2.janos.processor.core.data.store;

import org.apache.olingo.odata2.janos.processor.api.data.store.DataStore;
import org.apache.olingo.odata2.janos.processor.api.data.store.DataStoreException;
import org.apache.olingo.odata2.janos.processor.api.data.store.DataStoreManager;

import javax.persistence.Entity;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
public class DualDataStoreManager implements DataStoreManager {

  private final Map<String, String> properties = new HashMap<>();

  private final Map<String, DataStore<Object>> dataStores = new HashMap<>();

  @Override
  public <T> DataStore<T> createDataStore(Class<T> clz) throws DataStoreException {
    return createDataStore(clz, properties);
  }

  @Override
  public <T> DataStore<T> createDataStore(Class<T> clz, Map<String, String> properties) throws DataStoreException {
    boolean keepPersistent = Boolean.parseBoolean(properties.get(KEEP_PERSISTENT));
    return createInstance(clz, keepPersistent);
  }

  @Override
  public <T> DataStore<T> grantDataStore(String name, Class<T> clz) throws DataStoreException {
    return grantDataStore(name, clz, properties);
  }

  @Override
  public <T> DataStore<T> grantDataStore(String name, Class<T> clz, Map<String, String> properties) throws DataStoreException {
    DataStore<T> ds = getDataStore(name, clz);
    if(ds == null) {
      ds = createDataStore(clz);
      dataStores.put(name, (DataStore<Object>) ds);
    }
    return ds;
  }

  @Override
  public DataStore<Object> getDataStore(String name) {
    return dataStores.get(name);
  }

  @Override
  public <T> DataStore<T> getDataStore(String name, Class<T> clz) throws DataStoreException {
    DataStore<?> ds = getDataStore(name);
    if(ds != null && clz != ds.getDataTypeClass()) {
      throw new DataStoreException("Unable to cast required class.");
    }
    return (DataStore<T>) ds;
  }

  @Override
  public void setDefaultProperty(String name, String value) {
    properties.put(name, value);
  }

  public <T> DataStore<T>  createInstance(Class<T> clz, boolean keepPersistent) throws DataStoreException {
    if(isJpaAnnotated(clz)) {
      String persistenceName = System.getProperty(JpaAnnotationDataStore.PERSISTENCE_NAME);
      if(persistenceName == null) {
        return JpaAnnotationDataStore.createInstance(clz);
      }
      return JpaAnnotationDataStore.createInstance(clz, persistenceName);
    }
    return InMemoryDataStore.createInMemory(clz, keepPersistent);
  }

  private boolean isJpaAnnotated(Class<?> clz) {
    return clz.getAnnotation(Entity.class) != null;
  }
}


text:
using Core.Common.MVVM;
using System;
using System.Threading;
using System.Threading.Tasks;
using Core.Common;

namespace Core.Common.Wpf
{
    public static class ViewHandleExtensions
    {

        private const string ViewIdentifer = "UNIQ_VIEW_STR";
        public static void SetViewHandle(this CommandExecutionContext context, ViewHandle handle)
        {
            context.Data[ViewIdentifer] = handle;
        }
        public static ViewHandle ViewHandle(this CommandExecutionContext context)
        {
            if (context == null)
            {
                return null;
            }
            return context.Data.GetOrDefault(ViewIdentifer) as ViewHandle;
        }
        public static void OnViewClose(this CommandExecutionContext context, Action action)
        {
            var vh = context.ViewHandle();
            if (vh == null)
            {
                throw new InvalidOperationException();
            }
            TaskScheduler syncContext;
            if (SynchronizationContext.Current != null)
            {
                syncContext = TaskScheduler.FromCurrentSynchronizationContext();
            }
            else
            {
                syncContext = TaskScheduler.Current;
            }
            vh.ViewTask.ContinueWith(t =>
            {
                action();
            }, syncContext);
        }
    }

}


text:
/**
 * Created by sixsides on 27/7/17.
 */

/**
 * Initialize for each element with the "input-x" class the corresponding element.
 *
 * Includes:
 * 1) "input-bv-datepicker": calendar with datepicker element
 * 2) "input-bv-font": only adds font glyphicon > for text elements
 * 3) "input-bv-lock": only adds lock glyphicon >  for password elements
 * 4) "input-bv-phone": only adds phone glyphicon
 * 5) "input-bv-usd": adds usd glyphicon and currency validation/format
 * 6) "input-bv-number": adds number glyphicon and number validation/format
 * 7) "input-bv-picture": only adds picture glyphicon >  for picture elements
 * 8) "input-bv-envelope": only adds envelope glyphicon >  for mail elements
 */
function createFormFields(){
    createDatepickerFormField();
    createFormField('font');
    createFormField('lock');
    createFormField('phone');
    createFormField('usd', true, false, true);
    createFormField('number', false, true);
    createFormField('picture');
    createFormField('envelope');
}

/**
 * Initialize for each element with the "input-bv-datepicker" class the corresponding element.
 */
function createDatepickerFormField(){

    var input = $(".input-bv-datepicker");
    if(input){
        // Adds a surrounding div for appending the glyphicon calendar object
        input.wrap("

");

        // Appends the glyphicon calendar
        $(".surround-bv-datepicker").append('

');

        input.datepicker({
            autoclose: true,
            todayHighlight: true,
            format: 'dd/mm/yyyy',
        });
    }

    var input18 = $(".input-bv-18datepicker");
    if(input18){
        // Adds a surrounding div for appending the glyphicon calendar object
        input18.wrap("

");

        // Appends the glyphicon calendar
        $(".surround-bv-18datepicker").append('

');

        input18.datepicker({
            autoclose: true,
            todayHighlight: true,
            format: 'dd/mm/yyyy',
            viewMode: "years",
            endDate: '-18y'
        });
    }
}

/**
 * Initialize for each element with the "input-bv-"+field class the corresponding element.
 * @param field the field class to search for
 * @param prepend boolean in order to define if the image should be prepended instead of appended
 * @param isNumber boolean in order to add the numeric validation and automatic edition on error
 * @param isCurrency boolean in order to add the numeric validation and automatic format edition on focusout
 */
function createFormField(field, prepend, isNumber, isCurrency){

    var input = $(".input-bv-"+field);
    if(input){
        // Adds a surrounding div for appending the glyphicon calendar object
        input.wrap('

');

        if(prepend){
            // Prepends the glyphicon icon
            $(".surround-bv-"+field).prepend('

');
        }else{
            if(isNumber){
                // Appends the % icon without glyphicon
                $(".surround-bv-"+field).append('
#
');
            }else{
                // Appends the glyphicon icon
                $(".surround-bv-"+field).append('

');
            }
        }

        if(isNumber) {
            //Number formatter
            input.numeric({decimalPlaces: 0});
            input.on('keyup', function () {
                $(this).val(numeral($(this).val()).format('0,0'));
            });
        }

        if(isCurrency){
            //Currency formatter
            input.numeric({ decimalPlaces : 2 });
            input.focusout(function () {
                $(this).val(numeral($(this).val()).format('0,0'));
            });
        }
    }
}


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 com.google.devtools.j2objc.ast;

import com.google.devtools.j2objc.types.Types;

import org.eclipse.jdt.core.dom.ITypeBinding;

/**
 * Node type for string literals.
 */
public class StringLiteral extends Expression {

  private String literalValue = null;
  private final ITypeBinding typeBinding;

  public StringLiteral(org.eclipse.jdt.core.dom.StringLiteral jdtNode) {
    super(jdtNode);
    literalValue = jdtNode.getLiteralValue();
    typeBinding = jdtNode.resolveTypeBinding();
  }

  public StringLiteral(StringLiteral other) {
    super(other);
    literalValue = other.getLiteralValue();
    typeBinding = other.getTypeBinding();
  }

  public StringLiteral(String literalValue, Types typeEnv) {
    this.literalValue = literalValue;
    typeBinding = typeEnv.resolveJavaType("java.lang.String");
  }

  @Override
  public Kind getKind() {
    return Kind.STRING_LITERAL;
  }

  @Override
  public ITypeBinding getTypeBinding() {
    return typeBinding;
  }

  public String getLiteralValue() {
    return literalValue;
  }

  @Override
  protected void acceptInner(TreeVisitor visitor) {
    visitor.visit(this);
    visitor.endVisit(this);
  }

  @Override
  public StringLiteral copy() {
    return new StringLiteral(this);
  }
}


text:
package com.caflores.sales_manager.dao.implementation;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.caflores.sales_manager.dao.CustomerDao;
import com.caflores.sales_manager.model.Customer;

@Repository("customerDao")
public class CustomerDaoImpl implements CustomerDao{

	@Autowired
	JdbcTemplate jdbcTemplate;

	public Customer findCustomer(long customerId) {
		Customer customer = null;
		String query = "SELECT id, name, dni "
				+ "FROM t_customers "
				+ "WHERE id = ?";
		customer = jdbcTemplate.queryForObject(query, new Object[]{customerId}, new CustomerMapper());
		return customer;
	}

	private static final class CustomerMapper implements RowMapper<Customer> {
		public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
			Customer customer = new Customer();
			customer.setId(rs.getLong("id"));
			customer.setName(rs.getString("name"));
			customer.setDni(rs.getString("dni"));
			return customer;
		}
	}

}


text:
from keras.datasets import imdb
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM, Conv1D, Flatten, Dropout
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence

def convolutional_nn():
    """
    https://medium.com/@thoszymkowiak/how-to-implement-sentiment-analysis-using-word-embedding-and-convolutional-neural-networks-on-keras-163197aef623
    """
    embedding_vector_length = 300
    model = Sequential()
    model.add(Embedding(top_words, embedding_vector_length, input_length=max_review_length))
    model.add(Conv1D(64, 3, padding='same'))
    model.add(Conv1D(32, 3, padding='same'))
    model.add(Conv1D(16, 3, padding='same'))
    model.add(Flatten())
    model.add(Dropout(0.2))
    model.add(Dense(180, activation='sigmoid'))
    model.add(Dropout(0.2))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

def lstm():
    """
    http://www.volodenkov.com/post/keras-lstm-sentiment-p2/
    """
    timesteps = 350
    dimensions = 300
    model = Sequential()
    model.add(LSTM(200,  input_shape=(timesteps, dimensions),  return_sequences=False))
    model.add(Dropout(0.2))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss="binary_crossentropy", optimizer='rmsprop', metrics=['accuracy'])
    return model

# Using keras to load the dataset with the top_words
top_words = 10000
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words)

# Pad the sequence to the same length
max_review_length = 1600
X_train = sequence.pad_sequences(X_train, maxlen=max_review_length)
X_test = sequence.pad_sequences(X_test, maxlen=max_review_length)
# print(X_train)
# print(y_train)

model = convolutional_nn()

model.fit(X_train, y_train, epochs=3, batch_size=64)

# Evaluation on the test set
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

# model = lstm()
# model.fit(X_train, y_train, epochs=20, batch_size=64)
# scores = model.evaluate(X_test, y_test, verbose=0)
# print("Accuracy: %.2f%%" % (scores[1]*100))


text:
package org.jdeferred2.impl;

import org.jdeferred2.Promise;

/***
 * @author Ray Tsang
 * @author Andres Almiray
 */
class MasterDeferredObject5<V1, V2, V3, V4, V5> extends AbstractMasterDeferredObject {
	MasterDeferredObject5(Promise<V1, ?, ?> promiseV1,
	                      Promise<V2, ?, ?> promiseV2,
	                      Promise<V3, ?, ?> promiseV3,
	                      Promise<V4, ?, ?> promiseV4,
	                      Promise<V5, ?, ?> promiseV5) {
		super(new MutableMultipleResults5<V1, V2, V3, V4, V5>());
		configurePromise(0, promiseV1);
		configurePromise(1, promiseV2);
		configurePromise(2, promiseV3);
		configurePromise(3, promiseV4);
		configurePromise(4, promiseV5);
	}
}


text:
/*
 * First Visit Js jQuery Plugin version 0.1.2
 * Roman Pushkin - roman.pushkin@gmail.com
 */
;(function($){

	'use strict';

	$.fn.firstVisit = function(options) {

		if (!window.localStorage) {
			console.warn('localStorage is not defined, add Modernizr referece: https://github.com/Modernizr/Modernizr');
			return;
		}

		var VISIT_KEY_NAME = 'first_visit_key';
		var visitKey = false;
		var $elements = $(this);

		var settings = {
			classToAdd: '',
			currentPathOnly: false,
			currentPathStartsWith: ''
		};

		$.extend(settings, options);

		if(settings.currentPathOnly && settings.currentPathStartsWith)
		{
			if(window.location.pathname.indexOf(settings.currentPathStartsWith) != 0)
			{
				console.warn('Incorrect usage of currentPathStartsWith.');
				return;
			}
		}

		var getVisitKeyName = function() {
			return settings.currentPathOnly ?
				VISIT_KEY_NAME + '_' +
				(settings.currentPathStartsWith ? settings.currentPathStartsWith : window.location.pathname) + '_'
				: VISIT_KEY_NAME;
		}

		var setVisitKey = function() {
			var date = new Date();
			window.localStorage.setItem(getVisitKeyName(), date);
		}

		var getVisitKey = function() {
			return window.localStorage.getItem(getVisitKeyName());
		}

		// get last visit variable
		if(!visitKey) {
			visitKey = getVisitKey();
		}

		if(!visitKey) {

			setVisitKey();

			// show
			$elements.show();

			// add class if any
			if(settings.classToAdd) { $elements.addClass(settings.classToAdd); }
		}
	}
})(jQuery);


text:
//
//  SZUploadTool.h
//  OTIS_PJ
//
//  Created by sunze on 16/6/24.
//  Copyright © 2016年 sunzeboy. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SZUploadMaintenancemRequest.h"

@interface SZUploadTool : NSObject

/**
 *  维保上传
 */
+(void)uploadMaintenanceSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure done:(void(^)(NSString *))done;

/**
 *  维保照片上传
 */
+(void)uploadMaintenancePicSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure done:(void(^)(NSString *))done;

/**
 * 维修换件报告上传
 */
+(void)uploadFixSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure done:(void(^)(NSString *))done;

/**
 * 批量中断上传
 */
//+(void)uploadReportInBatchesSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure;

/**
 * 上传签字数据
 */
+(void)uploadSignatureSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure done:(void(^)(NSString *))done;

/**
 * 上传年检记录
 */
+(void)uploadYearlyCheckSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure done:(void(^)(NSString *))done;

/**
 * 上传全工时数据
 */
+(void)uploadFullLaborHoursSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure;

/**
 * 上传日志
 */
+(void)uploadLogSuccess:(void(^)(NSString *))success failure:(void(^)(NSError *error))failure;

@end


text:
describe('jsts.operation.buffer.BufferOp', function() {
  var reader = new jsts.io.WKTReader(), errorMargin=0.01;

  it('can be constructed', function() {
    var bufferOp = new jsts.operation.buffer.BufferOp();
    expect(bufferOp).toBeDefined();
  });

  it('Round buffer around point has area r^2 * PI', function() {
    var point = reader.read('POLYGON ((0 0))');
    var highResQuadrantSegments = 18;
    var bufferedGeom = point.buffer(1.0, highResQuadrantSegments);

	expect(bufferedGeom.getArea()).toBeCloseTo(Math.PI, errorMargin)
  });

  // we simulate Square buffers by ROUND_CAP style with quadrantSegments: 1, and distance * sqrt(2)
  it('Square buffer around point has area 2d * 2d', function() {
    var pointPolygon = reader.read('POLYGON ((0 0))');
    var distance = 1;
    var quadrantSegments = 1;
    var newArea = 2*2;
    var bufferedGeom = pointPolygon.buffer(distance * Math.sqrt(2), quadrantSegments);

	expect(bufferedGeom.getArea()).toBeCloseTo(newArea, errorMargin);
  });

  it('We should shrink by a factor with the inverse square', function() {
    var polygon = reader.read('POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))');
	var expectedWKT = "POLYGON((1 1,1 4,4 4,4 1,1 1))";
    var expectedGeom = reader.read(expectedWKT);
	var expectedArea = 9;

	var bufferedGeom = polygon.buffer(-1);

    expect(expectedGeom.equals(bufferedGeom)).toBeTruthy();
    expect(bufferedGeom.getArea()).toBe(expectedArea);
  });

  /* Shape has a very long, very thin part sticking out. We want to remove it with a negative buffer
   *
   *  /-\ (100,0.001)
   *  | |
   *  . .
   *  . .
   *  | |
   *  | ----- (5,5)
   *  |     |
   *  |     |
   *  |     |
   *  |     |
   *  ------- (5,0)
   * (0,0)
   */
  it('We should drop points with the inverse square', function() {
  	var polygon = reader.read('POLYGON ((0 0, 5 0, 100 0, 100 0.00001, 5 0.00001, 5 5, 0 5, 0 0))');
  	var currentArea = 25;
  	var currentLength = 100+95+5+5+5;
  	var currentPoints = 7+1
    expect(polygon.getArea()).toBeCloseTo(currentArea, errorMargin);
    expect(polygon.getLength()).toBeCloseTo(currentLength);
    expect(polygon.getExteriorRing().getNumPoints()).toBe(currentPoints);

	var newGeom = polygon.buffer(-0.001);
	var expectedArea = currentArea;
	var expectedLength = 5+5+5+5;
	var expectedPoints = 4+1;
    expect(newGeom.getExteriorRing().getNumPoints()).toBe(expectedPoints);
    expect(newGeom.getArea()).toBeCloseTo(expectedArea, errorMargin);
    expect(newGeom.getLength()).toBeCloseTo(expectedLength, errorMargin);
  });

  it('Buffer around block, size should be 2d * 2d', function() {
    var polygon = reader.read('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))');
    expect(polygon.getArea()).toBe(5*5);

	var bufferedGeom = polygon.buffer(1,18);
	var roundCornersLossArea = 4 - Math.PI; // 4 corners fill a full circle, so lost area is 4-Pi
	var expectedArea = 7*7 - roundCornersLossArea;
    expect(bufferedGeom.getArea()).toBeCloseTo(expectedArea, errorMargin);
  });
});


text:
var util = require('util'),
    extendWithGettersAndSetters = require('../util/extendWithGettersAndSetters'),
    Relation = require('./Relation'),
    HtmlRelation = require('./HtmlRelation');

function HtmlCacheManifest(config) {
    HtmlRelation.call(this, config);
}

util.inherits(HtmlCacheManifest, HtmlRelation);

extendWithGettersAndSetters(HtmlCacheManifest.prototype, {
    get href() {
        return this.node.getAttribute('manifest') || undefined;
    },

    set href(href) {
        this.node.setAttribute('manifest', href);
    },

    attach: function (asset, position, adjacentRelation) {
        this.node = asset.parseTree.documentElement; // Always uses <html manifest='...'>
        return HtmlRelation.prototype.attach.call(this, asset, position, adjacentRelation);
    },

    detach: function () {
        this.node.removeAttribute('manifest');
        delete this.node;
        return Relation.prototype.detach.call(this);
    }
});

module.exports = HtmlCacheManifest;