V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
XadillaX
V2EX  ›  分享创造

让我们一起来起花名吧

  •  
  •   XadillaX ·
    XadillaX · 2016-02-24 16:14:40 +08:00 · 5271 次点击
    这是一个创建于 3203 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原文: https://xcoder.in/2016/02/24/lets-hua/

    起因

    起因是我一个叫『小龙』的好基友由于某些原因离职去了一家跟阿里一样有着『花名文化』的公司,于是开始为花名犯愁。

    结合之前妹纸『弍纾』在起花名的时候也遇到了同样的困扰,于是决定用 Node.js 写个『一本正经乱起花名』的程序。

    准备

    Chinese Random Name

    首先起花名的原理就是胡乱随机一串字出来胡乱拼。

    于是准备应该有 chinese-random-name,一个随机生成中文名的包。

    使用它很简单,先把它 require 进来:

    const randomName = require("chinese-random-name");
    

    基本用法

    如果你需要随机生成一个名字只需要 randomName.generate() 就可以了;如果你要随机一个姓那么就 randomName.surnames.getOne();如果你只需要获得名字,这里面就有点门道了。

    高级用法

    你可以随机生成一个名(不带姓的) randomName.names.get();你也可以指定名字的字数,一二三:

    randomName.names.get1();
    randomName.names.get2();
    randomName.names.get3();
    

    或者!

    又或者!

    然后或者!

    你可以指定每个字的五行哦!

    什么意思呢?比如你想给孩子起个名,然后孩子命里五行缺金,那么就可以:

    randomName.names.get2("金金");
    

    然后你就可能得到一个『紫铨』,两个字都是属金的。那么如果你孩子姓李,就叫李紫铨;如果孩子姓王,就叫王紫铨;如果姓爱新觉罗,那么就叫爱新觉罗·紫铨。

    有木有想给我装得这个逼打个 82 分呢?剩下的就交给 666 吧。(ง •̀_•́)ง

    Nomnom

    这个包是用来解析命令行参数的。虽然市面上有挺多别的的,比如 commander 等,不过我还是最习惯 nomnom,用称手了就不想换了。

    虽然它的 GitHub Repo 下面有这么一段话。

    Nomnom is deprecated. Check out https://github.com/tj/commander.js, which should have most, if not all of the capability that nomnom had. Thank you!

    不过再怎么说 nomnom 也是当年 substack 大神推荐的啊。(ಡωಡ)

    Colorful

    这个包是用来上色的。

    毕竟五行是有颜色的哇。

    const color = require("colorful");
    console.log(color.red("(*/∇\*)"));
    

    那么在你的终端就好看到一个红色的 (*/∇\*)

    Is Chinese

    用来判断是不是中文的包。

    作为一个起名的命令行程序,你总得好好传参才行吧,总不能你随便传个咸鸭蛋🐣我也好好处理吧。

    于是就用 is-chinese 来判断某个字符串是不是纯中文。

    这个包是由前阿里小伙伴, CNode 站长唐少写的。

    用起来也很简单,只要 isChinese("什么你要判断什么") 就可以了。

    集合

    $ npm install --save -d chinese-random-name
    $ npm install --save -d nomnom
    $ npm install --save -d colorful
    $ npm install --save -d is-chinese
    

    开工

    其结果在这里

    解析命令行参数

    首先效果是这样的:

    $ hua --help
    
    Usage: hua [options]
    
    Options:
    -p PREFIX, --prefix PREFIX          to specify a prefix.
    -s SUFFIX, --suffix SUFFIX          to specify a suffix.
    -5 WUXING, --five-elements WUXING   the file elements (Wuxing) of huaming.
    -c COUNT, --count COUNT             the count of huaming  [10]
    

    使用者可以自己想一个前缀或者后缀,然后自定义(或者也可以不指定)两个字的五行,以及指定一次性生成多少个花名。

    比如想要生成以 字为前缀的花名,就可以 $ hua --prefix 龙,得到结果可以是这样的:

    * 龙幼
     * 龙巡
     * 龙躬
     * 龙仇
     * 龙锤
     * 龙镒
     * 龙拾
     * 龙央
     * 龙些
     * 龙悠
    

    如果想两个字分别所属金和谁,就可以 $ hua --five-elements 金水 来起花名:

    * 倩娥
     * 雀效
     * 黍棓
     * 姹溶
     * 馨沙
     * 宫闲
     * 裕混
     * 俗封
     * 绸娥
     * 瑞淦
    

    想要得到这样一个命令行参数,我们可以用 nomnom 来解决。

    var opts = require("nomnom")
        .script("hua")
        .option("prefix", {
            abbr: "p",
            help: "to specify a prefix.",
            metavar: "PREFIX"
        })
        .option("suffix", {
            abbr: "s",
            help: "to specify a suffix.",
            metavar: "SUFFIX"
        })
        .option("five-elements", {
            abbr: "5",
            help: "the file elements (Wuxing) of huaming.",
            metavar: "WUXING"
        })
        .option("count", {
            abbr: "c",
            help: "the count of huaming",
            metavar: "COUNT",
            default: 10
        })
        .parse();
    

    上面的这段代码分别指定了脚本名为 hua,然后指定了 prefix / suffix / five-elementscount 四个参数,并把解析好的参数赋值给 opts 变量。

    由于我希望这个包在通常的 Node.js 下都可以跑,所以没有用 let 之类的东西。

    花名类

    接下去要写一个花名类,这个类不只是可以在 CLI 之中使用,也可以让别人作为一个包来引入。然后实际上这个类就是要对 chinese-random-name 进行一个封装。

    构造函数

    var Hua = function(options) {
        this.options = options;
    
        // Do something...
    };
    

    首先这个 options 就是之前由 nomnom 解析出来的参数,当然有些参数是可选的。

    接下去我们要在构造函数也就是 Hua 里面格式化前缀或者后缀(如果有的话),将他们弄成只有一个汉字的格式。

    if(options.prefix) {
        options.prefix = options.prefix[0];
        if(!isChinese(options.prefix)) delete options.prefix;
    }
    
    if(options.suffix) {
        options.suffix = options.suffix[0];
        if(!isChinese(options.suffix)) delete options.suffix;
    }
    

    前后缀弄好之后要对五行进行分析了。

    如果有前后缀那么忽略五行参数。

    if(options.prefix && options.suffix) {
        delete options["file-elements"];
    }
    

    如果有前缀,那么忽略传进来的五行的第一个五行;如果有后缀那么忽略第二个字的五行。

    var wuxing = "金木水火土";
    
    .
    .
    .
    
    } else if(options.prefix) {
        options["five-elements"] = options["five-elements"].substr(1, 1);
        if(-1 === wuxing.indexOf(options["five-elements"])) {
            delete options["five-elements"];
        }
    } else if(options.suffix) {
        options["five-elements"] = options["five-elements"].substr(0, 1);
        if(-1 === wuxing.indexOf(options["five-elements"])) {
            delete options["five-elements"];
        }
    }
    

    如果前后缀都没有,那么要格式化一下该参数,使其仅剩两个有效的五行汉字。

    } else {
        options["five-elements"] = options["five-elements"].substr(0, 2).split("");
        for(var i = 0; i < options["five-elements"].length; i++) {
            // 如果是无效五行或者冰没有这个字的话,随机一个五行出来
            if(-1 === wuxing.indexOf(options["five-elements"][i])) {
                options["five-elements"][i] = wuxing[Math.floor(Math.random() * 5)];
            }
        }
    
        // 字数不够,随机来凑
        while(options["five-elements"].length < 2) {
            options["five-elements"].push(wuxing[Math.floor(Math.random() * 5)]);
        }
    
        options["five-elements"] = options["five-elements"].join("");
    }
    

    以上的这些逻辑都写在构造函数里面,如果想要完整的构造函数可以看 huahua.js 文件。

    生成一个花名

    生成一个花名其实就是调用 randomName.names.get 系列函数们了。

    • 有前后缀:直接返回前缀加后缀。
    • 有前缀:返回前缀加 get1
    • 有后缀:返回 get1 加后缀。
    • 没有前后缀:直接返回 get2

    注意:以上情况都会传进(哪怕是 undefined)五行参数。

    所以 generateOne 函数长这样

    Hua.prototype.generateOne = function() {
        if(this.options.prefix && this.options.suffix) {
            return this.options.prefix + this.options.suffix;
        }
    
        if(this.options.prefix) {
            debug(this.options["five-elements"]);
            return this.options.prefix + randomName.names.get1(this.options["five-elements"]);
        }
    
        if(this.options.suffix) {
            debug(this.options["five-elements"]);
            return randomName.names.get1(this.options["five-elements"]) + this.options.suffix;
        }
    
        return randomName.names.get2(this.options["five-elements"]);
    };
    

    生成 Count 个花名

    还记得 CLI 的 count 参数么?因为为了方便,我们可以批量生成花名,所以就需要生成 Count 个花名的函数了。

    实际上就是一个循环调用 generateOne 的函数而已。

    Hua.prototype.generate = function(count) {
        if(!count) count = this.options.count || 10;
    
        var result = [];
        for(var i = 0; i < count; i++) {
            result.push(this.generateOne());
        }
        return result;
    };
    

    CLI 文件

    刚刚那个 nomnom 解析就在这个文件里面,然后接下去就是实例化一个 Hua 对象,然后生成 count 个花名。

    var hua = new Hua(opts);
    var result = hua.generate();
    

    最后把花名输出来就好了。

    for(var i = 0; i < result.length; i++) {
        console.log(" * " + result[i]);
    }
    

    桥豆麻袋!

    说好的五行颜色呢?!

    好像是的哦,我们要在输出之前给 result 上个色儿。

    遍历 result 里面的花名每个字,获取它的五行属性,然后涮上色儿。

    chinese-random-name 暴露了字典中每个字的五行属性,只需要赋值一下就好了。

    var dict = require("chinese-random-name").names.dict;
    

    然后逐一对比。最后对应金木水火土的颜色值分别为:

    var definedColors = [
        220, 83, 26, 197, 59
    ];
    

    220 为黄色,代表金; 83 为绿色,代表木; 26 蓝色代表水; 197 红色代表火; 59 灰色代表土。

    如果那个字无法找到属性,则不上色,保持默认。

    result = result.map(function(name) {
        var withColor = "";
    
        for(var i = 0; i < 2; i++) {
            for(var j = 0; j < wuxing.length; j++) {
                var wx = wuxing[j];
                if(wx === " ") {
                    withColor += name[i];
                    break;
                }
    
                if(dict[wx].indexOf(name[i]) !== -1) {
                    var color = new Color(name[i]);
                    color.fgcolor = definedColors[j];
                    withColor += color.toString();
                    break;
                }
            }
        }
    
        return withColor;
    });
    

    至此我们的 CLI 就写好了,最后别忘了在 hua 这个 CLI 文件顶部加上一句话。

    #!/usr/bin/env node
    

    这代表到时候如果要 ./hua 的时候这个脚本是用 Node.js 来跑的。

    收拾

    本来想好好写篇起花名的牢骚,结果不知不觉写成了给初心者看的初级教程了,泪目 ( •̥́ ˍ •̀ू )

    不嫌弃的就这么看看吧。

    最后这里给出我写好的这个 hua 程序。

    $ [sudo] npm install -g huaming
    

    然后就能在命令行下面跑了,跑法上面几章有介绍过。它的 Repo 在这里

    最后希望这个包在你们起花名的时候还真有那么一丢丢的用处。

    18 条回复    2016-02-25 17:50:22 +08:00
    miyuki
        1
    miyuki  
       2016-02-24 16:20:21 +08:00
    欧金金
    XadillaX
        2
    XadillaX  
    OP
       2016-02-24 16:21:57 +08:00
    @miyuki shenmegui
    messyidea
        3
    messyidea  
       2016-02-24 16:22:43 +08:00
    @miyuki 污!
    VmuTargh
        4
    VmuTargh  
       2016-02-24 16:23:39 +08:00
    什么鬼,果然林子大了什么轮子都有 999999999999999999
    XadillaX
        5
    XadillaX  
    OP
       2016-02-24 16:26:25 +08:00
    @miyuki -。 - 太污了
    yongzhong
        6
    yongzhong  
       2016-02-24 16:35:33 +08:00
    @miyuki 欧芒果
    XadillaX
        7
    XadillaX  
    OP
       2016-02-24 16:51:41 +08:00
    感觉你们的点是不是都歪了 -。 -
    AstroProfundis
        8
    AstroProfundis  
       2016-02-24 17:01:37 +08:00
    233333333333333333333333333333
    elya
        9
    elya  
       2016-02-24 17:21:38 +08:00
    wuli 滔滔
    jkjoke
        10
    jkjoke  
       2016-02-24 17:22:51 +08:00
    @miyuki 奇库比
    XadillaX
        11
    XadillaX  
    OP
       2016-02-24 17:29:14 +08:00
    @jkjoke 你们都好污,纯洁的我才不知道什么意思呢
    kslr
        12
    kslr  
       2016-02-24 19:17:54 +08:00
    @XadillaX
    @elya
    @jkjoke
    这究竟是啥意思啊
    la0wei
        13
    la0wei  
       2016-02-24 23:55:08 +08:00
    这么麻烦,找个国内页游,创建人物不是有自动起名的功能吗?随机个顺眼的。
    XadillaX
        14
    XadillaX  
    OP
       2016-02-24 23:56:55 +08:00 via Android
    @la0wei 很大程度那些花名已经有了😂
    SlipStupig
        15
    SlipStupig  
       2016-02-25 01:09:36 +08:00
    @XadillaX 之前公司为了造假数据做了一个这个玩意原理很简单
    1.先整理出百家姓
    2.整理出形容词、自然风景名称、天干地支
    产生算法:
    1.根据百家姓权重进行随机产生姓
    2.然后根据时间产生名字

    于是就出现了一些不错的名字:
    诸葛奔雷 司马如风 张壬午 李江南,哈哈哈
    anyforever
        16
    anyforever  
       2016-02-25 09:41:13 +08:00
    @SlipStupig 哈哈
    sobigfish
        17
    sobigfish  
       2016-02-25 17:17:45 +08:00
    不错 感谢 社交 app 有个花名也不错
    guotie
        18
    guotie  
       2016-02-25 17:50:22 +08:00
    尼欧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2803 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 11:41 · PVG 19:41 · LAX 03:41 · JFK 06:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.