<commit_before>// utility for a field definition object

import {AGGREGATE_OP_INDEX, AggregateOp, isCountingAggregateOp} from './aggregate';
import {Axis} from './axis';
import {autoMaxBins, Bin, binToString} from './bin';
import {Channel, rangeType} from './channel';
import {CompositeAggregate} from './compositemark';
import {Config} from './config';
import {Field} from './fielddef';
import {Legend} from './legend';
import * as log from './log';
import {LogicalOperand} from './logical';
import {Scale, ScaleType} from './scale';
import {SortField, SortOrder} from './sort';
import {StackOffset} from './stack';
import {isDiscreteByDefault, TimeUnit} from './timeunit';
import {getFullName, Type} from './type';
import {isBoolean, isString, stringValue} from './util';


/**
 * Definition object for a constant value of an encoding channel.
 */
export interface ValueDef<T> {
  /**
   * A constant value in visual domain.
   */
  value: T;
}

/**
 * Generic type for conditional channelDef.
 * F defines the underlying FieldDef type while V defines the underlying ValueDef type.
 */
export type Conditional<F extends FieldDef<any>, V extends ValueDef<any>> = ConditionalFieldDef<F, V> | ConditionalValueDef<F, V> | ConditionOnlyDef<F, V>;


export type Condition<T> = {
  selection: LogicalOperand<string>;
} & T;

/**
 * A FieldDef with Condition<ValueDef>
 * {
 *   condition: {value: ...},
 *   field: ...,
 *   ...
 * }
 */
export type ConditionalFieldDef<F extends FieldDef<any>, V extends ValueDef<any>> = F & {condition?: Condition<V>};

export interface ConditionOnlyDef <F extends FieldDef<any>, V extends ValueDef<any>> {
  condition: Condition<F> | Condition<V>;
}


/**
 * A ValueDef with Condition<ValueDef | FieldDef>
 * {
 *   condition: {field: ...} | {value: ...},
 *   value: ...,
 * }
 */
export type ConditionalValueDef<F extends FieldDef<any>, V extends ValueDef<any>> = V & {condition?: Condition<F> | Condition<V>;};

/**
 * Reference to a repeated value.
 */
export type RepeatRef = {
  repeat: 'row' | 'column'
};

export type Field = string | RepeatRef;

export function isRepeatRef(field: Field): field is RepeatRef {
  return field && !isString(field) && 'repeat' in field;
}

export interface FieldDefBase<F> {

  /**
   * __Required.__ Name of the field from which to pull a data value.
   *
   * __Note:__ `field` is not required if `aggregate` is `count`.
   */
  field?: F;

  // function

  /**
   * Time unit for a `temporal` field  (e.g., `year`, `yearmonth`, `month`, `hour`).
   *
   * __Default value:__ `undefined` (None)
   *
   */
  timeUnit?: TimeUnit;

  /**
   * Flag for binning a `quantitative` field, or a bin property object
   * for binning parameters.
   */
  bin?: boolean | Bin;

  /**
   * Aggregation function for the field
   * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
   *
   * __Default value:__ `undefined` (None)
   *
   */
  aggregate?: AggregateOp | CompositeAggregate;
}

/**
 *  Definition object for a data field, its type and transformation of an encoding channel.
 */
export interface FieldDef<F> extends FieldDefBase<F> {
  /**
   * The encoded field's type of measurement. This can be either a full type
   * name (`"quantitative"`, `"temporal"`, `"ordinal"`,  and `"nominal"`)
   * or an initial character of the type name (`"Q"`, `"T"`, `"O"`, `"N"`).
   * This property is case-insensitive.
   */
  type: Type;
}

export interface ScaleFieldDef<F> extends FieldDef<F> {
  scale?: Scale;
  /**
   * Sort order for a field with discrete domain.
   * This can be `"ascending"`, `"descending"`, `null`, or a [sort field definition object](sort.html#sort-field) for sorting by an aggregate calculation of a specified sort field.
   *
   * __Note:__ For fields with continuous domain, please use `"scale": {"reverse": true}` to flip the scale instead.
   */
  sort?: SortField | SortOrder;
}

export interface PositionFieldDef<F> extends ScaleFieldDef<F> {
  /**
   * By default, Vega-Lite automatically creates axes for `x` and `y` channels when they are encoded.
   * If `axis` is not defined, default axis properties are applied.
   * User can provide set `axis` to an object to customize [axis properties](axis.html#axis-properties)
   * or set `axis` to `null` to remove the axis.
   * @nullable
   */
  axis?: Axis;

  /**
   * Type of stacking offset if the field should be stacked.
   * "none" or null, if the field should not be stacked.
   */
  stack?: StackOffset;
}

export interface LegendFieldDef<F> extends ScaleFieldDef<F> {
   /**
    * @nullable
    */
  legend?: Legend;
}

// Detail

// Order Path have no scale

export interface OrderFieldDef<F> extends FieldDef<F> {
  sort?: SortOrder;
}

export interface TextFieldDef<F> extends FieldDef<F> {
  // FIXME: add more reference to Vega's format pattern or d3's format pattern.
  /**
   * The formatting pattern for text value. If not defined, this will be determined automatically.
   */
  format?: string;
}

export type ChannelDef<F> = Conditional<FieldDef<F>, ValueDef<any>>;

export function isConditionalDef<F>(channelDef: ChannelDef<F>): channelDef is Conditional<FieldDef<F>, ValueDef<any>> {
  return !!channelDef && !!channelDef.condition;
}

/**
 * Return if a channelDef is a ConditionalValueDef with ConditionFieldDef
 */
export function hasConditionFieldDef<F>(channelDef: ChannelDef<F>): channelDef is (ValueDef<any> & {condition: FieldDef<F>}) {
  return !!channelDef && !!channelDef.condition && isFieldDef(channelDef.condition);
}

export function isFieldDef<F>(channelDef: ChannelDef<F>): channelDef is FieldDef<F> | PositionFieldDef<F> | LegendFieldDef<F> | OrderFieldDef<F> | TextFieldDef<F> {
  return !!channelDef && (!!channelDef['field'] || channelDef['aggregate'] === 'count');
}

export function isValueDef<F>(channelDef: ChannelDef<F>): channelDef is ValueDef<any> {
  return channelDef && 'value' in channelDef && channelDef['value'] !== undefined;
}<commit_msg>Correct type in hasConditionFieldDef<commit_after>// utility for a field definition object

import {AGGREGATE_OP_INDEX, AggregateOp, isCountingAggregateOp} from './aggregate';
import {Axis} from './axis';
import {autoMaxBins, Bin, binToString} from './bin';
import {Channel, rangeType} from './channel';
import {CompositeAggregate} from './compositemark';
import {Config} from './config';
import {Field} from './fielddef';
import {Legend} from './legend';
import * as log from './log';
import {LogicalOperand} from './logical';
import {Scale, ScaleType} from './scale';
import {SortField, SortOrder} from './sort';
import {StackOffset} from './stack';
import {isDiscreteByDefault, TimeUnit} from './timeunit';
import {getFullName, Type} from './type';
import {isBoolean, isString, stringValue} from './util';


/**
 * Definition object for a constant value of an encoding channel.
 */
export interface ValueDef<T> {
  /**
   * A constant value in visual domain.
   */
  value: T;
}

/**
 * Generic type for conditional channelDef.
 * F defines the underlying FieldDef type while V defines the underlying ValueDef type.
 */
export type Conditional<F extends FieldDef<any>, V extends ValueDef<any>> = ConditionalFieldDef<F, V> | ConditionalValueDef<F, V> | ConditionOnlyDef<F, V>;


export type Condition<T> = {
  selection: LogicalOperand<string>;
} & T;

/**
 * A FieldDef with Condition<ValueDef>
 * {
 *   condition: {value: ...},
 *   field: ...,
 *   ...
 * }
 */
export type ConditionalFieldDef<F extends FieldDef<any>, V extends ValueDef<any>> = F & {condition?: Condition<V>};

export interface ConditionOnlyDef <F extends FieldDef<any>, V extends ValueDef<any>> {
  condition: Condition<F> | Condition<V>;
}


/**
 * A ValueDef with Condition<ValueDef | FieldDef>
 * {
 *   condition: {field: ...} | {value: ...},
 *   value: ...,
 * }
 */
export type ConditionalValueDef<F extends FieldDef<any>, V extends ValueDef<any>> = V & {condition?: Condition<F> | Condition<V>;};

/**
 * Reference to a repeated value.
 */
export type RepeatRef = {
  repeat: 'row' | 'column'
};

export type Field = string | RepeatRef;

export function isRepeatRef(field: Field): field is RepeatRef {
  return field && !isString(field) && 'repeat' in field;
}

export interface FieldDefBase<F> {

  /**
   * __Required.__ Name of the field from which to pull a data value.
   *
   * __Note:__ `field` is not required if `aggregate` is `count`.
   */
  field?: F;

  // function

  /**
   * Time unit for a `temporal` field  (e.g., `year`, `yearmonth`, `month`, `hour`).
   *
   * __Default value:__ `undefined` (None)
   *
   */
  timeUnit?: TimeUnit;

  /**
   * Flag for binning a `quantitative` field, or a bin property object
   * for binning parameters.
   */
  bin?: boolean | Bin;

  /**
   * Aggregation function for the field
   * (e.g., `mean`, `sum`, `median`, `min`, `max`, `count`).
   *
   * __Default value:__ `undefined` (None)
   *
   */
  aggregate?: AggregateOp | CompositeAggregate;
}

/**
 *  Definition object for a data field, its type and transformation of an encoding channel.
 */
export interface FieldDef<F> extends FieldDefBase<F> {
  /**
   * The encoded field's type of measurement. This can be either a full type
   * name (`"quantitative"`, `"temporal"`, `"ordinal"`,  and `"nominal"`)
   * or an initial character of the type name (`"Q"`, `"T"`, `"O"`, `"N"`).
   * This property is case-insensitive.
   */
  type: Type;
}

export interface ScaleFieldDef<F> extends FieldDef<F> {
  scale?: Scale;
  /**
   * Sort order for a field with discrete domain.
   * This can be `"ascending"`, `"descending"`, `null`, or a [sort field definition object](sort.html#sort-field) for sorting by an aggregate calculation of a specified sort field.
   *
   * __Note:__ For fields with continuous domain, please use `"scale": {"reverse": true}` to flip the scale instead.
   */
  sort?: SortField | SortOrder;
}

export interface PositionFieldDef<F> extends ScaleFieldDef<F> {
  /**
   * By default, Vega-Lite automatically creates axes for `x` and `y` channels when they are encoded.
   * If `axis` is not defined, default axis properties are applied.
   * User can provide set `axis` to an object to customize [axis properties](axis.html#axis-properties)
   * or set `axis` to `null` to remove the axis.
   * @nullable
   */
  axis?: Axis;

  /**
   * Type of stacking offset if the field should be stacked.
   * "none" or null, if the field should not be stacked.
   */
  stack?: StackOffset;
}

export interface LegendFieldDef<F> extends ScaleFieldDef<F> {
   /**
    * @nullable
    */
  legend?: Legend;
}

// Detail

// Order Path have no scale

export interface OrderFieldDef<F> extends FieldDef<F> {
  sort?: SortOrder;
}

export interface TextFieldDef<F> extends FieldDef<F> {
  // FIXME: add more reference to Vega's format pattern or d3's format pattern.
  /**
   * The formatting pattern for text value. If not defined, this will be determined automatically.
   */
  format?: string;
}

export type ChannelDef<F> = Conditional<FieldDef<F>, ValueDef<any>>;

export function isConditionalDef<F>(channelDef: ChannelDef<F>): channelDef is Conditional<FieldDef<F>, ValueDef<any>> {
  return !!channelDef && !!channelDef.condition;
}

/**
 * Return if a channelDef is a ConditionalValueDef with ConditionFieldDef
 */
export function hasConditionFieldDef<F>(channelDef: ChannelDef<F>): channelDef is (ValueDef<any> & {condition: Condition<FieldDef<F>>}) {
  return !!channelDef && !!channelDef.condition && isFieldDef(channelDef.condition);
}

export function isFieldDef<F>(channelDef: ChannelDef<F>): channelDef is FieldDef<F> | PositionFieldDef<F> | LegendFieldDef<F> | OrderFieldDef<F> | TextFieldDef<F> {
  return !!channelDef && (!!channelDef['field'] || channelDef['aggregate'] === 'count');
}

export function isValueDef<F>(channelDef: ChannelDef<F>): channelDef is ValueDef<any> {
  return channelDef && 'value' in channelDef && channelDef['value'] !== undefined;
}
{'fraction_non_alphanumeric': 0.14304880093912462, 'fraction_numerical': 0.0001677008217340265, 'mean_word_length': 4.0197811447811445, 'pattern_counts': {'":': 4, '<': 126, '<?xml version=': 0, '>': 126, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4892352', 'n_tokens_mistral': 3716, 'n_tokens_neox': 3651, 'n_words': 1229}