You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
vore-rpg/src/managers/genders.ts

168 lines
5.8 KiB

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<void>|null = null
private readonly _table: GenderTable
constructor({genders}: { genders: GenderTable }) {
this._table = genders
}
async refreshCache(): Promise<void> {
if (this.refreshPromise !== null) {
await this.refreshPromise
return
}
this.refreshPromise = (async () => {
const {pronouns, markers} = await this._table.getPronounsAndMarkers()
const pronounSet = new Set<string>()
const markerSet = new Set<string>()
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<Pronouns[]> {
if (this.refreshPromise !== null) {
await this.refreshPromise
}
return this.cachedPronounList
}
async getPronounsById(id: string): Promise<Pronouns> {
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<Pronouns> {
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<GenderMarker[]> {
if (this.refreshPromise !== null) {
await this.refreshPromise
}
return this.cachedMarkerList
}
async getGenderMarkerByEmoji(emoji: string): Promise<GenderMarker> {
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<GenderMarker> {
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
}
}