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.
168 lines
5.8 KiB
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
|
|
}
|
|
} |