refactor to break stateReducer into modules for each property of state
This commit is contained in:
parent
02426fb383
commit
c8f6b65302
12 changed files with 351 additions and 913 deletions
|
@ -1,675 +0,0 @@
|
||||||
|
|
||||||
{
|
|
||||||
"header": {
|
|
||||||
"reportVersion": 1,
|
|
||||||
"event": "Allocation failed - JavaScript heap out of memory",
|
|
||||||
"trigger": "FatalError",
|
|
||||||
"filename": "report.20191129.153032.5120.0.001.json",
|
|
||||||
"dumpEventTime": "2019-11-29T15:30:32Z",
|
|
||||||
"dumpEventTimeStamp": "1575070232386",
|
|
||||||
"processId": 5120,
|
|
||||||
"cwd": "/Users/sorrel/code/phono-change-applier",
|
|
||||||
"commandLine": [
|
|
||||||
"/usr/local/Cellar/node/12.6.0/bin/node",
|
|
||||||
"/Users/sorrel/code/phono-change-applier/node_modules/jest-worker/build/workers/processChild.js"
|
|
||||||
],
|
|
||||||
"nodejsVersion": "v12.6.0",
|
|
||||||
"wordSize": 64,
|
|
||||||
"arch": "x64",
|
|
||||||
"platform": "darwin",
|
|
||||||
"componentVersions": {
|
|
||||||
"node": "12.6.0",
|
|
||||||
"v8": "7.5.288.22-node.14",
|
|
||||||
"uv": "1.30.1",
|
|
||||||
"zlib": "1.2.11",
|
|
||||||
"brotli": "1.0.7",
|
|
||||||
"ares": "1.15.0",
|
|
||||||
"modules": "72",
|
|
||||||
"nghttp2": "1.38.0",
|
|
||||||
"napi": "4",
|
|
||||||
"llhttp": "1.1.4",
|
|
||||||
"http_parser": "2.8.0",
|
|
||||||
"openssl": "1.1.1c",
|
|
||||||
"cldr": "35.1",
|
|
||||||
"icu": "64.2",
|
|
||||||
"tz": "2019a",
|
|
||||||
"unicode": "12.1"
|
|
||||||
},
|
|
||||||
"release": {
|
|
||||||
"name": "node",
|
|
||||||
"headersUrl": "https://nodejs.org/download/release/v12.6.0/node-v12.6.0-headers.tar.gz",
|
|
||||||
"sourceUrl": "https://nodejs.org/download/release/v12.6.0/node-v12.6.0.tar.gz"
|
|
||||||
},
|
|
||||||
"osName": "Darwin",
|
|
||||||
"osRelease": "17.7.0",
|
|
||||||
"osVersion": "Darwin Kernel Version 17.7.0: Sun Jun 2 20:31:42 PDT 2019; root:xnu-4570.71.46~1/RELEASE_X86_64",
|
|
||||||
"osMachine": "x86_64",
|
|
||||||
"cpus": [
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"model": "Intel(R) Core(TM) i7-4750HQ CPU @ 2.00GHz",
|
|
||||||
"speed": 2000,
|
|
||||||
"user": 2044650,
|
|
||||||
"nice": 0,
|
|
||||||
"sys": 1337730,
|
|
||||||
"idle": 7706670,
|
|
||||||
"irq": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"host": "SBJ-comp.local"
|
|
||||||
},
|
|
||||||
"javascriptStack": {
|
|
||||||
"message": "No stack.",
|
|
||||||
"stack": [
|
|
||||||
"Unavailable."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nativeStack": [
|
|
||||||
{
|
|
||||||
"pc": "0x0000000100140f5b",
|
|
||||||
"symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, v8::Local<v8::String>) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x0000000100075aec",
|
|
||||||
"symbol": "node::OnFatalError(char const*, char const*) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x000000010016900d",
|
|
||||||
"symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x0000000100168faf",
|
|
||||||
"symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002c018b",
|
|
||||||
"symbol": "v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002c1004",
|
|
||||||
"symbol": "v8::internal::Heap::HasLowYoungGenerationAllocationRate() [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002bf345",
|
|
||||||
"symbol": "v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002bdcfa",
|
|
||||||
"symbol": "v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002c4d97",
|
|
||||||
"symbol": "v8::internal::Heap::AllocateRawWithLightRetry(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002c4de4",
|
|
||||||
"symbol": "v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001002a41e8",
|
|
||||||
"symbol": "v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x00000001004960a2",
|
|
||||||
"symbol": "v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pc": "0x000000010071bf59",
|
|
||||||
"symbol": "Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/usr/local/Cellar/node/12.6.0/bin/node]"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"javascriptHeap": {
|
|
||||||
"totalMemory": 2153086976,
|
|
||||||
"totalCommittedMemory": 2151679912,
|
|
||||||
"usedMemory": 2144297648,
|
|
||||||
"availableMemory": 48338248,
|
|
||||||
"memoryLimit": 2197815296,
|
|
||||||
"heapSpaces": {
|
|
||||||
"read_only_space": {
|
|
||||||
"memorySize": 262144,
|
|
||||||
"committedMemory": 32272,
|
|
||||||
"capacity": 261832,
|
|
||||||
"used": 31960,
|
|
||||||
"available": 229872
|
|
||||||
},
|
|
||||||
"new_space": {
|
|
||||||
"memorySize": 2097152,
|
|
||||||
"committedMemory": 1359664,
|
|
||||||
"capacity": 1047328,
|
|
||||||
"used": 374792,
|
|
||||||
"available": 672536
|
|
||||||
},
|
|
||||||
"old_space": {
|
|
||||||
"memorySize": 2127966208,
|
|
||||||
"committedMemory": 2127561520,
|
|
||||||
"capacity": 2123871224,
|
|
||||||
"used": 2122211032,
|
|
||||||
"available": 1660192
|
|
||||||
},
|
|
||||||
"code_space": {
|
|
||||||
"memorySize": 688128,
|
|
||||||
"committedMemory": 657536,
|
|
||||||
"capacity": 543776,
|
|
||||||
"used": 543776,
|
|
||||||
"available": 0
|
|
||||||
},
|
|
||||||
"map_space": {
|
|
||||||
"memorySize": 2625536,
|
|
||||||
"committedMemory": 2621112,
|
|
||||||
"capacity": 1757200,
|
|
||||||
"used": 1757200,
|
|
||||||
"available": 0
|
|
||||||
},
|
|
||||||
"large_object_space": {
|
|
||||||
"memorySize": 19398656,
|
|
||||||
"committedMemory": 19398656,
|
|
||||||
"capacity": 19375432,
|
|
||||||
"used": 19375432,
|
|
||||||
"available": 0
|
|
||||||
},
|
|
||||||
"code_large_object_space": {
|
|
||||||
"memorySize": 49152,
|
|
||||||
"committedMemory": 49152,
|
|
||||||
"capacity": 3456,
|
|
||||||
"used": 3456,
|
|
||||||
"available": 0
|
|
||||||
},
|
|
||||||
"new_large_object_space": {
|
|
||||||
"memorySize": 0,
|
|
||||||
"committedMemory": 0,
|
|
||||||
"capacity": 1047328,
|
|
||||||
"used": 0,
|
|
||||||
"available": 1047328
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"resourceUsage": {
|
|
||||||
"userCpuSeconds": 82.9667,
|
|
||||||
"kernelCpuSeconds": 5.36789,
|
|
||||||
"cpuConsumptionPercent": 200.76,
|
|
||||||
"maxRss": 2276429135872,
|
|
||||||
"pageFaults": {
|
|
||||||
"IORequired": 28,
|
|
||||||
"IONotRequired": 955033
|
|
||||||
},
|
|
||||||
"fsActivity": {
|
|
||||||
"reads": 0,
|
|
||||||
"writes": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libuv": [
|
|
||||||
],
|
|
||||||
"environmentVariables": {
|
|
||||||
"npm_config_save_dev": "",
|
|
||||||
"npm_config_legacy_bundling": "",
|
|
||||||
"npm_config_dry_run": "",
|
|
||||||
"npm_config_viewer": "man",
|
|
||||||
"npm_config_only": "",
|
|
||||||
"npm_config_commit_hooks": "true",
|
|
||||||
"npm_config_browser": "",
|
|
||||||
"npm_package_gitHead": "13e04ab20d0f19c2364c2effe91bdb03bb2f2e10",
|
|
||||||
"npm_config_also": "",
|
|
||||||
"npm_package_devDependencies_react_test_renderer": "^16.12.0",
|
|
||||||
"npm_config_sign_git_commit": "",
|
|
||||||
"npm_config_rollback": "true",
|
|
||||||
"TERM_PROGRAM": "Apple_Terminal",
|
|
||||||
"NODE": "/usr/local/Cellar/node/12.6.0/bin/node",
|
|
||||||
"npm_config_usage": "",
|
|
||||||
"npm_config_audit": "true",
|
|
||||||
"INIT_CWD": "/Users/sorrel/code/phono-change-applier",
|
|
||||||
"npm_config_globalignorefile": "/usr/local/etc/npmignore",
|
|
||||||
"SHELL": "/bin/bash",
|
|
||||||
"TERM": "xterm-256color",
|
|
||||||
"npm_config_shell": "/bin/bash",
|
|
||||||
"npm_config_maxsockets": "50",
|
|
||||||
"npm_config_init_author_url": "",
|
|
||||||
"npm_config_shrinkwrap": "true",
|
|
||||||
"npm_config_parseable": "",
|
|
||||||
"npm_config_metrics_registry": "https://registry.npmjs.org/",
|
|
||||||
"TMPDIR": "/var/folders/61/30m32tnj2_n8vpgq01j3xqb40000gq/T/",
|
|
||||||
"npm_config_timing": "",
|
|
||||||
"npm_config_init_license": "ISC",
|
|
||||||
"Apple_PubSub_Socket_Render": "/private/tmp/com.apple.launchd.J3gGwt1Hbc/Render",
|
|
||||||
"npm_config_if_present": "",
|
|
||||||
"TERM_PROGRAM_VERSION": "404.1",
|
|
||||||
"npm_config_sign_git_tag": "",
|
|
||||||
"npm_config_init_author_email": "",
|
|
||||||
"npm_config_cache_max": "Infinity",
|
|
||||||
"npm_config_preid": "",
|
|
||||||
"npm_config_long": "",
|
|
||||||
"npm_config_local_address": "",
|
|
||||||
"npm_config_git_tag_version": "true",
|
|
||||||
"npm_config_cert": "",
|
|
||||||
"TERM_SESSION_ID": "71BD6564-37BE-4A5F-A20D-A1F80094E087",
|
|
||||||
"npm_config_registry": "https://registry.npmjs.org/",
|
|
||||||
"npm_config_noproxy": "",
|
|
||||||
"npm_config_fetch_retries": "2",
|
|
||||||
"npm_package_private": "true",
|
|
||||||
"npm_package_dependencies_react_dom": "^16.12.0",
|
|
||||||
"npm_config_versions": "",
|
|
||||||
"npm_config_message": "%s",
|
|
||||||
"npm_config_key": "",
|
|
||||||
"npm_package_readmeFilename": "README.md",
|
|
||||||
"npm_package_description": "[Inspired by the Zompist Sound Change Applier 2](https://www.zompist.com/sca2.html)",
|
|
||||||
"npm_package_devDependencies__testing_library_react": "^9.3.2",
|
|
||||||
"USER": "sorrel",
|
|
||||||
"npm_config_globalconfig": "/usr/local/etc/npmrc",
|
|
||||||
"npm_package_browserslist_development_1": "last 1 firefox version",
|
|
||||||
"npm_config_prefer_online": "",
|
|
||||||
"npm_config_logs_max": "10",
|
|
||||||
"npm_config_always_auth": "",
|
|
||||||
"npm_package_browserslist_development_0": "last 1 chrome version",
|
|
||||||
"npm_package_eslintConfig_extends": "react-app",
|
|
||||||
"SSH_AUTH_SOCK": "/private/tmp/com.apple.launchd.Pvi0zgMU0F/Listeners",
|
|
||||||
"npm_package_browserslist_development_2": "last 1 safari version",
|
|
||||||
"__CF_USER_TEXT_ENCODING": "0x1F7:0x0:0x0",
|
|
||||||
"npm_execpath": "/usr/local/lib/node_modules/npm/bin/npm-cli.js",
|
|
||||||
"npm_config_global_style": "",
|
|
||||||
"npm_config_cache_lock_retries": "10",
|
|
||||||
"npm_config_update_notifier": "true",
|
|
||||||
"npm_config_cafile": "",
|
|
||||||
"npm_config_heading": "npm",
|
|
||||||
"npm_config_audit_level": "low",
|
|
||||||
"npm_config_searchlimit": "20",
|
|
||||||
"npm_config_read_only": "",
|
|
||||||
"npm_config_offline": "",
|
|
||||||
"npm_config_fetch_retry_mintimeout": "10000",
|
|
||||||
"npm_config_json": "",
|
|
||||||
"npm_config_access": "",
|
|
||||||
"npm_config_argv": "{\"remain\":[],\"cooked\":[\"test\"],\"original\":[\"test\"]}",
|
|
||||||
"PATH": "/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/sorrel/code/phono-change-applier/node_modules/.bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Library/TeX/texbin:/opt/X11/bin",
|
|
||||||
"npm_config_allow_same_version": "",
|
|
||||||
"npm_config_https_proxy": "",
|
|
||||||
"npm_config_engine_strict": "",
|
|
||||||
"npm_config_description": "true",
|
|
||||||
"_": "/Users/sorrel/code/phono-change-applier/node_modules/.bin/react-scripts",
|
|
||||||
"npm_config_userconfig": "/Users/sorrel/.npmrc",
|
|
||||||
"npm_config_init_module": "/Users/sorrel/.npm-init.js",
|
|
||||||
"npm_package_browserslist_production_1": "not dead",
|
|
||||||
"npm_config_cidr": "",
|
|
||||||
"npm_package_browserslist_production_0": ">0.2%",
|
|
||||||
"PWD": "/Users/sorrel/code/phono-change-applier",
|
|
||||||
"npm_config_user": "",
|
|
||||||
"npm_config_node_version": "12.6.0",
|
|
||||||
"npm_package_dependencies_node_sass": "^4.13.0",
|
|
||||||
"npm_lifecycle_event": "test",
|
|
||||||
"npm_package_browserslist_production_2": "not op_mini all",
|
|
||||||
"npm_config_save": "true",
|
|
||||||
"npm_config_ignore_prepublish": "",
|
|
||||||
"npm_config_editor": "vi",
|
|
||||||
"npm_config_auth_type": "legacy",
|
|
||||||
"npm_package_name": "phono-change-applier",
|
|
||||||
"LANG": "en_US.UTF-8",
|
|
||||||
"npm_config_tag": "latest",
|
|
||||||
"npm_config_script_shell": "",
|
|
||||||
"npm_config_progress": "true",
|
|
||||||
"npm_config_global": "",
|
|
||||||
"npm_config_before": "",
|
|
||||||
"npm_package_scripts_build": "react-scripts build",
|
|
||||||
"npm_package_scripts_start": "react-scripts start",
|
|
||||||
"npm_config_searchstaleness": "900",
|
|
||||||
"npm_config_optional": "true",
|
|
||||||
"npm_config_ham_it_up": "",
|
|
||||||
"XPC_FLAGS": "0x0",
|
|
||||||
"npm_config_save_prod": "",
|
|
||||||
"npm_config_force": "",
|
|
||||||
"npm_config_bin_links": "true",
|
|
||||||
"npm_config_searchopts": "",
|
|
||||||
"npm_config_node_gyp": "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js",
|
|
||||||
"npm_config_depth": "Infinity",
|
|
||||||
"npm_config_sso_poll_frequency": "500",
|
|
||||||
"npm_config_rebuild_bundle": "true",
|
|
||||||
"npm_package_version": "0.1.0",
|
|
||||||
"XPC_SERVICE_NAME": "0",
|
|
||||||
"npm_config_unicode": "true",
|
|
||||||
"SHLVL": "2",
|
|
||||||
"HOME": "/Users/sorrel",
|
|
||||||
"npm_config_fetch_retry_maxtimeout": "60000",
|
|
||||||
"npm_package_scripts_test": "react-scripts test",
|
|
||||||
"npm_config_tag_version_prefix": "v",
|
|
||||||
"npm_config_strict_ssl": "true",
|
|
||||||
"npm_config_sso_type": "oauth",
|
|
||||||
"npm_config_scripts_prepend_node_path": "warn-only",
|
|
||||||
"npm_config_save_prefix": "^",
|
|
||||||
"npm_config_loglevel": "notice",
|
|
||||||
"npm_config_ca": "",
|
|
||||||
"npm_config_save_exact": "",
|
|
||||||
"npm_config_group": "20",
|
|
||||||
"npm_config_fetch_retry_factor": "10",
|
|
||||||
"npm_config_dev": "",
|
|
||||||
"npm_config_version": "",
|
|
||||||
"npm_config_prefer_offline": "",
|
|
||||||
"npm_config_cache_lock_stale": "60000",
|
|
||||||
"npm_config_otp": "",
|
|
||||||
"npm_config_cache_min": "10",
|
|
||||||
"npm_config_searchexclude": "",
|
|
||||||
"npm_config_cache": "/Users/sorrel/.npm",
|
|
||||||
"npm_package_dependencies_react_scripts": "3.2.0",
|
|
||||||
"LOGNAME": "sorrel",
|
|
||||||
"npm_lifecycle_script": "react-scripts test",
|
|
||||||
"npm_config_color": "true",
|
|
||||||
"npm_config_proxy": "",
|
|
||||||
"npm_config_package_lock": "true",
|
|
||||||
"npm_config_package_lock_only": "",
|
|
||||||
"npm_config_fund": "true",
|
|
||||||
"npm_package_dependencies_react": "^16.12.0",
|
|
||||||
"npm_config_save_optional": "",
|
|
||||||
"npm_config_ignore_scripts": "",
|
|
||||||
"npm_config_user_agent": "npm/6.13.1 node/v12.6.0 darwin x64",
|
|
||||||
"npm_config_cache_lock_wait": "10000",
|
|
||||||
"npm_config_production": "",
|
|
||||||
"DISPLAY": "/private/tmp/com.apple.launchd.x5Pdwz4pIw/org.macosforge.xquartz:0",
|
|
||||||
"npm_config_send_metrics": "",
|
|
||||||
"npm_config_save_bundle": "",
|
|
||||||
"npm_config_umask": "0022",
|
|
||||||
"npm_config_node_options": "",
|
|
||||||
"npm_config_init_version": "1.0.0",
|
|
||||||
"npm_config_init_author_name": "",
|
|
||||||
"npm_config_git": "git",
|
|
||||||
"npm_config_scope": "",
|
|
||||||
"npm_package_scripts_eject": "react-scripts eject",
|
|
||||||
"SECURITYSESSIONID": "186a7",
|
|
||||||
"npm_config_unsafe_perm": "true",
|
|
||||||
"npm_config_tmp": "/var/folders/61/30m32tnj2_n8vpgq01j3xqb40000gq/T",
|
|
||||||
"npm_config_onload_script": "",
|
|
||||||
"npm_node_execpath": "/usr/local/Cellar/node/12.6.0/bin/node",
|
|
||||||
"npm_config_link": "",
|
|
||||||
"npm_config_format_package_lock": "true",
|
|
||||||
"npm_config_prefix": "/usr/local",
|
|
||||||
"npm_package_devDependencies__testing_library_jest_dom": "^4.2.4",
|
|
||||||
"BABEL_ENV": "test",
|
|
||||||
"NODE_ENV": "test",
|
|
||||||
"PUBLIC_URL": "",
|
|
||||||
"NODE_PATH": "",
|
|
||||||
"JEST_WORKER_ID": "1",
|
|
||||||
"FORCE_COLOR": "1"
|
|
||||||
},
|
|
||||||
"userLimits": {
|
|
||||||
"core_file_size_blocks": {
|
|
||||||
"soft": 0,
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"data_seg_size_kbytes": {
|
|
||||||
"soft": "unlimited",
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"file_size_blocks": {
|
|
||||||
"soft": "unlimited",
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"max_locked_memory_bytes": {
|
|
||||||
"soft": "unlimited",
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"max_memory_size_kbytes": {
|
|
||||||
"soft": "unlimited",
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"open_files": {
|
|
||||||
"soft": 10240,
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"stack_size_bytes": {
|
|
||||||
"soft": 8388608,
|
|
||||||
"hard": 67104768
|
|
||||||
},
|
|
||||||
"cpu_time_seconds": {
|
|
||||||
"soft": "unlimited",
|
|
||||||
"hard": "unlimited"
|
|
||||||
},
|
|
||||||
"max_user_processes": {
|
|
||||||
"soft": 709,
|
|
||||||
"hard": 1064
|
|
||||||
},
|
|
||||||
"virtual_memory_kbytes": {
|
|
||||||
"soft": "unlimited",
|
|
||||||
"hard": "unlimited"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sharedObjects": [
|
|
||||||
"/usr/local/Cellar/node/12.6.0/bin/node",
|
|
||||||
"/usr/local/opt/icu4c/lib/libicui18n.64.dylib",
|
|
||||||
"/usr/local/opt/icu4c/lib/libicuuc.64.dylib",
|
|
||||||
"/usr/local/opt/icu4c/lib/libicudata.64.dylib",
|
|
||||||
"/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation",
|
|
||||||
"/usr/lib/libSystem.B.dylib",
|
|
||||||
"/usr/lib/libc++.1.dylib",
|
|
||||||
"/usr/lib/system/libcache.dylib",
|
|
||||||
"/usr/lib/system/libcommonCrypto.dylib",
|
|
||||||
"/usr/lib/system/libcompiler_rt.dylib",
|
|
||||||
"/usr/lib/system/libcopyfile.dylib",
|
|
||||||
"/usr/lib/system/libcorecrypto.dylib",
|
|
||||||
"/usr/lib/system/libdispatch.dylib",
|
|
||||||
"/usr/lib/system/libdyld.dylib",
|
|
||||||
"/usr/lib/system/libkeymgr.dylib",
|
|
||||||
"/usr/lib/system/liblaunch.dylib",
|
|
||||||
"/usr/lib/system/libmacho.dylib",
|
|
||||||
"/usr/lib/system/libquarantine.dylib",
|
|
||||||
"/usr/lib/system/libremovefile.dylib",
|
|
||||||
"/usr/lib/system/libsystem_asl.dylib",
|
|
||||||
"/usr/lib/system/libsystem_blocks.dylib",
|
|
||||||
"/usr/lib/system/libsystem_c.dylib",
|
|
||||||
"/usr/lib/system/libsystem_configuration.dylib",
|
|
||||||
"/usr/lib/system/libsystem_coreservices.dylib",
|
|
||||||
"/usr/lib/system/libsystem_darwin.dylib",
|
|
||||||
"/usr/lib/system/libsystem_dnssd.dylib",
|
|
||||||
"/usr/lib/system/libsystem_info.dylib",
|
|
||||||
"/usr/lib/system/libsystem_m.dylib",
|
|
||||||
"/usr/lib/system/libsystem_malloc.dylib",
|
|
||||||
"/usr/lib/system/libsystem_network.dylib",
|
|
||||||
"/usr/lib/system/libsystem_networkextension.dylib",
|
|
||||||
"/usr/lib/system/libsystem_notify.dylib",
|
|
||||||
"/usr/lib/system/libsystem_sandbox.dylib",
|
|
||||||
"/usr/lib/system/libsystem_secinit.dylib",
|
|
||||||
"/usr/lib/system/libsystem_kernel.dylib",
|
|
||||||
"/usr/lib/system/libsystem_platform.dylib",
|
|
||||||
"/usr/lib/system/libsystem_pthread.dylib",
|
|
||||||
"/usr/lib/system/libsystem_symptoms.dylib",
|
|
||||||
"/usr/lib/system/libsystem_trace.dylib",
|
|
||||||
"/usr/lib/system/libunwind.dylib",
|
|
||||||
"/usr/lib/system/libxpc.dylib",
|
|
||||||
"/usr/lib/closure/libclosured.dylib",
|
|
||||||
"/usr/lib/libobjc.A.dylib",
|
|
||||||
"/usr/lib/libc++abi.dylib",
|
|
||||||
"/usr/lib/libDiagnosticMessagesClient.dylib",
|
|
||||||
"/usr/lib/libicucore.A.dylib",
|
|
||||||
"/usr/lib/libz.1.dylib",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices",
|
|
||||||
"/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics",
|
|
||||||
"/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO",
|
|
||||||
"/System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSyncLegacy.framework/Versions/A/ColorSyncLegacy",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis",
|
|
||||||
"/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight",
|
|
||||||
"/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate",
|
|
||||||
"/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit",
|
|
||||||
"/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation",
|
|
||||||
"/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration",
|
|
||||||
"/System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay",
|
|
||||||
"/System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface",
|
|
||||||
"/System/Library/Frameworks/Metal.framework/Versions/A/Metal",
|
|
||||||
"/System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport",
|
|
||||||
"/System/Library/Frameworks/Security.framework/Versions/A/Security",
|
|
||||||
"/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore",
|
|
||||||
"/usr/lib/libbsm.0.dylib",
|
|
||||||
"/usr/lib/libauto.dylib",
|
|
||||||
"/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration",
|
|
||||||
"/usr/lib/libarchive.2.dylib",
|
|
||||||
"/usr/lib/libxml2.2.dylib",
|
|
||||||
"/usr/lib/liblangid.dylib",
|
|
||||||
"/usr/lib/libCRFSuite.dylib",
|
|
||||||
"/usr/lib/libenergytrace.dylib",
|
|
||||||
"/usr/lib/system/libkxld.dylib",
|
|
||||||
"/usr/lib/libOpenScriptingUtil.dylib",
|
|
||||||
"/usr/lib/libcoretls.dylib",
|
|
||||||
"/usr/lib/libcoretls_cfhelpers.dylib",
|
|
||||||
"/usr/lib/libpam.2.dylib",
|
|
||||||
"/usr/lib/libsqlite3.dylib",
|
|
||||||
"/usr/lib/libxar.1.dylib",
|
|
||||||
"/usr/lib/libbz2.1.0.dylib",
|
|
||||||
"/usr/lib/liblzma.5.dylib",
|
|
||||||
"/usr/lib/libnetwork.dylib",
|
|
||||||
"/usr/lib/libapple_nghttp2.dylib",
|
|
||||||
"/usr/lib/libpcap.A.dylib",
|
|
||||||
"/usr/lib/libboringssl.dylib",
|
|
||||||
"/usr/lib/libusrtcp.dylib",
|
|
||||||
"/usr/lib/libapple_crypto.dylib",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices",
|
|
||||||
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList",
|
|
||||||
"/System/Library/Frameworks/NetFS.framework/Versions/A/NetFS",
|
|
||||||
"/System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth",
|
|
||||||
"/System/Library/PrivateFrameworks/login.framework/Versions/A/Frameworks/loginsupport.framework/Versions/A/loginsupport",
|
|
||||||
"/System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC",
|
|
||||||
"/usr/lib/libmecabra.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData",
|
|
||||||
"/usr/lib/libmarisa.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon",
|
|
||||||
"/usr/lib/libChineseTokenizer.dylib",
|
|
||||||
"/usr/lib/libcmph.dylib",
|
|
||||||
"/usr/lib/libiconv.2.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling",
|
|
||||||
"/System/Library/Frameworks/CoreData.framework/Versions/A/CoreData",
|
|
||||||
"/System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji",
|
|
||||||
"/usr/lib/libcompression.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory",
|
|
||||||
"/System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS",
|
|
||||||
"/usr/lib/libutil.dylib",
|
|
||||||
"/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement",
|
|
||||||
"/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement",
|
|
||||||
"/usr/lib/libxslt.1.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib",
|
|
||||||
"/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/GPUWrangler.framework/Versions/A/GPUWrangler",
|
|
||||||
"/System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator",
|
|
||||||
"/System/Library/PrivateFrameworks/IOPresentment.framework/Versions/A/IOPresentment",
|
|
||||||
"/System/Library/PrivateFrameworks/DSExternalDisplay.framework/Versions/A/DSExternalDisplay",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib",
|
|
||||||
"/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage",
|
|
||||||
"/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL",
|
|
||||||
"/System/Library/PrivateFrameworks/GraphVisualizer.framework/Versions/A/GraphVisualizer",
|
|
||||||
"/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders",
|
|
||||||
"/usr/lib/libFosl_dynamic.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore",
|
|
||||||
"/System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib",
|
|
||||||
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib",
|
|
||||||
"/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG",
|
|
||||||
"/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSCore.framework/Versions/A/MPSCore",
|
|
||||||
"/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSImage.framework/Versions/A/MPSImage",
|
|
||||||
"/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork",
|
|
||||||
"/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix",
|
|
||||||
"/System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib",
|
|
||||||
"/usr/lib/libcups.2.dylib",
|
|
||||||
"/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos",
|
|
||||||
"/System/Library/Frameworks/GSS.framework/Versions/A/GSS",
|
|
||||||
"/usr/lib/libresolv.9.dylib",
|
|
||||||
"/System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal",
|
|
||||||
"/usr/lib/libheimdal-asn1.dylib",
|
|
||||||
"/System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory",
|
|
||||||
"/System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth",
|
|
||||||
"/System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation",
|
|
||||||
"/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio",
|
|
||||||
"/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox",
|
|
||||||
"/System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce",
|
|
||||||
"/Users/sorrel/code/phono-change-applier/node_modules/jest-haste-map/node_modules/fsevents/lib/binding/Release/node-v72-darwin-x64/fse.node"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -9,7 +9,8 @@ import Epochs from './components/Epochs';
|
||||||
import Options from './components/Options';
|
import Options from './components/Options';
|
||||||
import Output from './components/Output';
|
import Output from './components/Output';
|
||||||
|
|
||||||
import {initState, stateReducer} from './reducers/stateReducer';
|
import {stateReducer} from './reducers/stateReducer';
|
||||||
|
import {initState} from './reducers/stateReducer.init';
|
||||||
|
|
||||||
const PhonoChangeApplier = () => {
|
const PhonoChangeApplier = () => {
|
||||||
const [ state, dispatch ] = useReducer(
|
const [ state, dispatch ] = useReducer(
|
||||||
|
|
30
src/reducers/stateReducer.epochs.js
Normal file
30
src/reducers/stateReducer.epochs.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// @flow
|
||||||
|
import type { stateType } from './stateReducer';
|
||||||
|
|
||||||
|
export type epochAction = {
|
||||||
|
type: "ADD_EPOCH" | "SET_EPOCH",
|
||||||
|
value: {
|
||||||
|
index?: number,
|
||||||
|
name: string,
|
||||||
|
changes?: Array<string>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addEpoch = (state: stateType, action: epochAction): stateType => {
|
||||||
|
const newEpoch = { ...action.value, changes: ['']};
|
||||||
|
return {...state, epochs: [...state.epochs, newEpoch]}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setEpoch = (state: stateType, action: epochAction): stateType => {
|
||||||
|
let mutatedEpochs = state.epochs;
|
||||||
|
const index = action.value.index
|
||||||
|
if (!index) return state;
|
||||||
|
mutatedEpochs[index].name = action.value.name
|
||||||
|
? action.value.name
|
||||||
|
: mutatedEpochs[index].name;
|
||||||
|
|
||||||
|
mutatedEpochs[index].changes = action.value.changes
|
||||||
|
? action.value.changes
|
||||||
|
: mutatedEpochs[index].changes;
|
||||||
|
return {...state, epochs: [...mutatedEpochs]}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ describe('Epochs', () => {
|
||||||
state.epochs = [
|
state.epochs = [
|
||||||
{
|
{
|
||||||
name: 'epoch 1',
|
name: 'epoch 1',
|
||||||
changes: []
|
changes: ['']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@ -17,33 +17,33 @@ describe('Epochs', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('epochs addition returns new epochs list', () => {
|
it('epochs addition returns new epochs list', () => {
|
||||||
const action = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: []}};
|
const action = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: ['']}};
|
||||||
expect(stateReducer(state, action)).toEqual({...state, epochs: [...state.epochs, action.value]})
|
expect(stateReducer(state, action)).toEqual({...state, epochs: [...state.epochs, action.value]})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('epoch name mutation returns new epochs list with mutation', () => {
|
it('epoch name mutation returns new epochs list with mutation', () => {
|
||||||
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: []}};
|
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: ['']}};
|
||||||
const secondAction = {type: 'SET_EPOCH', value: { index: 0, name: 'proto-lang'}};
|
const secondAction = {type: 'SET_EPOCH', value: { index: 0, name: 'proto-lang'}};
|
||||||
const secondState = stateReducer(state, firstAction);
|
const secondState = stateReducer(state, firstAction);
|
||||||
expect(stateReducer(secondState, secondAction)).toEqual(
|
expect(stateReducer(secondState, secondAction)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
epochs: [
|
epochs: [
|
||||||
{name: 'proto-lang', changes: []},
|
{name: 'proto-lang', changes: ['']},
|
||||||
{name: 'epoch 2', changes: []}
|
{name: 'epoch 2', changes: ['']}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('epoch changes mutation returns new epochs list with mutation', () => {
|
it('epoch changes mutation returns new epochs list with mutation', () => {
|
||||||
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: []}};
|
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: ['']}};
|
||||||
const secondAction = {type: 'SET_EPOCH', value: { index: 0, changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n']}};
|
const secondAction = {type: 'SET_EPOCH', value: { index: 0, changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n']}};
|
||||||
const secondState = stateReducer(state, firstAction);
|
const secondState = stateReducer(state, firstAction);
|
||||||
expect(stateReducer(secondState, secondAction)).toEqual(
|
expect(stateReducer(secondState, secondAction)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
epochs: [
|
epochs: [
|
||||||
{name: 'epoch 1', changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n']},
|
{name: 'epoch 1', changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n']},
|
||||||
{name: 'epoch 2', changes: []}
|
{name: 'epoch 2', changes: ['']}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
75
src/reducers/stateReducer.features.js
Normal file
75
src/reducers/stateReducer.features.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// @flow
|
||||||
|
import type { stateType } from './stateReducer';
|
||||||
|
|
||||||
|
export type featureAction = {
|
||||||
|
type: "ADD_FEATURE",
|
||||||
|
value: {
|
||||||
|
positivePhones: Array<string>,
|
||||||
|
negativePhones: Array<string>,
|
||||||
|
feature: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addPhones = (phones: {}, phone: string): {} => {
|
||||||
|
let node = {};
|
||||||
|
phone.split('').forEach((graph, index) => {
|
||||||
|
if (index) node[graph] = {}
|
||||||
|
if (!index && !phones[graph]) phones[graph] = {}
|
||||||
|
node = index === 0 ? phones[graph] : node[graph];
|
||||||
|
if (index === phone.length - 1) node.grapheme = phone;
|
||||||
|
})
|
||||||
|
return phones;
|
||||||
|
}
|
||||||
|
|
||||||
|
const findPhone = (phones: {}, phone: string): {} => {
|
||||||
|
let node = {};
|
||||||
|
phone.split('').forEach((graph, index) => {
|
||||||
|
node = index === 0 ? phones[graph] : node[graph];
|
||||||
|
});
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
const addFeatureToPhone = (
|
||||||
|
phones: {}, phone: string, featureKey: string, featureValue: boolean
|
||||||
|
): {} =>
|
||||||
|
{
|
||||||
|
let node = {}
|
||||||
|
phone.split('').forEach((graph, index) => {
|
||||||
|
node = index === 0 ? phones[graph] : node[graph];
|
||||||
|
if (index === phone.split('').length - 1) node.features = {...node.features, [featureKey]: featureValue}
|
||||||
|
})
|
||||||
|
return phones;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addFeature = (state: stateType, action: featureAction): stateType => {
|
||||||
|
let positivePhones = action.value.positivePhones || [];
|
||||||
|
let negativePhones = action.value.negativePhones || [];
|
||||||
|
let newFeatureName = action.value.feature;
|
||||||
|
|
||||||
|
let newPhoneObject = [
|
||||||
|
...positivePhones, ...negativePhones
|
||||||
|
].reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)
|
||||||
|
|
||||||
|
if (positivePhones) {
|
||||||
|
|
||||||
|
positivePhones.reduce(
|
||||||
|
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, true)
|
||||||
|
, newPhoneObject
|
||||||
|
);
|
||||||
|
|
||||||
|
positivePhones = positivePhones.map( positivePhone => findPhone(newPhoneObject, positivePhone) )
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negativePhones) {
|
||||||
|
|
||||||
|
negativePhones.reduce(
|
||||||
|
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, false)
|
||||||
|
, newPhoneObject
|
||||||
|
);
|
||||||
|
|
||||||
|
negativePhones = negativePhones.map( negativePhone => findPhone(newPhoneObject, negativePhone) )
|
||||||
|
}
|
||||||
|
|
||||||
|
let newFeature = {[action.value.feature]: {positive: positivePhones, negative: negativePhones}};
|
||||||
|
return {...state, features:{...state.features, ...newFeature}, phones: newPhoneObject}
|
||||||
|
}
|
84
src/reducers/stateReducer.init.js
Normal file
84
src/reducers/stateReducer.init.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// @flow
|
||||||
|
import type { stateType } from './stateReducer';
|
||||||
|
|
||||||
|
export type initAction = {
|
||||||
|
type: "INIT"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initState = (changesArgument: number = -1): stateType => {
|
||||||
|
const state = {
|
||||||
|
lexicon: [
|
||||||
|
{lexeme: 'anta', epoch: 'epoch 1'}, 'anat', 'anət', 'anna', 'tan', 'ənta'
|
||||||
|
],
|
||||||
|
epochs: [
|
||||||
|
{
|
||||||
|
name: 'epoch 1',
|
||||||
|
changes: [
|
||||||
|
'[+ occlusive - nasal]>[+ occlusive nasal]/n_',
|
||||||
|
'at>ta/_#',
|
||||||
|
'[+ sonorant - low rounded high back]>_/_',
|
||||||
|
'nn>nun/_',
|
||||||
|
'[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_',
|
||||||
|
'[+ sonorant rounded]>[+ sonorant - rounded]/_#'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
phones: {
|
||||||
|
a: {
|
||||||
|
grapheme: 'a', features: {
|
||||||
|
sonorant: true, back: true, low: true, high: false, rounded: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
u: {
|
||||||
|
grapheme: 'u', features: {
|
||||||
|
sonorant: true, back: true, low: false, high: true, rounded: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ɯ: {
|
||||||
|
grapheme: 'ɯ', features: {
|
||||||
|
sonorant: true, back: true, low: false, high: true, rounded: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ə: {
|
||||||
|
grapheme: 'ə', features: {
|
||||||
|
sonorant: true, low: false, rounded: false, high: false, back: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
t: {
|
||||||
|
grapheme: 't', features: {
|
||||||
|
occlusive: true, coronal: true, obstruent: true
|
||||||
|
},
|
||||||
|
ʰ: {
|
||||||
|
grapheme: 'tʰ', features: {
|
||||||
|
occlusive: true, coronal: true, obstruent: true, aspirated: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
n: {
|
||||||
|
grapheme: 'n', features: {
|
||||||
|
sonorant: true, nasal: true, occlusive: true, coronal: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: {},
|
||||||
|
results: {},
|
||||||
|
errors: {},
|
||||||
|
features: {}
|
||||||
|
};
|
||||||
|
state.features = {
|
||||||
|
sonorant: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ, state.phones.ə, state.phones.n], negative: [] },
|
||||||
|
back: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ ], negative: [ state.phones.ə ] },
|
||||||
|
low: { positive:[ state.phones.a ], negative: [ state.phones.u, state.phones.ɯ, state.phones.ə ] },
|
||||||
|
high: { positive:[ state.phones.u, state.phones.ɯ ], negative: [ state.phones.a, state.phones.ə ] },
|
||||||
|
rounded: { positive:[ state.phones.u ], negative: [ state.phones.a, state.phones.ɯ, state.phones.ə ] },
|
||||||
|
occlusive: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },
|
||||||
|
coronal: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },
|
||||||
|
obstruent: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },
|
||||||
|
nasal: { positive:[ state.phones.n ], negative: [] },
|
||||||
|
aspirated: { positive:[ state.phones.t.ʰ ], negative: [] },
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(changesArgument, 1)
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
|
@ -1,7 +1,18 @@
|
||||||
// @flow
|
// @flow
|
||||||
type stateType = {
|
import { addLexeme, setLexicon } from './stateReducer.lexicon';
|
||||||
lexicon: Array<?string>,
|
import type { lexiconAction } from './stateReducer.lexicon';
|
||||||
epochs: Array<?{name: string, changes: Array<string>}>,
|
import { addEpoch, setEpoch } from './stateReducer.epochs';
|
||||||
|
import type { epochAction } from './stateReducer.epochs';
|
||||||
|
import { addFeature } from './stateReducer.features';
|
||||||
|
import type { featureAction } from './stateReducer.features';
|
||||||
|
import { run } from './stateReducer.results';
|
||||||
|
import type { resultsAction } from './stateReducer.results'
|
||||||
|
import { initState } from './stateReducer.init';
|
||||||
|
import type { initAction } from './stateReducer.init';
|
||||||
|
|
||||||
|
export type stateType = {
|
||||||
|
lexicon: Array<{lexeme: string, epoch: epochType}>,
|
||||||
|
epochs: Array<epochType>,
|
||||||
phones: {[key: string]: phoneType},
|
phones: {[key: string]: phoneType},
|
||||||
options: {},
|
options: {},
|
||||||
results: {},
|
results: {},
|
||||||
|
@ -9,6 +20,10 @@ type stateType = {
|
||||||
features: featureType
|
features: featureType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type epochType = {
|
||||||
|
name: string, changes: Array<string>
|
||||||
|
}
|
||||||
|
|
||||||
type phoneType = {
|
type phoneType = {
|
||||||
grapheme: string,
|
grapheme: string,
|
||||||
features: {[key: string]: boolean}
|
features: {[key: string]: boolean}
|
||||||
|
@ -18,239 +33,39 @@ type featureType = {
|
||||||
[key: string]: {[key: string]: Array<phoneType>}
|
[key: string]: {[key: string]: Array<phoneType>}
|
||||||
}
|
}
|
||||||
|
|
||||||
const addPhones = (phones: {}, phone: string): {} => {
|
type actionType = featureAction | epochAction | initAction | resultsAction | lexiconAction
|
||||||
let node = {};
|
|
||||||
phone.split('').forEach((graph, index) => {
|
|
||||||
if (index) node[graph] = {}
|
|
||||||
if (!index && !phones[graph]) phones[graph] = {}
|
|
||||||
node = index === 0 ? phones[graph] : node[graph];
|
|
||||||
if (index === phone.length - 1) node.grapheme = phone;
|
|
||||||
})
|
|
||||||
return phones;
|
|
||||||
}
|
|
||||||
|
|
||||||
const findPhone = (phones: {}, phone: string): {} => {
|
export const stateReducer = (state: stateType, action: actionType): stateType => {
|
||||||
let node = {};
|
|
||||||
phone.split('').forEach((graph, index) => {
|
|
||||||
node = index === 0 ? phones[graph] : node[graph];
|
|
||||||
});
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
const addFeatureToPhone = (
|
|
||||||
phones: {}, phone: string, featureKey: string, featureValue: boolean
|
|
||||||
): {} =>
|
|
||||||
{
|
|
||||||
let node = {}
|
|
||||||
phone.split('').forEach((graph, index) => {
|
|
||||||
node = index === 0 ? phones[graph] : node[graph];
|
|
||||||
if (index === phone.split('').length - 1) node.features = {...node.features, [featureKey]: featureValue}
|
|
||||||
})
|
|
||||||
return phones;
|
|
||||||
}
|
|
||||||
|
|
||||||
const findFeatures = (phones: {}, lexeme:string): [] => {
|
|
||||||
let featureBundle = []
|
|
||||||
let lastIndex = lexeme.length - 1;
|
|
||||||
let node = {};
|
|
||||||
[...lexeme].forEach((graph, index) => {
|
|
||||||
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[] => {
|
|
||||||
let decomposedChange = rule.split('>');
|
|
||||||
decomposedChange = [decomposedChange[0], ...decomposedChange[1].split('/')]
|
|
||||||
decomposedChange = [decomposedChange[0], decomposedChange[1], ...decomposedChange[2].split('_')];
|
|
||||||
return [...decomposedChange];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const stateReducer = (state: stateType, action: {type: string, value: {}}) => {
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'INIT': {
|
case 'INIT': {
|
||||||
return initState();
|
return initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'ADD_LEXEME': {
|
case 'ADD_LEXEME': {
|
||||||
let newLexeme = action.value;
|
return addLexeme(state, action);
|
||||||
if (!newLexeme.epoch) newLexeme.epoch = state.epochs[0].name;
|
|
||||||
return {...state, lexicon:[...state.lexicon, newLexeme]}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'SET_LEXICON': {
|
case 'SET_LEXICON': {
|
||||||
let newLexicon = action.value;
|
return setLexicon(state, action);
|
||||||
newLexicon = newLexicon.map(lexeme => lexeme.epoch
|
|
||||||
? lexeme
|
|
||||||
: {...lexeme, epoch: state.epochs[0].name});
|
|
||||||
return {...state, lexicon: newLexicon}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'ADD_EPOCH': {
|
case 'ADD_EPOCH': {
|
||||||
let newEpoch = action.value;
|
return addEpoch(state, action);
|
||||||
return {...state, epochs: [...state.epochs, newEpoch]}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'SET_EPOCH': {
|
case 'SET_EPOCH': {
|
||||||
let mutatedEpochs = state.epochs;
|
return setEpoch(state, action);
|
||||||
let index = [action.value.index]
|
|
||||||
|
|
||||||
mutatedEpochs[index].name = action.value.name
|
|
||||||
? action.value.name
|
|
||||||
: mutatedEpochs[index].name;
|
|
||||||
|
|
||||||
mutatedEpochs[index].changes = action.value.changes
|
|
||||||
? action.value.changes
|
|
||||||
: mutatedEpochs[index].changes;
|
|
||||||
return {...state, epochs: [...mutatedEpochs]}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'ADD_FEATURE': {
|
case 'ADD_FEATURE': {
|
||||||
let positivePhones = action.value.positivePhones || [];
|
return addFeature(state, action);
|
||||||
let negativePhones = action.value.negativePhones || [];
|
|
||||||
let newFeatureName = action.value.feature;
|
|
||||||
|
|
||||||
let newPhoneObject = [
|
|
||||||
...positivePhones, ...negativePhones
|
|
||||||
].reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)
|
|
||||||
|
|
||||||
if (positivePhones) {
|
|
||||||
|
|
||||||
positivePhones.reduce(
|
|
||||||
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, true)
|
|
||||||
, newPhoneObject
|
|
||||||
);
|
|
||||||
|
|
||||||
positivePhones = positivePhones.map( positivePhone => findPhone(newPhoneObject, positivePhone) )
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negativePhones) {
|
|
||||||
|
|
||||||
negativePhones.reduce(
|
|
||||||
(phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, false)
|
|
||||||
, newPhoneObject
|
|
||||||
);
|
|
||||||
|
|
||||||
negativePhones = negativePhones.map( negativePhone => findPhone(newPhoneObject, negativePhone) )
|
|
||||||
}
|
|
||||||
|
|
||||||
let newFeature = {[action.value.feature]: {positive: positivePhones, negative: negativePhones}};
|
|
||||||
return {...state, features:{...state.features, ...newFeature}, phones: newPhoneObject}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'RUN': {
|
case 'RUN': {
|
||||||
// ! one epoch only
|
return run(state, action);
|
||||||
// rule 0 '[+ occlusive - nasal]>[+ occlusive nasal]/n_'
|
|
||||||
let ruleBundle = state.epochs[0].changes;
|
|
||||||
ruleBundle = ruleBundle.map(rule => decomposeRule(rule))
|
|
||||||
|
|
||||||
ruleBundle.map(rule => {
|
|
||||||
rule.forEach(position => {
|
|
||||||
console.log(position)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
let featurePhoneBundle = state.lexicon.map(lexeme => findFeatures(state.phones, lexeme))
|
|
||||||
|
|
||||||
console.log(featurePhoneBundle)
|
|
||||||
ruleBundle.forEach(rule => {
|
|
||||||
featurePhoneBundle.map(featurePhone => {
|
|
||||||
// if (findRules(featurePhone, )
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
let results = [];
|
|
||||||
return {...state, results: { pass: state.epochs[0].name, results } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initState = (changesArgument: number = -1): stateType => {
|
|
||||||
const state = {
|
|
||||||
lexicon: [
|
|
||||||
'anta', 'anat', 'anət', 'anna', 'tan', 'ənta'
|
|
||||||
],
|
|
||||||
epochs: [
|
|
||||||
{
|
|
||||||
name: 'epoch 1',
|
|
||||||
changes: [
|
|
||||||
'[+ occlusive - nasal]>[+ occlusive nasal]/n_',
|
|
||||||
'at>ta/_#',
|
|
||||||
'[+ sonorant - low rounded high back]>_/_',
|
|
||||||
'nn>nun/_',
|
|
||||||
'[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_',
|
|
||||||
'[+ sonorant rounded]>[+ sonorant - rounded]/_#'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
phones: {
|
|
||||||
a: {
|
|
||||||
grapheme: 'a', features: {
|
|
||||||
sonorant: true, back: true, low: true, high: false, rounded: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
u: {
|
|
||||||
grapheme: 'u', features: {
|
|
||||||
sonorant: true, back: true, low: false, high: true, rounded: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ɯ: {
|
|
||||||
grapheme: 'ɯ', features: {
|
|
||||||
sonorant: true, back: true, low: false, high: true, rounded: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ə: {
|
|
||||||
grapheme: 'ə', features: {
|
|
||||||
sonorant: true, low: false, rounded: false, high: false, back: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
t: {
|
|
||||||
grapheme: 't', features: {
|
|
||||||
occlusive: true, coronal: true, obstruent: true
|
|
||||||
},
|
|
||||||
ʰ: {
|
|
||||||
grapheme: 'tʰ', features: {
|
|
||||||
occlusive: true, coronal: true, obstruent: true, aspirated: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
n: {
|
|
||||||
grapheme: 'n', features: {
|
|
||||||
sonorant: true, nasal: true, occlusive: true, coronal: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
options: {},
|
|
||||||
results: {},
|
|
||||||
errors: {},
|
|
||||||
features: {}
|
|
||||||
};
|
|
||||||
state.features = {
|
|
||||||
sonorant: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ, state.phones.ə, state.phones.n], negative: [] },
|
|
||||||
back: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ ], negative: [ state.phones.ə ] },
|
|
||||||
low: { positive:[ state.phones.a ], negative: [ state.phones.u, state.phones.ɯ, state.phones.ə ] },
|
|
||||||
high: { positive:[ state.phones.u, state.phones.ɯ ], negative: [ state.phones.a, state.phones.ə ] },
|
|
||||||
rounded: { positive:[ state.phones.u ], negative: [ state.phones.a, state.phones.ɯ, state.phones.ə ] },
|
|
||||||
occlusive: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },
|
|
||||||
coronal: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },
|
|
||||||
obstruent: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },
|
|
||||||
nasal: { positive:[ state.phones.n ], negative: [] },
|
|
||||||
aspirated: { positive:[ state.phones.t.ʰ ], negative: [] },
|
|
||||||
}
|
|
||||||
|
|
||||||
if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(changesArgument, 1)
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
41
src/reducers/stateReducer.lexicon.js
Normal file
41
src/reducers/stateReducer.lexicon.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// @flow
|
||||||
|
import type { stateType } from './stateReducer';
|
||||||
|
|
||||||
|
type lexemeType = {
|
||||||
|
lexeme: string,
|
||||||
|
epoch?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type addLexemeAction = {
|
||||||
|
type: 'ADD_LEXEME',
|
||||||
|
value: lexemeType
|
||||||
|
}
|
||||||
|
|
||||||
|
type setLexiconAction = {
|
||||||
|
type: 'SET_LEXICON',
|
||||||
|
value: Array<lexemeType>
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeLexeme = (lexeme: string, epochName: ?string, state: stateType) => {
|
||||||
|
const newLexeme = {lexeme: lexeme, epoch: state.epochs[0]};
|
||||||
|
if (epochName) {
|
||||||
|
const epochIndex = state.epochs.findIndex(epoch => epoch.name === epochName);
|
||||||
|
if (epochIndex > 0) {
|
||||||
|
newLexeme.epoch = state.epochs[epochIndex];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return newLexeme;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type lexiconAction = addLexemeAction | setLexiconAction
|
||||||
|
|
||||||
|
export const addLexeme = (state: stateType, action: addLexemeAction): stateType => {
|
||||||
|
const newLexeme = makeLexeme(action.value.lexeme, action.value.epoch, state);
|
||||||
|
return {...state, lexicon:[...state.lexicon, newLexeme]}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setLexicon = (state: stateType, action: setLexiconAction): stateType => {
|
||||||
|
let newLexicon = action.value;
|
||||||
|
newLexicon = newLexicon.map(lexeme => makeLexeme(lexeme.lexeme, lexeme.epoch, state));
|
||||||
|
return {...state, lexicon: newLexicon}
|
||||||
|
}
|
|
@ -2,16 +2,20 @@ import {stateReducer} from './stateReducer';
|
||||||
|
|
||||||
describe('Lexicon', () => {
|
describe('Lexicon', () => {
|
||||||
const state = {
|
const state = {
|
||||||
lexicon: [
|
epochs: [
|
||||||
{lexeme:'anta', epoch:'epoch 1'},
|
{ name: 'epoch 1', changes:[''] },
|
||||||
{lexeme:'anat', epoch:'epoch 1'},
|
{ name: 'epoch 2', changes:[''] }
|
||||||
{lexeme:'anət', epoch:'epoch 1'},
|
]
|
||||||
{lexeme:'anna', epoch:'epoch 1'},
|
}
|
||||||
{lexeme:'tan', epoch:'epoch 1'},
|
state.lexicon = [
|
||||||
{lexeme:'ənta', epoch:'epoch 1'}
|
{lexeme:'anta', epoch:state.epochs[0]},
|
||||||
],
|
{lexeme:'anat', epoch:state.epochs[0]},
|
||||||
epochs: [{name: 'epoch 1'}]
|
{lexeme:'anət', epoch:state.epochs[0]},
|
||||||
};
|
{lexeme:'anna', epoch:state.epochs[0]},
|
||||||
|
{lexeme:'tan', epoch:state.epochs[0]},
|
||||||
|
{lexeme:'ənta', epoch:state.epochs[0]}
|
||||||
|
]
|
||||||
|
;
|
||||||
|
|
||||||
it('lexicon returned unaltered', () => {
|
it('lexicon returned unaltered', () => {
|
||||||
const action = {type: ''};
|
const action = {type: ''};
|
||||||
|
@ -20,12 +24,12 @@ describe('Lexicon', () => {
|
||||||
|
|
||||||
it('lexicon addition without epoch returns updated lexicon with default epoch', () => {
|
it('lexicon addition without epoch returns updated lexicon with default epoch', () => {
|
||||||
const action = {type: 'ADD_LEXEME', value: {lexeme:'ntʰa'}}
|
const action = {type: 'ADD_LEXEME', value: {lexeme:'ntʰa'}}
|
||||||
expect(stateReducer(state, action)).toEqual({...state, lexicon:[...state.lexicon, {lexeme:'ntʰa', epoch:'epoch 1'}]});
|
expect(stateReducer(state, action)).toEqual({...state, lexicon:[...state.lexicon, {lexeme:'ntʰa', epoch:state.epochs[0]}]});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('lexicon addition with epoch returns updated lexicon with correct epoch', () => {
|
it('lexicon addition with epoch returns updated lexicon with correct epoch', () => {
|
||||||
const action = {type: 'ADD_LEXEME', value: {lexeme:'ntʰa', epoch: 'epoch 2'}}
|
const action = {type: 'ADD_LEXEME', value: {lexeme:'ntʰa', epoch: 'epoch 2'}}
|
||||||
expect(stateReducer(state, action)).toEqual({...state, lexicon:[...state.lexicon, action.value]});
|
expect(stateReducer(state, action)).toEqual({...state, lexicon:[...state.lexicon, {lexeme:'ntʰa', epoch:state.epochs[1]}]});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('lexicon set returns updated lexicon with correct epoch', () => {
|
it('lexicon set returns updated lexicon with correct epoch', () => {
|
||||||
|
@ -36,15 +40,20 @@ describe('Lexicon', () => {
|
||||||
{lexeme:'anna', epoch:'epoch 1'}
|
{lexeme:'anna', epoch:'epoch 1'}
|
||||||
]
|
]
|
||||||
const action = {type: 'SET_LEXICON', value: newLexicon}
|
const action = {type: 'SET_LEXICON', value: newLexicon}
|
||||||
expect(stateReducer(state, action)).toEqual({...state, lexicon:newLexicon});
|
expect(stateReducer(state, action)).toEqual({...state, lexicon:[
|
||||||
|
{lexeme:'anta', epoch:state.epochs[0]},
|
||||||
|
{lexeme:'anat', epoch:state.epochs[0]},
|
||||||
|
{lexeme:'anət', epoch:state.epochs[0]},
|
||||||
|
{lexeme:'anna', epoch:state.epochs[0]}
|
||||||
|
]});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('lexicon set with no epoch returns updated lexicon with defaul epoch', () => {
|
it('lexicon set with no epoch returns updated lexicon with defaul epoch', () => {
|
||||||
const newLexicon = [
|
const newLexicon = [
|
||||||
{lexeme:'anta', epoch:'epoch 1'},
|
{lexeme:'anta', epoch:state.epochs[0]},
|
||||||
{lexeme:'anat', epoch:'epoch 1'},
|
{lexeme:'anat', epoch:state.epochs[0]},
|
||||||
{lexeme:'anət', epoch:'epoch 2'},
|
{lexeme:'anət', epoch:state.epochs[1]},
|
||||||
{lexeme:'anna', epoch:'epoch 1'}
|
{lexeme:'anna', epoch:state.epochs[0]}
|
||||||
]
|
]
|
||||||
const inputLexicon = [
|
const inputLexicon = [
|
||||||
{lexeme:'anta'},
|
{lexeme:'anta'},
|
||||||
|
|
57
src/reducers/stateReducer.results.js
Normal file
57
src/reducers/stateReducer.results.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// @flow
|
||||||
|
import type { stateType } from './stateReducer';
|
||||||
|
|
||||||
|
export type resultsAction = {
|
||||||
|
type: 'RUN'
|
||||||
|
}
|
||||||
|
|
||||||
|
const findFeatures = (phones: {}, lexeme:string): [] => {
|
||||||
|
let featureBundle = []
|
||||||
|
let lastIndex = lexeme.length - 1;
|
||||||
|
let node = {};
|
||||||
|
[...lexeme].forEach((graph, index) => {
|
||||||
|
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[] => {
|
||||||
|
let decomposedChange = rule.split('>');
|
||||||
|
decomposedChange = [decomposedChange[0], ...decomposedChange[1].split('/')]
|
||||||
|
decomposedChange = [decomposedChange[0], decomposedChange[1], ...decomposedChange[2].split('_')];
|
||||||
|
return [...decomposedChange];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const run = (state: stateType, action: resultsAction): stateType => {
|
||||||
|
// ! one epoch only
|
||||||
|
// rule 0 '[+ occlusive - nasal]>[+ occlusive nasal]/n_'
|
||||||
|
let ruleBundle = state.epochs[0].changes;
|
||||||
|
ruleBundle = ruleBundle.map(rule => decomposeRule(rule))
|
||||||
|
|
||||||
|
ruleBundle.map(rule => {
|
||||||
|
rule.forEach(position => {
|
||||||
|
console.log(position)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let featurePhoneBundle = state.lexicon.map(lexeme => findFeatures(state.phones, lexeme))
|
||||||
|
|
||||||
|
console.log(featurePhoneBundle)
|
||||||
|
ruleBundle.forEach(rule => {
|
||||||
|
featurePhoneBundle.map(featurePhone => {
|
||||||
|
// if (findRules(featurePhone, )
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let results = [];
|
||||||
|
return {...state, results: { pass: state.epochs[0].name, results } }
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import {stateReducer, initState} from './stateReducer';
|
import {stateReducer} from './stateReducer';
|
||||||
|
import {initState} from './stateReducer.init';
|
||||||
|
|
||||||
describe('Results', () => {
|
describe('Results', () => {
|
||||||
let state = {};
|
let state = {};
|
||||||
|
|
Loading…
Reference in a new issue