refactor state for features to contain references to phones
This commit is contained in:
parent
741af7f76e
commit
faec991cd0
3 changed files with 79 additions and 36 deletions
|
@ -1,13 +1,19 @@
|
||||||
import {stateReducer} from './stateReducer';
|
import {stateReducer} from './stateReducer';
|
||||||
|
|
||||||
describe('Features', () => {
|
describe('Features', () => {
|
||||||
const state = {
|
const state = {}
|
||||||
features: [
|
beforeEach(() => {
|
||||||
'low', 'high','back', 'rounded', 'sonorant',
|
state.phones = {
|
||||||
'nasal', 'obstruent', 'occlusive', 'plosive',
|
a: {features: {occlusive: true}, grapheme: 'a'},
|
||||||
'prenasalized', 'aspirated', 'coronal'
|
n: {features: {occlusive: false}, grapheme: 'n'}
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
state.features = {
|
||||||
|
occlusive: {
|
||||||
|
positive: [state.phones.n],
|
||||||
|
negative: [state.phones.a]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
it('features returned unaltered', () => {
|
it('features returned unaltered', () => {
|
||||||
const action = {type: ''};
|
const action = {type: ''};
|
||||||
|
@ -16,7 +22,13 @@ describe('Features', () => {
|
||||||
|
|
||||||
it('feature addition returns new feature list', () => {
|
it('feature addition returns new feature list', () => {
|
||||||
const action = {type: 'ADD_FEATURE', value: {feature: 'anterior'}};
|
const action = {type: 'ADD_FEATURE', value: {feature: 'anterior'}};
|
||||||
expect(stateReducer(state, action)).toEqual({...state, features:[...state.features, action.value.feature]})
|
expect(stateReducer(state, action)).toEqual(
|
||||||
})
|
{...state,
|
||||||
|
features:{...state.features,
|
||||||
|
anterior:{ positive:[], negative:[] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
|
@ -5,15 +5,24 @@ const initState = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const addPhones = (phones, phone) => {
|
const addPhones = (phones, phone) => {
|
||||||
let node = {}
|
let node = {};
|
||||||
phone.split('').forEach((graph, index) => {
|
phone.split('').forEach((graph, index) => {
|
||||||
if (index) node[graph] = {}
|
if (index) node[graph] = {}
|
||||||
if (!index && !phones[graph]) phones[graph] = {}
|
if (!index && !phones[graph]) phones[graph] = {}
|
||||||
node = index === 0 ? phones[graph] : node[graph];
|
node = index === 0 ? phones[graph] : node[graph];
|
||||||
|
if (index === phone.length - 1) node.grapheme = phone;
|
||||||
})
|
})
|
||||||
return phones;
|
return phones;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findPhone = (phones, phone) => {
|
||||||
|
let node;
|
||||||
|
phone.split('').forEach((graph, index) => {
|
||||||
|
node = index === 0 ? phones[graph] : node[graph];
|
||||||
|
});
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
const addFeatureToPhone = (phones, phone, featureKey, featureValue) => {
|
const addFeatureToPhone = (phones, phone, featureKey, featureValue) => {
|
||||||
let node = {}
|
let node = {}
|
||||||
phone.split('').forEach((graph, index) => {
|
phone.split('').forEach((graph, index) => {
|
||||||
|
@ -44,20 +53,38 @@ const stateReducer = (state, action) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'ADD_FEATURE': {
|
case 'ADD_FEATURE': {
|
||||||
let newFeature = action.value.feature;
|
|
||||||
let positivePhones = action.value.positivePhones || [];
|
let positivePhones = action.value.positivePhones || [];
|
||||||
let negativePhones = action.value.negativePhones || [];
|
let negativePhones = action.value.negativePhones || [];
|
||||||
|
let newFeatureName = action.value.feature;
|
||||||
|
|
||||||
let newPhoneObject = [
|
let newPhoneObject = [
|
||||||
...positivePhones, ...negativePhones
|
...positivePhones, ...negativePhones
|
||||||
].reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)
|
].reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)
|
||||||
if (positivePhones) positivePhones = positivePhones.reduce(
|
|
||||||
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeature, true)
|
if (positivePhones) {
|
||||||
, newPhoneObject);
|
|
||||||
if (negativePhones) negativePhones = negativePhones.reduce(
|
positivePhones.reduce(
|
||||||
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeature, false)
|
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, true)
|
||||||
, newPhoneObject);
|
, newPhoneObject
|
||||||
return {...state, features:[...state.features, newFeature], phones: newPhoneObject}
|
);
|
||||||
|
|
||||||
|
positivePhones = positivePhones.map( positivePhone => findPhone(newPhoneObject, positivePhone) )
|
||||||
|
// console.log(positivePhones)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negativePhones) {
|
||||||
|
|
||||||
|
negativePhones.reduce(
|
||||||
|
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, false)
|
||||||
|
, newPhoneObject
|
||||||
|
);
|
||||||
|
|
||||||
|
negativePhones = negativePhones.map( negativePhone => findPhone(newPhoneObject, negativePhone) )
|
||||||
|
// console.log(negativePhones)
|
||||||
|
}
|
||||||
|
|
||||||
|
let newFeature = {[action.value.feature]: {positive: positivePhones, negative: negativePhones}};
|
||||||
|
return {...state, features:{...state.features, ...newFeature}, phones: newPhoneObject}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import {stateReducer} from './stateReducer';
|
import {stateReducer} from './stateReducer';
|
||||||
|
|
||||||
describe('Phones', () => {
|
describe('Phones', () => {
|
||||||
const n_phone = {features: {nasal: true}}
|
const n_phone = {features: {nasal: true}, grapheme: 'n'};
|
||||||
const state = {
|
const state = {};
|
||||||
features: [
|
|
||||||
'nasal'
|
|
||||||
],
|
|
||||||
phones: { n: n_phone }
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(()=> {
|
beforeEach(()=> {
|
||||||
state.features = [ 'nasal' ];
|
|
||||||
state.phones= { n: n_phone };
|
state.phones= { n: n_phone };
|
||||||
|
state.features = {
|
||||||
|
nasal: {
|
||||||
|
positive: [state.phones.n],
|
||||||
|
negative: []
|
||||||
|
}
|
||||||
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
it('phones returned unaltered', () => {
|
it('phones returned unaltered', () => {
|
||||||
|
@ -23,7 +22,7 @@ describe('Phones', () => {
|
||||||
const action = {type: 'ADD_FEATURE', value: {feature: 'anterior', positivePhones: ['n']}};
|
const action = {type: 'ADD_FEATURE', value: {feature: 'anterior', positivePhones: ['n']}};
|
||||||
expect(stateReducer(state, action)).toEqual(
|
expect(stateReducer(state, action)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
features:[...state.features, action.value.feature],
|
features:{...state.features, anterior: { positive: [state.phones.n], negative: [] }},
|
||||||
phones:{...state.phones, n:{...state.phones.n, features: {...state.phones.n.features, anterior: true}}}
|
phones:{...state.phones, n:{...state.phones.n, features: {...state.phones.n.features, anterior: true}}}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -33,8 +32,8 @@ describe('Phones', () => {
|
||||||
const action = {type: 'ADD_FEATURE', value: {feature: 'sonorant', negativePhones: ['t']}};
|
const action = {type: 'ADD_FEATURE', value: {feature: 'sonorant', negativePhones: ['t']}};
|
||||||
expect(stateReducer(state, action)).toEqual(
|
expect(stateReducer(state, action)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
features:[...state.features, action.value.feature],
|
features:{...state.features, sonorant: { positive: [], negative: [state.phones.t] }},
|
||||||
phones:{...state.phones, t:{features:{sonorant: false}}}
|
phones:{...state.phones, t:{features:{sonorant: false}, grapheme: 't'}}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -43,9 +42,9 @@ describe('Phones', () => {
|
||||||
const action = {type: 'ADD_FEATURE', value: {feature: 'sonorant', positivePhones: ['n'], negativePhones: ['t']}};
|
const action = {type: 'ADD_FEATURE', value: {feature: 'sonorant', positivePhones: ['n'], negativePhones: ['t']}};
|
||||||
expect(stateReducer(state, action)).toEqual(
|
expect(stateReducer(state, action)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
features:[...state.features, action.value.feature],
|
features:{...state.features, sonorant: { positive: [state.phones.n], negative: [state.phones.t] }},
|
||||||
phones:{...state.phones,
|
phones:{...state.phones,
|
||||||
t:{features:{sonorant: false}},
|
t:{features:{sonorant: false}, grapheme: 't'},
|
||||||
n:{...state.phones.n, features: {...state.phones.n.features, sonorant: true}}
|
n:{...state.phones.n, features: {...state.phones.n.features, sonorant: true}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,11 +55,16 @@ describe('Phones', () => {
|
||||||
const action = {type: 'ADD_FEATURE', value: {feature: 'aspirated', positivePhones: ['ntʰ'], negativePhones: ['n','t']}};
|
const action = {type: 'ADD_FEATURE', value: {feature: 'aspirated', positivePhones: ['ntʰ'], negativePhones: ['n','t']}};
|
||||||
expect(stateReducer(state, action)).toEqual(
|
expect(stateReducer(state, action)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
features:[...state.features, action.value.feature],
|
features:{...state.features,
|
||||||
|
aspirated: {
|
||||||
|
positive: [state.phones.n.t.ʰ],
|
||||||
|
negative: [state.phones.n, state.phones.t]
|
||||||
|
}
|
||||||
|
},
|
||||||
phones:{...state.phones,
|
phones:{...state.phones,
|
||||||
t:{features:{aspirated: false}},
|
t:{features:{aspirated: false}, grapheme: 't'},
|
||||||
n:{...state.phones.n, features: {...state.phones.n.features, aspirated: false},
|
n:{...state.phones.n, features: {...state.phones.n.features, aspirated: false},
|
||||||
t: {ʰ:{features:{aspirated:true}}}
|
t: {ʰ:{features:{aspirated:true}, grapheme: 'ntʰ'}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue