@cruncheevos/core
Version:
Parse and generate achievements and leaderboards for RetroAchievements.org
375 lines (374 loc) • 13.2 kB
TypeScript
import { Condition } from './condition.js';
type ConditionBuilderInput = Array<boolean | Condition.Input | ConditionBuilder>;
type DefineFunction = ((...args: ConditionBuilderInput) => ConditionBuilder) & {
/**
* Same as calling `new Condition()`
*
* Can be useful if you need to reuse the condition but have it slightly different
*
* @example
* import { define as $ } from '@cruncheevos/core'
*
* const isNTSC = $.one(['', 'Mem', '24bit', 0x9e1e, '=', 'Value', '', 0x373030])
* const notNTSC = isNTSC.with({ cmp: '!=' })
*/
one: (arg: Condition.Input) => Condition;
/**
* Allows to generate conditions for comparing strings
*
* The string is split into numeric chunks, little endian, up to 32bit,
* which are provided to the supplied callback. The final result is also
* wrapped with `andNext`
*
* Internally, TextEncoder is used and the input is treated as UTF-8
*
* If you need to treat input as UTF-16, currently you need to convert it to UTF-16 yourself
*
* @example
* import { define as $ } from '@cruncheevos/core'
*
* $.str(
* 'abcde',
* (size, value) => $(
* ['AddAddress', 'Mem', '32bit', 0xcafe],
* ['AddAddress', 'Mem', '32bit', 0xfeed],
* ['', 'Mem', size, 0xabcd, '=', ...value],
* )
* )
* // "I:0xXcafe_I:0xXfeed_N:0xXabcd=1684234849_I:0xXcafe_I:0xXfeed_0xHabcd=101"
* // abcd = 0x64636261 = 1684234849
* // e = 0x65 = 101
*/
str: (input: string, callback: (s: Condition.Size, v: ['Value', '', number]) => ConditionBuilder) => ConditionBuilder;
};
/**
* Function providing versatile way to define conditions,
* returns instance of ConditionBuilder class
*
* @example
* import { define as $ } from '@cruncheevos/core'
* let someParameter = false
*
* $(
* ['', 'Mem', '32bit', 0xCAFE, '=', 'Value', '', 1],
* '0=2'
* ).trigger(
* '0=3',
* // condition below will not be included because
* // the expression evaluated to falsy value
* someParameter && '0=4',
* ).toString() // 0xXcafe=1_0=2_T:0=3
*/
export declare const define: DefineFunction;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with Trigger flag
*
* @example
* import { trigger } from '@cruncheevos/core'
* trigger('0=1', '0=2').toString() // T:0=1_T:0=2
*/
export declare const trigger: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with ResetIf flag
*
* @example
* import { resetIf } from '@cruncheevos/core'
* resetIf('0=1', '0=2').toString() // R:0=1_R:0=2
*/
export declare const resetIf: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with PauseIf flag
*
* @example
* import { pauseIf } from '@cruncheevos/core'
* pauseIf('0=1', '0=2').toString() // P:0=1_P:0=2
*/
export declare const pauseIf: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with AddHits flag
*
* @example
* import { addHits } from '@cruncheevos/core'
* addHits('0=1', '0=2').toString() // C:0=1_C:0=2
*/
export declare const addHits: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with SubHits flag
*
* @example
* import { subHits } from '@cruncheevos/core'
* subHits('0=1', '0=2').toString() // D:0=1_D:0=2
*/
export declare const subHits: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with Measured flag
*
* @example
* import { measured } from '@cruncheevos/core'
* measured('0=1', '0=2').toString() // M:0=1_M:0=2
*/
export declare const measured: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with Measured% flag
*
* RAIntegration converts Measured flags to Measured% if *Track as %* checkbox is ticked
*
* @example
* import { measuredPercent } from '@cruncheevos/core'
* measuredPercent('0=1', '0=2').toString() // G:0=1_G:0=2
*/
export declare const measuredPercent: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with MeasuredIf flag
*
* @example
* import { measuredIf } from '@cruncheevos/core'
* measuredIf('0=1', '0=2').toString() // Q:0=1_Q:0=2
*/
export declare const measuredIf: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with ResetNextIf flag
*
* @example
* import { resetNextIf } from '@cruncheevos/core'
* resetNextIf('0=1', '0=2').toString() // Z:0=1_Z:0=2
*/
export declare const resetNextIf: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with AndNext flag
*
* The final condition will not have AndNext flag applied
* unless it's followed by a chained method call, otherwise
* codition will not work correctly that way
*
* @example
* import { andNext } from '@cruncheevos/core'
* andNext('0=1', '0=2').toString() // N:0=1_0=2
* andNext('0=1', '0=2').also('0=3').toString() // N:0=1_N:0=2_0=3
*/
export declare const andNext: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but starts the condition chain
* by wrapping the passed conditions with OrNext flag
*
* The final condition will not have OrNext flag applied
* unless it's followed by a chained method call, otherwise
* codition will not work correctly that way
*
* @example
* import { orNext } from '@cruncheevos/core'
* orNext('0=1', '0=2').toString() // O:0=1_0=2
* orNext('0=1', '0=2').also('0=3').toString() // O:0=1_O:0=2_0=3
*/
export declare const orNext: (...args: ConditionBuilderInput) => ConditionBuilder;
/**
* Same as {@link define}, but sets 1 hit to the final
* condition that was passed to the function
*
* @example
* $('0=1').once(
* andNext('0=2', '0=3')
* ).toString() // 0=1_N:0=2_0=3.1.
*/
export declare const once: (...args: ConditionBuilderInput) => ConditionBuilder;
export declare class ConditionBuilder {
/**
* Holds the conditions that were previously added
* by calling the {@link define} function and class methods
* @readonly
*/
conditions: Condition[];
constructor();
/**
* Adds conditions wrapped with Trigger flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').trigger('0=2', '0=3').toString() // 0=1_T:0=2_T:0=3
*/
trigger(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with ResetIf flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').resetIf('0=2', '0=3').toString() // 0=1_R:0=2_R:0=3
*/
resetIf(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with PauseIf flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').pauseIf('0=2', '0=3').toString() // 0=1_P:0=2_P:0=3
*/
pauseIf(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with AddHits flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').addHits('0=2', '0=3').toString() // 0=1_C:0=2_C:0=3
*/
addHits(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with SubHits flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').subHits('0=2', '0=3').toString() // 0=1_D:0=2_D:0=3
*/
subHits(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with Measured flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').measured('0=2', '0=3').toString() // 0=1_M:0=2_M:0=3
*/
measured(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with Measured% flag to the chain
*
* RAIntegration converts Measured flags to Measured% if *Track as %* checkbox is ticked
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').measuredPercent('0=2', '0=3').toString() // 0=1_G:0=2_G:0=3
*/
measuredPercent(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with Measured flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').measuredIf('0=2', '0=3').toString() // 0=1_Q:0=2_Q:0=3
*/
measuredIf(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with ResetNextIf flag to the chain
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').resetNextIf('0=2', '0=3').toString() // 0=1_Z:0=2_Z:0=3
*/
resetNextIf(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with AndNext flag to the chain
*
* The final condition in the chain will not have AndNext flag
* applied, because the condition will not work correctly that way
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').andNext('0=2', '0=3').toString() // 0=1_N:0=2_0=3
* $('0=1')
* .andNext('0=2', '0=3')
* .resetIf('0=4').toString() // 0=1_N:0=2_N:0=3_R:0=4
*/
andNext(...args: ConditionBuilderInput): this;
/**
* Adds conditions wrapped with OrNext flag to the chain
*
* The final condition in the chain will not have OrNext flag
* applied, because the condition will not work correctly that way
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1').orNext('0=2', '0=3').toString() // 0=1_O:0=2_0=3
* $('0=1')
* .orNext('0=2', '0=3')
* .resetIf('0=4').toString() // 0=1_O:0=2_O:0=3_R:0=4
*/
orNext(...args: ConditionBuilderInput): this;
/**
* Adds conditions to the chain as is
*
* @example
* import { define as $, resetIf } from '@cruncheevos/core'
* resetIf('0=1', '0=2')
* .also('0=3')
* .toString() // R:0=1_R:0=2_0=3
*/
also(...args: ConditionBuilderInput): this;
/**
* Adds conditions as is with final condition set to have 1 hit
*
* @example
* import { define as $ } from '@cruncheevos/core'
* $('0=1')
* .once(
* andNext('0=2', '0=3')
* ).toString() // 0=1_N:0=2_0=3.1.
*/
once(...args: ConditionBuilderInput): this;
[Symbol.iterator](): Generator<Condition, void, unknown>;
/**
* Returns new instance of ConditionBuilder with mapped conditions
*
* Accepts a callback function that acts similar to Array.prototype.map
*
* If any conditional condition was ignored, it will not appear in the callback
*
* @example
* $('0=1', false && '0=2', '0=3')
* .map((c, i) => c.with({ hits: i + 1 }))
* .toString() // 0=1.1._0=3.2.
*/
map(cb: (c: Condition, idx: number, array: Condition[]) => Condition): ConditionBuilder;
/**
* Returns new instance of ConditionBuilder with different
* values merged into last condition
*
* `lvalue` and `rvalue` can be specified as partial array, which can be less verbose
*
* Useful when combined with pointer chains
*
* @param {Condition.PartialMergedData} data Condition.PartialMergedData
*
* @example
* $(
* ['AddAddress', 'Mem', '32bit', 0xcafe],
* ['AddAddress', 'Mem', '32bit', 0xbeef],
* ['', 'Mem', '32bit', 0, '=', 'Value', '', 120],
* ).withLast({ cmp: '!=', rvalue: { value: 9 } })
* .toString() // I:0xXcafe_I:0xXbeef_0xX0!=9
*
* $(
* ['AddAddress', 'Mem', '32bit', 0xcafe],
* ['AddAddress', 'Mem', '32bit', 0xbeef],
* ['', 'Mem', '32bit', 0, '=', 'Value', '', 120],
* ).withLast({ cmp: '!=', rvalue: rvalue: ['Delta', '32bit', 0] })
* .toString() // I:0xXcafe_I:0xXbeef_0xX0!=d0xX0
*/
withLast(data: Condition.PartialMergedData): ConditionBuilder;
/**
* Returns a string with raw condition code
*
* @example
* $(
* ['AndNext', 'Mem', '32bit', 0xCAFE, '=', 'Value', '', 5],
* ['', 'Delta', '32bit', 0xCAFE, '=', 'Value', '', 4]
* ).toString() // N:0xXcafe=5_d0xXcafe=4
*/
toString(): string;
/**
* Same as {@link ConditionBuilder.prototype.toString toString()}
*
* @example
* JSON.stringify({ conditions: $('0=1', '0=2') })
* // {"conditions":"0=1_0=2"}
*/
toJSON(): string;
}
export {};