map rules object on results run

This commit is contained in:
Sorrel Bri 2020-02-13 13:56:19 -08:00
parent 98864740ca
commit 1e15578aec
2 changed files with 121 additions and 17 deletions

View file

@ -1,11 +1,22 @@
// @flow // @flow
import type { stateType } from './stateReducer'; import type { stateType, epochType, phoneType } from './stateReducer';
export type resultsAction = { export type resultsAction = {
type: 'RUN' type: 'RUN'
} }
const findFeatures = (phones: {}, lexeme:string): [] => { export type decomposedRulesType = [
{
environment: {
pre: [{[key: string]: boolean}],
position: [{[key: string]: boolean}],
post: [{[key: string]: boolean}]
},
newFeatures: [{[key: string]: boolean}]
}
]
const findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {
let featureBundle = [] let featureBundle = []
let lastIndex = lexeme.length - 1; let lastIndex = lexeme.length - 1;
let node = {}; let node = {};
@ -23,12 +34,80 @@ const findFeatures = (phones: {}, lexeme:string): [] => {
}) })
return featureBundle; return featureBundle;
} }
const findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {
let featureBundle = []
let lastIndex = lexeme.length - 1;
let node = {};
[...lexeme].forEach((graph, index) => {
if (!index && !lastIndex) featureBundle.push(phones[graph].features)
if (!index) return node = phones[graph]
if (index === lastIndex) return node[graph]
? featureBundle.push(node[graph])
: featureBundle.push(node, phones[graph])
if (!node[graph] && node.features) {
featureBundle.push(node)
return node = phones[graph]
}
if (!node[graph])
return node = node[graph]
})
return featureBundle;
}
const decomposeRule = (rule: string): string[] => { const decomposeRule = (rule: string) => {
let decomposedChange = rule.split('>'); let decomposedChange = rule.split('>');
decomposedChange = [decomposedChange[0], ...decomposedChange[1].split('/')] decomposedChange = [decomposedChange[0], ...decomposedChange[1].split('/')]
decomposedChange = [decomposedChange[0], decomposedChange[1], ...decomposedChange[2].split('_')]; decomposedChange = [decomposedChange[0], decomposedChange[1], ...decomposedChange[2].split('_')];
return [...decomposedChange]; const ruleBundle = {
environment: {
pre: decomposedChange[2],
position: decomposedChange[0],
post: decomposedChange[3]
},
newFeatures: decomposedChange[1]
}
return ruleBundle;
}
const mapStringToFeatures = (ruleString, phones) => {
if (ruleString) {
const ruleBrackets = ruleString.match(/\[.*\]/)
if (ruleBrackets) {
const ruleFeatures = ruleString.match(/(?!\[).*(?<!\])/)[0]
const plusIndex = ruleFeatures.indexOf('+');
const minusIndex = ruleFeatures.indexOf('-');
const positiveFeatures = ruleFeatures.slice(plusIndex + 1, minusIndex).trim().split(' ');
const positiveFeaturesMap = positiveFeatures.map(feature => ({[feature]: true}))
const negativeFeatures = ruleFeatures.slice(minusIndex +1).trim().split(' ');
const negativeFeaturesMap = negativeFeatures.map(feature => ({[feature]: false}))
return {...positiveFeaturesMap, ...negativeFeaturesMap}
}
const grapheme = ruleString;
return findFeaturesFromGrapheme(phones, grapheme);
}
return {};
}
const mapRuleBundleToFeatureBundle = (ruleBundle, phones) => {
// ! for each object in ruleBundle, map values to array of objects with feature-boolean key-value pairs
const featureBundle = {...ruleBundle};
console.log(featureBundle)
featureBundle.environment.pre = mapStringToFeatures(featureBundle.environment.pre, phones);
console.log(featureBundle.environment.pre)
featureBundle.environment.position = mapStringToFeatures(featureBundle.environment.position, phones);
console.log(featureBundle.environment.position)
featureBundle.environment.post = mapStringToFeatures(featureBundle.environment.post, phones);
console.log(featureBundle.environment.post)
featureBundle.newFeatures = mapStringToFeatures(featureBundle.newFeatures, phones);
console.log(featureBundle.newFeatures)
return featureBundle;
}
export const decomposeRules = (epoch: epochType, phones: {[key: string]: phoneType}): decomposedRulesType => {
let ruleBundle = [...epoch.changes]
ruleBundle = epoch.changes.map(rule => decomposeRule(rule));
const featureBundle = ruleBundle.map(rule => mapRuleBundleToFeatureBundle(rule, phones));
return featureBundle;
} }
export const run = (state: stateType, action: resultsAction): stateType => { export const run = (state: stateType, action: resultsAction): stateType => {
@ -43,7 +122,7 @@ export const run = (state: stateType, action: resultsAction): stateType => {
}) })
}) })
let featurePhoneBundle = state.lexicon.map(lexeme => findFeatures(state.phones, lexeme)) let featurePhoneBundle = state.lexicon.map(lexeme => findFeaturesFromLexeme(state.phones, lexeme))
console.log(featurePhoneBundle) console.log(featurePhoneBundle)
ruleBundle.forEach(rule => { ruleBundle.forEach(rule => {

View file

@ -1,5 +1,6 @@
import {stateReducer} from './stateReducer'; import { stateReducer } from './stateReducer';
import {initState} from './stateReducer.init'; import { initState } from './stateReducer.init';
import { decomposeRules } from './stateReducer.results';
describe('Results', () => { describe('Results', () => {
let state = {}; let state = {};
@ -12,15 +13,39 @@ describe('Results', () => {
expect(stateReducer(state, action)).toBe(state); expect(stateReducer(state, action)).toBe(state);
}); });
it('results returned from first sound change rule', () => { it('rules decomposed properly', () => {
const action = {type: 'RUN'}; const epoch = initState().epochs[0];
state = initState(0) epoch.changes = epoch.changes.slice(0,1)
expect(stateReducer(state, action).results).toEqual({ const phones = initState().phones;
pass: 'epoch 1', const result = [
results: [ {
'anna', 'anat', 'anət', 'anna', 'tan', 'ənna' // ! '[+ occlusive - nasal]>[+ occlusive nasal]/n_',
] environment: {
}) pre: [
}); {
sonorant: true, nasal: true, occlusive: true, coronal: true
}
],
position: [
{occlusive: true, nasal: false}
],
post: [],
},
newFeatures: {occlusive: true, nasal: true}
}
];
expect(decomposeRules(epoch, phones)).toBe(result);
})
// it('results returned from first sound change rule', () => {
// const action = {type: 'RUN'};
// state = initState(0)
// expect(stateReducer(state, action).results).toEqual({
// pass: 'epoch 1',
// results: [
// 'anna', 'anat', 'anət', 'anna', 'tan', 'ənna'
// ]
// })
// });
}); });