import {GenderTable} from "../database/genders"; export interface Pronouns { id: string defaultGenderMarker: GenderMarker name: string displayOrder: number usePlural: boolean subjective: string adjective: string possessive: string reflexive: string objective: string } export interface GenderMarker { emoji: string defaultGenderName: string displayOrder: number defaultPronouns: Pronouns|null } export class GenderManager { private cachedPronouns: {[key: string]: Pronouns} = {} private cachedGenderMarkers: {[key: string]: GenderMarker} = {} private cachedPronounList: Pronouns[] = [] private cachedMarkerList: GenderMarker[] = [] private refreshPromise: Promise|null = null private readonly _table: GenderTable constructor({genders}: { genders: GenderTable }) { this._table = genders } async refreshCache(): Promise { if (this.refreshPromise !== null) { await this.refreshPromise return } this.refreshPromise = (async () => { const {pronouns, markers} = await this._table.getPronounsAndMarkers() const pronounSet = new Set() const markerSet = new Set() this.cachedPronounList = [] this.cachedMarkerList = [] for (const pronounData of pronouns) { const pronoun: Pronouns = this.cachedPronouns[pronounData.id] ?? {} pronoun.id = pronounData.id pronoun.name = pronounData.name pronoun.displayOrder = pronounData.display_order pronoun.subjective = pronounData.subjective pronoun.adjective = pronounData.adjective pronoun.possessive = pronounData.possessive pronoun.reflexive = pronounData.reflexive pronoun.objective = pronounData.objective this.cachedPronouns[pronoun.id] = pronoun pronounSet.add(pronoun.id) this.cachedPronounList.push(pronoun) } for (const key of Object.keys(this.cachedPronouns)) { if (!pronounSet.has(key)) { delete this.cachedPronouns[key] } } for (const markerData of markers) { const marker: GenderMarker = this.cachedGenderMarkers[markerData.emoji] ?? {} marker.emoji = markerData.emoji marker.displayOrder = markerData.display_order marker.defaultGenderName = markerData.default_name this.cachedGenderMarkers[marker.emoji] = marker markerSet.add(marker.emoji) this.cachedMarkerList.push(marker) } for (const key of Object.keys(this.cachedGenderMarkers)) { if (!markerSet.has(key)) { delete this.cachedGenderMarkers[key] } } this.cachedPronounList.sort((a, b) => a.displayOrder - b.displayOrder) this.cachedMarkerList.sort((a, b) => a.displayOrder - b.displayOrder) for (const pronounData of pronouns) { if (!Object.hasOwn(this.cachedPronouns, pronounData.id) || !Object.hasOwn(this.cachedGenderMarkers, pronounData.default_marker)) { throw Error("invalid marker: can't find " + pronounData.id + " and " + pronounData.default_marker) } this.cachedPronouns[pronounData.id].defaultGenderMarker = this.cachedGenderMarkers[pronounData.default_marker] } for (const markerData of markers) { this.cachedGenderMarkers[markerData.emoji].defaultPronouns = this.cachedPronounList.find((p) => p.defaultGenderMarker.emoji === markerData.emoji) ?? null } })() try { await this.refreshPromise } finally { this.refreshPromise = null } } async getPronouns(): Promise { if (this.refreshPromise !== null) { await this.refreshPromise } return this.cachedPronounList } async getPronounsById(id: string): Promise { if (this.refreshPromise !== null) { await this.refreshPromise } const result = this.cachedPronouns[id] ?? null if (result === null) { throw Error("No battle type found with id: " + id) } return result } async getPronounsByName(name: string): Promise { if (this.refreshPromise !== null) { await this.refreshPromise } const result = this.cachedPronounList.find(t => t.name === name) ?? null if (result === null) { throw Error("No pronouns found with name: " + name) } return result } async getGenderMarkers(): Promise { if (this.refreshPromise !== null) { await this.refreshPromise } return this.cachedMarkerList } async getGenderMarkerByEmoji(emoji: string): Promise { if (this.refreshPromise !== null) { await this.refreshPromise } const result = this.cachedGenderMarkers[emoji] ?? null if (result === null) { throw Error("No marker found with emoji: " + emoji) } return result } async getDefaultGenderMarkerForGender(gender: string): Promise { if (this.refreshPromise !== null) { await this.refreshPromise } const result = this.cachedMarkerList.find(t => t.defaultGenderName === gender) ?? this.cachedMarkerList[0] ?? null if (result === null) { throw Error("No markers found") } return result } }