{"size": 5382, "ext": "js", "max_stars_repo_path": "src/core/choose-skill.js", "max_stars_repo_name": "gotoeasy/aify", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "src/core/choose-skill.js", "max_issues_repo_name": "gotoeasy/aify", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "src/core/choose-skill.js", "max_forks_repo_name": "gotoeasy/aify", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 35.4078947368, "max_line_length": 159, "alphanum_fraction": 0.4303232999}
const File = require('@gotoeasy/file');
const os = require('@gotoeasy/os');
const store = require('../util/store');
const getKeywords = require('../util/get-keywords');
const log = require('fancy-log');

module.exports = (function (oStore = store()) {

    // 获取技能（参数的名称和关键词，都已统一整理，转为半角小写去重复）
    return function (ainame, name, ...keywords) {

        if (!name){
            log(`[${ainame}] missing skill name`, '......', '你不懂我');
            return;
        }

        let storeKey = `${ainame}\n${name}`;
        let skills = oStore.peek(storeKey);
        if (!skills){

            if ( ainame !== 'angel' ) {
                // 看看有没有天赋
                storeKey = `angel\n${name}`;
                skills = oStore.peek(storeKey);
                if (!skills){
                    // 没天赋，再学吧
                    log(`[${ainame}] no  skill:`, name, '......', '你敢教我包会');
                    return;
                }else{
                    // 有天赋，继续
                }
            }else{
                // 直接乱要天赋？懒得理你
                return;
            }

        }

        let ary = [];
        skills.length > 1 && skills.forEach((skill, i) => {

            let item = { i, score: 0, datetime: skill.datetime };
            keywords.forEach(k => {
                skill.keywords.includes(k) && item.score++;                 // 每匹配到一个关键词，加1分
            });

            let total = item.score + skill.score;                           // 匹配数 + 基础分
            if ( item.score === 0 ) {
                // 零关键词匹配
                if ( !keywords.length ) {
                    // 没有关键词条件
                    if ( !skill.keywords.length ) {
                        total += 100;                                       // 技能没有关键词，等同完全匹配，加100分
                    }else{
                        total -= skill.keywords.length;                     // 技能有关键词，按技能关键词数量减分
                    }
                }else {
                    // 有关键词条件
                    total -= 100;                                           // 有关键词条件，却一个关键词都匹配不上，减100分
                }
            }else{
                // 有关键词匹配

                // 匹配占条件数量比重越大，分数越高
                if ( item.score === keywords.length ) {
                    total += item.score;                                    // 关键词条件全部被匹配，加1倍分
                }else{
                    total -= 2 * (keywords.length - item.score);            // 关键词条件部分被匹配，扣减未匹配条件数量的2倍
                }

                // 匹配占技能关键词数量比重越大，分数越高
                if ( item.score === skill.keywords.length ) {
                    total += 100;                                           // 技能关键词完全匹配，加100分
                }else{
                    total -= (skill.keywords.length - item.score);          // 技能关键词被部分匹配，扣减未匹配数量
                }
            }
            item.score = total;         
            skill.state && ary.push(item);                                  // 有效技能才加入筛选
        });


        skills.length > 1 && ary.sort(comparerSkill);                       // 按分数降序学习日升序进行排序
        let skill = skills.length > 1 ? skills[ary[0].i] : skills[0];       // 获得最佳匹配的技能（分数最高、学习最早）

        skill.jsfile = skill.jsfile || getJsFileName(skill.fn);
        let jsfile = File.resolve(getSkillFnsPath(), skill.jsfile);

		if ( !File.existsFile(jsfile) ){
            log(`[${ainame}] gen skill -`, skill.name, `[${skill.keywords.join(', ')}]`, File.name(jsfile));
            File.write(jsfile, getJsSource(skill));
		}
		let fnSkill = require(jsfile);

        if ( ary.length > 1 && ary[0].score === ary[1].score ) {
            log(`[${ainame}] [WARNING] USE EARLIEST SKILL -`, skill.name, `[${skill.keywords.join(', ')}]`, File.name(jsfile));  // 得分相同，输出警告提示，提醒使用注意明确更精准的关键词
        }else{
            log(`[${ainame}] use skill -`, skill.name, `[${skill.keywords.join(', ')}]`, File.name(jsfile));
        }
        return fnSkill;
    }

})();

function getSkillFnsPath(){
    return File.resolve(__dirname, '../../skillfns');
}

function comparerSkill(o1, o2) {
    if (o1.score === o2.score) {
        return o1.datetime - o2.datetime;                                   // 学习日升序
    } else {
        return o2.score - o1.score;                                         // 分数降序
    }
}

function getJsFileName(srcFn) {
    let rs1 = 11197, rs2 = 53503, rs3 = 90121, i = srcFn.length, charcode;
    while (i) {
        charcode = srcFn.charCodeAt(--i);
        rs1 = (rs1 * 33) ^ charcode;
        rs2 = (rs2 * 33) ^ charcode;
        rs3 = (rs3 * 33) ^ charcode;
    }
    rs1 = rs1 >>> 0;
    rs2 = rs2 >>> 0;
    rs3 = rs3 >>> 0;

    let p128 = rs1 & 0b1111111;

    return `${p128}/${rs1.toString(36)}-${rs2.toString(36)}-${rs3.toString(36)}.js`;
}

function getJsSource(skill) {

    let desc = skill.desc || '无描述';
    desc = desc.split('\n').join('\n// ');

    let ary = [];
    ary.push(`// ---------------------------------------------------------`);
    ary.push(`// ${desc}`);
    ary.push(`// `);
    ary.push(`// skill   : ${skill.name}`);
    ary.push(`// keywords: ${skill.keywords.join(', ')}`);
    ary.push(`// datetime: ${new Date(skill.datetime)}`);
    ary.push(`// aify ver: ${skill.aify || '无限定'}`);
    ary.push(`// ---------------------------------------------------------`);
    ary.push(/module.exports\s*=/.test(skill.fn) ? skill.fn : 'module.exports = ' + skill.fn);
    return ary.join('\r\n');
}

