diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/language.test.ts | 70 | ||||
-rw-r--r-- | src/language.ts | 99 |
2 files changed, 134 insertions, 35 deletions
diff --git a/src/language.test.ts b/src/language.test.ts index d3c6f23..62b03a2 100644 --- a/src/language.test.ts +++ b/src/language.test.ts @@ -69,3 +69,73 @@ test('fail to output impossible consonants', () => { voice: false, })).toBe(''); }); + + +test('all consonants can be selected', () => { + expect(lang.pickConsonants( + [ lang.ConsonantPlace.Bilabial ], + [ lang.ConsonantManner.Nasal ], + [ true, true ], + )).toEqual([ + { + place: lang.ConsonantPlace.Bilabial, + manner: lang.ConsonantManner.Nasal, + voice: false, + }, + { + place: lang.ConsonantPlace.Bilabial, + manner: lang.ConsonantManner.Nasal, + voice: true, + }, + ]); + + expect(lang.pickConsonants( + [ lang.ConsonantPlace.Labiodental ], + [ + lang.ConsonantManner.Nasal, + lang.ConsonantManner.Plosive, + lang.ConsonantManner.SibilantAffricate, + lang.ConsonantManner.NonSibilantAffricate, + lang.ConsonantManner.SibilantFricative, + lang.ConsonantManner.NonSibilantFricative, + lang.ConsonantManner.Approximant, + lang.ConsonantManner.Tap, + lang.ConsonantManner.Trill, + lang.ConsonantManner.LateralAffricate, + lang.ConsonantManner.LateralFricative, + lang.ConsonantManner.LateralApproximant, + lang.ConsonantManner.LateralTap, + ], + [ true, false ], + )).toEqual([ + { + place: lang.ConsonantPlace.Labiodental, + manner: lang.ConsonantManner.Nasal, + voice: false, + }, + { + place: lang.ConsonantPlace.Labiodental, + manner: lang.ConsonantManner.Plosive, + voice: false, + }, + { + place: lang.ConsonantPlace.Labiodental, + manner: lang.ConsonantManner.NonSibilantAffricate, + voice: false, + }, + { + place: lang.ConsonantPlace.Labiodental, + manner: lang.ConsonantManner.NonSibilantFricative, + voice: false, + }, + ]); + + + expect(lang.pickConsonants( + [ lang.ConsonantPlace.Bilabial, lang.ConsonantPlace.Alveolar ], + [ lang.ConsonantManner.Plosive, lang.ConsonantManner.Tap ], + [ true, true ], + ).map(lang.consonantFeaturesToIpa)).toEqual([ + 'p', 'b', 'ⱱ̟', 't', 'd', 'ɾ̥', 'ɾ', + ]); +}); diff --git a/src/language.ts b/src/language.ts index 0721e09..c0360b8 100644 --- a/src/language.ts +++ b/src/language.ts @@ -1,16 +1,16 @@ export enum VowelHeight { - Open, - NearOpen, - OpenMid, - Mid, - CloseMid, - NearClose, - Close, + Open = 'open', + NearOpen = 'nearOpen', + OpenMid = 'openMid', + Mid = 'mid', + CloseMid = 'closeMid', + NearClose = 'nearClose', + Close = 'close', } export enum VowelDepth { - Front, - Central, - Back, + Front = 'front', + Central = 'central', + Back = 'back', } export interface VowelFeatures { height: VowelHeight; @@ -106,33 +106,33 @@ export function vowelFeaturesToIpa(features: VowelFeatures): string { export enum ConsonantPlace { - Bilabial, - Labiodental, - Linguolabial, - Dental, - Alveolar, - Postalveolar, - Retroflex, - Palatal, - Velar, - Uvular, - Pharyngeal, - Glottal, + Bilabial = 'bilabial', + Labiodental = 'labiodental', + Linguolabial = 'labiolingual', + Dental = 'dental', + Alveolar = 'alveolar', + Postalveolar = 'postalveolar', + Retroflex = 'retroflex', + Palatal = 'palatal', + Velar = 'velar', + Uvular = 'uvular', + Pharyngeal = 'pharyngeal', + Glottal = 'glottal', } export enum ConsonantManner { - Nasal, - Plosive, - SibilantAffricate, - NonSibilantAffricate, - SibilantFricative, - NonSibilantFricative, - Approximant, - Tap, - Trill, - LateralAffricate, - LateralFricative, - LateralApproximant, - LateralTap, + Nasal = 'nasal', + Plosive = 'plosive', + SibilantAffricate = 'sibilantAffricate', + NonSibilantAffricate = 'nonSibilantAffricate', + SibilantFricative = 'sibilantFricative', + NonSibilantFricative = 'nonSibilantFricative', + Approximant = 'approximant', + Tap = 'tap', + Trill = 'trill', + LateralAffricate = 'lateralAffricate', + LateralFricative = 'lateralFricative', + LateralApproximant = 'lateralApproximant', + LateralTap = 'lateralTap', } export interface ConsonantFeatures { place: ConsonantPlace; @@ -480,3 +480,32 @@ export function consonantFeaturesToIpa(features: ConsonantFeatures): string { } } } + + +export function isConsonantPossible(features: ConsonantFeatures): boolean { + return consonantFeaturesToIpa(features) !== ''; +} + + +// get all of the consonants based on the features selected +export function pickConsonants( + places: ConsonantPlace[], + manners: ConsonantManner[], + voicing: [boolean, boolean], +): ConsonantFeatures[] { + return places.map<ConsonantFeatures[]>( + place => manners.map<ConsonantFeatures[]>( + manner => { + const [ unvoiced, voiced ] = voicing; + const result = []; + if (unvoiced) { + result.push({ place, manner, voice: false }); + } + if (voiced) { + result.push({ place, manner, voice: true }); + } + return result; + } + ).flat() + ).flat().filter(isConsonantPossible); +} |