(de)(pronouns) use a data model to define the structure of the grammar table

This commit is contained in:
Valentyne Stigloher 2024-03-17 00:09:15 +01:00
parent 45d3457933
commit 1fdd2cfa6b

View File

@ -4,97 +4,190 @@
<Icon v="spell-check" />
<T>pronouns.grammarTable</T><T>quotation.colon</T>
</h2>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th></th>
<th v-if="comprehensive"></th>
<th>Nominativ</th>
<th v-if="comprehensive">
Genitiv
<th v-if="grammarTable.rowHeaderCount" :colspan="grammarTable.rowHeaderCount"></th>
<th v-for="name in grammarTable.columnHeader" :key="name">
<Spelling :text="name" />
</th>
<th v-else>
Possessivartikel
</th>
<th>Dativ</th>
<th>Akkusativ</th>
</tr>
</thead>
<tbody>
<tr>
<th v-if="comprehensive">
Personalpronomen
</th>
<th v-else>
Pronomen
</th>
<td v-if="comprehensive"></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="pronoun_n" :counter="counter" /></td>
<td v-if="comprehensive">
<MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="pronoun_g" :counter="counter" />
</td>
<td v-else>
<MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_m_n" :counter="counter" />
</td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="pronoun_d" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="pronoun_a" :counter="counter" /></td>
</tr>
<tr v-if="comprehensive">
<th class="border-bottom-0">
Possessivartikel
</th>
<th>Femininum</th>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_f_n" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_f_g" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_f_d" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_f_a" :counter="counter" /></td>
</tr>
<tr v-if="comprehensive">
<th class="border-bottom-0"></th>
<th>Maskulinum</th>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_m_n" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_m_g" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_m_d" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_m_a" :counter="counter" /></td>
</tr>
<tr v-if="comprehensive">
<th></th>
<th>Neutrum</th>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_n_n" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_n_g" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_n_d" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive_n_a" :counter="counter" /></td>
</tr>
<tr v-if="comprehensive && selectedPronoun.getMorpheme('relative_n', counter)">
<th>Relativpronomen</th>
<td></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="relative_n" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="relative_g" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="relative_d" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="relative_a" :counter="counter" /></td>
</tr>
<tr v-if="comprehensive && selectedPronoun.getMorpheme('demonstrative_n', counter)">
<th>Demonstrativpronomen</th>
<td></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="demonstrative_n" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="demonstrative_g" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="demonstrative_d" :counter="counter" /></td>
<td><MorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="demonstrative_a" :counter="counter" /></td>
</tr>
<template v-for="section in grammarTable.sections">
<tr v-for="[i, variant] in section.variants.entries()" :key="`${section.name}-${variant.name}`">
<th v-if="i === 0 && grammarTable.rowHeaderCount >= 1" :rowspan="section.variants.length">
<Spelling :text="section.name" />
</th>
<th v-if="grammarTable.rowHeaderCount >= 2">
<Spelling :text="variant.name" />
</th>
<td v-for="morpheme in variant.morphemes" :key="morpheme">
<MorphemeWithPronunciation
:pronoun="selectedPronoun"
:morpheme="morpheme"
:counter="counter"
/>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</section>
</template>
<script>
export default {
props: {
selectedPronoun: { required: true },
comprehensive: { required: true },
counter: { required: true },
<script lang="ts">
import Vue from 'vue';
import type { PropType } from 'vue';
import type { Pronoun } from '../../../src/classes.ts';
const cases = ['n', 'g', 'd', 'a'];
const genders = [
{
name: 'Femininum',
abbreviation: 'f',
},
{
name: 'Maskulinum',
abbreviation: 'm',
},
{
name: 'Neutrum',
abbreviation: 'n',
},
];
interface GrammarTableDefinition {
columnHeader: string[];
sections: SectionDefinition[];
}
interface SectionDefinition {
name?: string;
morphemes: string[] | { base: string, type: string };
}
const grammarTableDefinitions: Record<'simple' | 'comprehensive', GrammarTableDefinition> = {
simple: {
columnHeader: ['Nominativ', 'Possessivartikel', 'Dativ', 'Akkusativ'],
sections: [
{
morphemes: ['pronoun_n', 'possessive_m_n', 'pronoun_d', 'pronoun_a'],
},
],
},
comprehensive: {
columnHeader: ['Nominativ', 'Genitiv', 'Dativ', 'Akkusativ'],
sections: [
{
name: 'Personalpronomen',
morphemes: {
base: 'pronoun',
type: 'case',
},
},
{
name: 'Possessivartikel',
morphemes: {
base: 'possessive',
type: 'gender-with-case',
},
},
{
name: 'Relativpronomen',
morphemes: {
base: 'relative',
type: 'case',
},
},
{
name: 'Demonstrativpronomen',
morphemes: {
base: 'demonstrative',
type: 'case',
},
},
],
},
};
const morphemesByCase = (morphemeBase: string): string[] => {
return cases.map((caseAbbreviation) => `${morphemeBase}_${caseAbbreviation}`);
};
interface GrammarTable {
columnHeader: string[];
rowHeaderCount: number;
sections: Section[];
}
interface Section {
name?: string;
variants: PronounVariant[];
}
interface PronounVariant {
name?: string;
morphemes: string[];
}
const expandMorphemesForSection = (sectionMorphemes: SectionDefinition['morphemes']): PronounVariant[] => {
if (Array.isArray(sectionMorphemes)) {
return [{ morphemes: sectionMorphemes }];
} else {
const morphemeBase = sectionMorphemes.base;
switch (sectionMorphemes.type) {
case 'case':
return [{ morphemes: morphemesByCase(morphemeBase) }];
case 'gender-with-case':
return genders.map((gender) => ({
name: gender.name,
morphemes: morphemesByCase(`${morphemeBase}_${gender.abbreviation}`),
}));
default:
throw new Error(`variant type ${sectionMorphemes.type} is unknown`);
}
}
};
const buildVariantsForSection = (
sectionMorphemes: SectionDefinition['morphemes'],
pronoun: Pronoun,
counter: number,
): PronounVariant[] => {
return expandMorphemesForSection(sectionMorphemes).filter((variant) => {
return variant.morphemes.some((morpheme) => pronoun.getMorpheme(morpheme, counter) !== null);
});
};
export default Vue.extend({
props: {
selectedPronoun: { required: true, type: Object as PropType<Pronoun> },
comprehensive: { required: true, type: Boolean },
counter: { required: true, type: Number },
},
computed: {
grammarTable(): GrammarTable {
const grammarTableDefinition = grammarTableDefinitions[this.comprehensive ? 'comprehensive' : 'simple'];
const sections = grammarTableDefinition.sections.map((section) => {
const variants = buildVariantsForSection(section.morphemes, this.selectedPronoun, this.counter);
return { name: section.name, variants };
}).filter((section) => {
return section.variants.length > 0;
});
const rowHeaderCount = Math.max(...sections.map((section) => {
if (!section.name) {
return 0;
} else if (!section.variants.some((variant) => variant.name)) {
return 1;
} else {
return 2;
}
}));
return { columnHeader: grammarTableDefinition.columnHeader, sections, rowHeaderCount };
},
},
});
</script>