relationship/src/method.js
2022-07-18 23:11:18 +08:00

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;
};