zenno/lib: legacy and affinity stuff
This commit is contained in:
35
zenno/src/lib/data/affinity.ts
Normal file
35
zenno/src/lib/data/affinity.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import globalJSON from '../../../../global/affinity.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Precomputed character pair and trio affinity.
|
||||||
|
*/
|
||||||
|
export interface Affinity {
|
||||||
|
/**
|
||||||
|
* First character in the relation.
|
||||||
|
*/
|
||||||
|
chara_a: number;
|
||||||
|
/**
|
||||||
|
* Second character in the relation.
|
||||||
|
* chara_a < chara_b is an invariant.
|
||||||
|
*/
|
||||||
|
chara_b: number;
|
||||||
|
/**
|
||||||
|
* Third character in the relation, if it is a trio relation.
|
||||||
|
* If defined, chara_b < chara_c is an invariant.
|
||||||
|
*/
|
||||||
|
chara_c?: number;
|
||||||
|
/**
|
||||||
|
* Total base compatibility between characters in the relation.
|
||||||
|
*/
|
||||||
|
affinity: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const affinity = {
|
||||||
|
global: globalJSON as Affinity[],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export function lookup(aff: Affinity[], chara_a: number, chara_b: number, chara_c?: number): number {
|
||||||
|
const [a, b, c] = [chara_a, chara_b, chara_c ?? Infinity].sort((a, b) => a - b);
|
||||||
|
const r = aff.find((v) => v.chara_a === a && v.chara_b === b && (v.chara_c ?? Infinity) === c);
|
||||||
|
return r?.affinity ?? 0;
|
||||||
|
}
|
||||||
75
zenno/src/lib/data/uma.ts
Normal file
75
zenno/src/lib/data/uma.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import globalJSON from '../../../../global/uma.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uma or character card definitions.
|
||||||
|
*/
|
||||||
|
export interface Uma {
|
||||||
|
/**
|
||||||
|
* Uma ID.
|
||||||
|
*/
|
||||||
|
chara_card_id: number;
|
||||||
|
/**
|
||||||
|
* Character ID that the Uma is a variant of.
|
||||||
|
*/
|
||||||
|
chara_id: number;
|
||||||
|
/**
|
||||||
|
* Regional name of the Uma, comprised of the variant name and the character name.
|
||||||
|
* E.g. "[Special Dreamer] Special Week".
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Regional variant name.
|
||||||
|
* E.g. "[Special Dreamer]".
|
||||||
|
*/
|
||||||
|
variant: string;
|
||||||
|
|
||||||
|
sprint: AptitudeLevel;
|
||||||
|
mile: AptitudeLevel;
|
||||||
|
medium: AptitudeLevel;
|
||||||
|
long: AptitudeLevel;
|
||||||
|
front: AptitudeLevel;
|
||||||
|
pace: AptitudeLevel;
|
||||||
|
late: AptitudeLevel;
|
||||||
|
end: AptitudeLevel;
|
||||||
|
turf: AptitudeLevel;
|
||||||
|
dirt: AptitudeLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the Uma's unique skill.
|
||||||
|
*/
|
||||||
|
unique: number;
|
||||||
|
/**
|
||||||
|
* ID of the Uma's first built-in skill.
|
||||||
|
*/
|
||||||
|
skill1: number;
|
||||||
|
/**
|
||||||
|
* ID of the Uma's second built-in skill.
|
||||||
|
*/
|
||||||
|
skill2: number;
|
||||||
|
/**
|
||||||
|
* ID of the Uma's third built-in skill.
|
||||||
|
*/
|
||||||
|
skill3: number;
|
||||||
|
/**
|
||||||
|
* ID of the skill unlocked at potential level 2.
|
||||||
|
*/
|
||||||
|
skill_pl2: number;
|
||||||
|
/**
|
||||||
|
* ID of the skill unlocked at potential level 3.
|
||||||
|
*/
|
||||||
|
skill_pl3: number;
|
||||||
|
/**
|
||||||
|
* ID of the skill unlocked at potential level 4.
|
||||||
|
*/
|
||||||
|
skill_pl4: number;
|
||||||
|
/**
|
||||||
|
* ID of the skill unlocked at potential level 5.
|
||||||
|
*/
|
||||||
|
skill_pl5: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AptitudeLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
||||||
|
|
||||||
|
export const uma = {
|
||||||
|
global: globalJSON as Uma[],
|
||||||
|
};
|
||||||
72
zenno/src/lib/legacy.ts
Normal file
72
zenno/src/lib/legacy.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { affinity, lookup } from './data/affinity';
|
||||||
|
import { uma, type Uma } from './data/uma';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A legacy, or parents and grandparents.
|
||||||
|
* Defined as an applicative over generic types to reduce the API surface.
|
||||||
|
* @see mapLegacy
|
||||||
|
*/
|
||||||
|
export interface Legacy<T> {
|
||||||
|
p1: T;
|
||||||
|
s11: T;
|
||||||
|
s12: T;
|
||||||
|
p2: T;
|
||||||
|
s21: T;
|
||||||
|
s22: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applicative fmap for legacies.
|
||||||
|
* @param l Input legacy
|
||||||
|
* @param f Mapping function
|
||||||
|
* @returns Transformed legacy
|
||||||
|
*/
|
||||||
|
export function mapLegacy<U, V>(l: Legacy<U>, f: (u: U) => V): Legacy<V> {
|
||||||
|
return {
|
||||||
|
p1: f(l.p1),
|
||||||
|
s11: f(l.s11),
|
||||||
|
s12: f(l.s12),
|
||||||
|
p2: f(l.p2),
|
||||||
|
s21: f(l.s21),
|
||||||
|
s22: f(l.s22),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A veteran, or the result of a completed career.
|
||||||
|
*/
|
||||||
|
export interface Veteran {
|
||||||
|
uma: number;
|
||||||
|
sparks: number[];
|
||||||
|
saddles: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function findUma(umas: Uma[], u: number): Uma | null {
|
||||||
|
return umas.find((v) => v.chara_card_id === u) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute individual affinities for a legacy using the global region ruleset.
|
||||||
|
* @param trainee Uma (not character) ID of the trainee Uma
|
||||||
|
* @param legacy Legacy veterans
|
||||||
|
* @returns Individual affinities
|
||||||
|
*/
|
||||||
|
export function globalAffinity(trainee: number, legacy: Legacy<Veteran>): Legacy<number> {
|
||||||
|
const t = findUma(uma.global, trainee)?.chara_id ?? 0;
|
||||||
|
const charas = mapLegacy(legacy, (u) => findUma(uma.global, u.uma)?.chara_id ?? 0);
|
||||||
|
const saddles = mapLegacy(legacy, (u) => new Set(u.saddles));
|
||||||
|
const aff = affinity.global;
|
||||||
|
const pp = lookup(aff, charas.p1, charas.p2);
|
||||||
|
const s11 = lookup(aff, t, charas.p1, charas.s11) + saddles.p1.intersection(saddles.s11).size;
|
||||||
|
const s12 = lookup(aff, t, charas.p1, charas.s12) + saddles.p1.intersection(saddles.s12).size;
|
||||||
|
const s21 = lookup(aff, t, charas.p2, charas.s21) + saddles.p2.intersection(saddles.s21).size;
|
||||||
|
const s22 = lookup(aff, t, charas.p2, charas.s22) + saddles.p2.intersection(saddles.s22).size;
|
||||||
|
return {
|
||||||
|
p1: lookup(aff, t, charas.p1) + pp + s11 + s12,
|
||||||
|
s11,
|
||||||
|
s12,
|
||||||
|
p2: lookup(aff, t, charas.p2) + pp + s21 + s22,
|
||||||
|
s21,
|
||||||
|
s22,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user