387 lines
12 KiB
JavaScript
387 lines
12 KiB
JavaScript
// 通用方法
|
|
import _filter from './filter';
|
|
import _map from './map';
|
|
|
|
var _mode = {}; // 模式数据
|
|
var _data = Object.assign({},_map); // 最终数据
|
|
|
|
// 数组去重
|
|
export function unique(arr){
|
|
var sameList = arr.filter(item=>item==item.replace(/[ol](?=s|b)/,'x').replace(/&[ol]/,''));
|
|
return arr.filter(item=>{
|
|
var temp = item.replace(/[ol](?=s|b)/,'x').replace(/&[ol]/,'');
|
|
return sameList.indexOf(item)>-1||item!=temp&&sameList.indexOf(temp)==-1;
|
|
}).filter((item,idx,arr) => arr.indexOf(item) === idx);
|
|
};
|
|
|
|
// 中文获取选择器
|
|
export function getSelectors(str){
|
|
str = str.replace(/之/,'的').replace(/我的?(.+)/,'$1');
|
|
if(str.match(/[^娘婆岳亲]家的?/)){
|
|
str = str.replace(/家的?/,'的');
|
|
}
|
|
var lists = str.split('的');
|
|
var result = [];
|
|
var isMatch = true;
|
|
// 双向替换
|
|
var replaceMap = {
|
|
'晜':'兄',
|
|
'哥':'兄',
|
|
'姐':'姊',
|
|
'侄':'姪',
|
|
'婿':'壻',
|
|
'祖父':'王父',
|
|
'祖母':'王母',
|
|
'弟媳':'弟妇',
|
|
'嫂':'兄妇',
|
|
'孙女婿':'孙婿',
|
|
'甥女婿':'甥婿',
|
|
'侄女婿':'侄婿',
|
|
'孙媳妇':'孙妇',
|
|
'甥媳妇':'甥妇',
|
|
'侄媳妇':'侄妇',
|
|
};
|
|
// 含义扩展
|
|
var replaceFilter = {
|
|
'^从表':['从父姑表','从父舅表','从父姨表','从母姑表','从母舅表','从母叔表'],
|
|
'^表表':['姑表叔表','姑表姑表','姑表舅表','姑表姨表','舅表叔表','舅表姑表','舅表舅表','舅表姨表'],
|
|
'^([夫妻内外]?)表':['$1姑表','$1舅表'],
|
|
'^([姑舅])表(?=[^伯叔])':['$1表伯','$1表叔'],
|
|
'^姻':['姑姻','姨姻','姊妹姻','女姻'],
|
|
'^眷':['叔眷','舅眷','兄弟眷','男眷'],
|
|
'^亲家':['姊妹姻','兄弟眷'],
|
|
'^([堂表姨]?)([曾高天烈太远鼻]?)(祖?)([伯叔姑舅姨])':['$1$4$2$3'],
|
|
'^([曾玄来晜仍云耳])([侄甥])':['$2$1'],
|
|
'^外表([伯叔姑舅姨])':['姑表$1外','舅表$1外'],
|
|
'^([堂表姨]?)外甥':['$1甥'],
|
|
'^([舅叔])([曾玄外]*)孙':['$1侄$2孙'],
|
|
'^([姨姑])([曾玄外]*)孙':['$1甥$2孙'],
|
|
'([孙甥侄])$':['$1男','$1女'],
|
|
'([姑舅姨叔])([孙外]*)([男女])$':['$1表侄$2$3','$1表甥$2$3'],
|
|
'祖$':['祖父'],
|
|
'嫂$':['兄妇'],
|
|
'女儿$':['女'],
|
|
'外甥$':['甥'],
|
|
};
|
|
while(lists.length){
|
|
var name = lists.shift(); //当前匹配词
|
|
var items = []; //当前匹配词可能性
|
|
var x_items = [];
|
|
var r_items = [];
|
|
var keywords = [name];
|
|
var getList = function(name){
|
|
for(var filter in replaceFilter){
|
|
var word_list = replaceFilter[filter];
|
|
word_list.forEach(function(word){
|
|
var name1 = name.replace(new RegExp(filter),word);
|
|
if(name1!=name){
|
|
keywords.push(name1);
|
|
getList(name1);
|
|
}
|
|
});
|
|
}
|
|
for(var word in replaceMap){
|
|
var name1 = name.replace(word,replaceMap[word]);
|
|
var name2 = name.replace(replaceMap[word],word);
|
|
if(name1!=name){
|
|
keywords.push(name1);
|
|
}
|
|
if(name2!=name){
|
|
keywords.push(name2);
|
|
}
|
|
}
|
|
};
|
|
getList(name);
|
|
// 通过关键词找关系
|
|
keywords.forEach(function(name){
|
|
var x_name = name.replace(/^[大|小|老]|^[一|二|三|四|五|六|七|八|九|十]{1,2}/,'几');
|
|
var r_name = name.replace(/^[大|小|老]|^[一|二|三|四|五|六|七|八|九|十]{1,2}/,'');
|
|
for(var i in _data){
|
|
if(_data[i].indexOf(name)>-1){
|
|
items.push(i);
|
|
}
|
|
if(name!=x_name&&_data[i].indexOf(x_name)>-1){
|
|
x_items.push(i);
|
|
}
|
|
if(name!=r_name&&_data[i].indexOf(r_name)>-1){
|
|
if(!i.match(/^[mf,]+$/)&&!r_name.match(/^[从世]/)){ // 直系祖辈不参与排序
|
|
r_items.push(i);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
// console.log('[keywords]',keywords);
|
|
// 如找不到结果,再是否存在称呼的排行问题(不直接判断,因存在"大舅""三从父兄""三世祖"这样特俗含义的情况)
|
|
if(!items.length){
|
|
items = x_items;
|
|
}
|
|
if(!items.length){
|
|
items = r_items;
|
|
}
|
|
// 完全匹配不到结果
|
|
if(!items.length){
|
|
isMatch = false;
|
|
}
|
|
var res = [];
|
|
if(!result.length){
|
|
result = [''];
|
|
}
|
|
result.forEach(function(a){
|
|
items.forEach(function(b){
|
|
res.push(a+(b?','+b:''));
|
|
});
|
|
});
|
|
result = res;
|
|
}
|
|
return isMatch?result:[];
|
|
};
|
|
|
|
// 选择器转ID
|
|
export function selector2id(selector,sex){
|
|
var result = [];
|
|
var hash = {};
|
|
//性别判断
|
|
if(sex<0){
|
|
if(selector.match(/^,[w1]/)){
|
|
sex = 1;
|
|
}else if(selector.match(/^,[h0]/)){
|
|
sex = 0;
|
|
}
|
|
}else if(sex==1&&selector.match(/^,[h0]/)){
|
|
return false;
|
|
}else if(sex==0&&selector.match(/^,[w1]/)){
|
|
return false;
|
|
}
|
|
// console.log('[selector]',selector);
|
|
var getId = function(selector,sex){
|
|
if(sex>-1&&selector.indexOf(',1')==-1&&selector.indexOf(',0')==-1){
|
|
selector = ','+sex+selector;
|
|
}
|
|
if(selector.match(/,[mwd0](&[ol])?,w|,[hfs1](&[ol])?,h/)){ //同志关系去除
|
|
return false;
|
|
}
|
|
var s='';
|
|
if(!hash[selector]){
|
|
hash[selector] = true;
|
|
do{
|
|
s = selector;
|
|
for(var i in _filter){
|
|
var item = _filter[i];
|
|
// console.log('[filter]',item['exp'],selector);
|
|
selector = selector.replace(item['exp'],item['str']);
|
|
if(selector.indexOf('#')>-1){
|
|
selector.split('#').forEach(getId);
|
|
return false;
|
|
}
|
|
}
|
|
}while(s!=selector);
|
|
if(selector.match(/,[mwd0](&[ol])?,w|,[hfs1](&[ol])?,h/)){ //同志关系去除
|
|
return false;
|
|
}
|
|
selector = selector.replace(/,[01]/,'').substr(1); //去前面逗号和性别信息
|
|
result.push(selector);
|
|
}
|
|
}
|
|
getId(selector,sex);
|
|
return unique(result);
|
|
};
|
|
|
|
// 通过ID获取数据
|
|
export function getItemsById(id){
|
|
var items = [];
|
|
var getData = function(d){
|
|
var res = [];
|
|
if(_data[d]){
|
|
res.push(_data[d][0]);
|
|
}else{
|
|
for(var i in _data){
|
|
if(i.replace(/&[ol]/g,'')==d){
|
|
res.push(_data[i][0]);
|
|
}else{
|
|
var expr = d;
|
|
while (expr.match(/[ol](b|s)/)){
|
|
expr = expr.replace(/[ol](b|s)/,'x$1');
|
|
if(expr==i){
|
|
res.push(_data[i][0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
if(_data[id]){ // 直接匹配称呼
|
|
items.push(_data[id][0]);
|
|
}else{
|
|
items = getData(id);
|
|
// 忽略年龄条件查找
|
|
if(!items.length){
|
|
id = id.replace(/&[ol]/g,'');
|
|
items = getData(id);
|
|
}
|
|
// 忽略年龄条件查找
|
|
if(!items.length){
|
|
id = id.replace(/[ol](b|s)/g,'x$1');
|
|
items = getData(id);
|
|
}
|
|
// 缩小访问查找
|
|
if(!items.length){
|
|
var l = id.replace(/x/g,'l');
|
|
var o = id.replace(/x/g,'o');
|
|
items = items.concat(getData(o),getData(l));
|
|
}
|
|
}
|
|
return items;
|
|
};
|
|
|
|
// 逆转ID
|
|
export function reverseId(id,sex){
|
|
var hash = {
|
|
f:['d','s'],
|
|
m:['d','s'],
|
|
h:['w',''],
|
|
w:['','h'],
|
|
s:['m','f'],
|
|
d:['m','f'],
|
|
lb:['os','ob'],
|
|
ob:['ls','lb'],
|
|
xb:['xs','xb'],
|
|
ls:['os','ob'],
|
|
os:['ls','lb'],
|
|
xs:['xs','xb']
|
|
};
|
|
var age = '';
|
|
if(id.match(/&o$/)){
|
|
age = '&l';
|
|
}else if(id.match(/&l$/)){
|
|
age = '&o';
|
|
}
|
|
if(id){
|
|
id = id.replace(/&[ol]/g,'');
|
|
//性别判断
|
|
if(sex<0){
|
|
if(id.match(/^w/)){
|
|
sex = 1;
|
|
}else if(id.match(/^h/)){
|
|
sex = 0;
|
|
}
|
|
}
|
|
var result = [];
|
|
var doing = function(sex){
|
|
var sid = (','+sex+','+id).replace(/,[fhs]|,[olx]b/g,',1').replace(/,[mwd]|,[olx]s/g,',0');
|
|
sid = sid.substring(0,sid.length-2);
|
|
var id_arr = id.split(',').reverse();
|
|
var sid_arr = sid.split(',').reverse();
|
|
var arr = id_arr.map((id,i)=>hash[id][sid_arr[i]]);
|
|
var g = 0;
|
|
var gMap = {'f':1,'m':1,'s':-1,'d':-1};
|
|
arr.forEach(function(r){
|
|
g += gMap[r]||0;
|
|
});
|
|
return arr.join(',')+(g?'':age);
|
|
};
|
|
if(sex<0){
|
|
result.push(doing(1));
|
|
result.push(doing(0));
|
|
}else{
|
|
result.push(doing(sex));
|
|
}
|
|
return result;
|
|
}
|
|
return [''];
|
|
};
|
|
|
|
// 通过ID获取关系链条
|
|
export function getChainById(id){
|
|
var arr = id.split(',');
|
|
return arr.map(function(sign){
|
|
var key = sign.replace(/&[ol]/,'');
|
|
var data = Object.assign({},_data,{
|
|
'xb':['兄弟'],
|
|
'xs':['姐妹'],
|
|
});
|
|
return data[key][0];
|
|
}).join('的');
|
|
};
|
|
|
|
// 合并选择器,查找两个对象之间的关系
|
|
export function mergeSelector(from,to,my_sex){
|
|
if(my_sex<0){
|
|
var to_sex = -1;
|
|
var from_sex = -1;
|
|
if(from.match(/^,[w1]/)){
|
|
from_sex = 1;
|
|
}else if(from.match(/^,[h0]/)){
|
|
from_sex = 0;
|
|
}
|
|
if(to.match(/^,[w1]/)){
|
|
to_sex = 1;
|
|
}else if(to.match(/^,[h0]/)){
|
|
to_sex = 0;
|
|
}
|
|
if(from_sex==-1&&to_sex>-1){
|
|
my_sex = to_sex;
|
|
}else if(from_sex>-1&&to_sex==-1){
|
|
my_sex = from_sex;
|
|
}else if(from_sex==to_sex){
|
|
my_sex = from_sex;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
var sex = my_sex;
|
|
var from_ids = selector2id(from,my_sex);
|
|
var to_ids = selector2id(to,my_sex);
|
|
var to_rids = [];
|
|
if(!from_ids.length||!to_ids.length){
|
|
return false;
|
|
}
|
|
if(to){
|
|
var toIsMale = false;
|
|
var toIsFemale = false;
|
|
to_ids.forEach(function(id){
|
|
if(id.match(/([fhs1](&[ol])?|[olx]b)$/)){
|
|
toIsMale = true;
|
|
}
|
|
if(id.match(/([mwd0](&[ol])?|[olx]s)$/)){
|
|
toIsFemale = true;
|
|
}
|
|
to_rids = to_rids.concat(reverseId(id,my_sex));
|
|
});
|
|
to_rids = unique(to_rids);
|
|
if(toIsMale&&toIsFemale){
|
|
sex = -1;
|
|
}else if(toIsMale){
|
|
sex = 1;
|
|
}else if(toIsFemale){
|
|
sex = 0;
|
|
}
|
|
}else{
|
|
to_rids = [''];
|
|
}
|
|
// console.log('[from_ids]',from_ids,'to_rids',to_rids);
|
|
var from_selector = from_ids.length>1?'['+from_ids.join('|')+']':from_ids[0];
|
|
var to_selector = to_rids.length>1?'['+to_rids.join('|')+']':to_rids[0];
|
|
return {
|
|
'selector':(to?','+to_selector:'')+(from?','+from_selector:''),
|
|
'sex':sex
|
|
};
|
|
};
|
|
|
|
// 设置模式
|
|
export function setMode(sign,data){
|
|
_mode[sign] = Object.assign(_mode[sign]||{},data);
|
|
};
|
|
|
|
// 获取指定模式数据
|
|
export function getDataByMode(sign){
|
|
var data = Object.assign({},_map);
|
|
if(sign&&_mode[sign]){
|
|
for(var key in _mode[sign]){
|
|
data[key] = [].concat(_mode[sign][key],_map[key]||[]);
|
|
}
|
|
}
|
|
return data;
|
|
};
|