星野しずるの語彙を差し替えられたら面白いだろうなと思ったんだ

表題がすべて

そこで、差し替えられるようにしました。

Baboon demo

使い方

以下のような形式のGoogleスプレッドシートを用意します。

スプレッドシート サンプル

用意したスプレッドシートを「ファイル > ウェブに公開」からカンマ区切り形式(.csv)で公開し、表示されているURLを上に貼ったリンク内の「Spreadsheet URL」というところにコピペします。

本家犬猿はもともとあらかじめ登録されている構文をランダムに選択し、構文に語彙を当てはめることで短歌を生成しています。今回作成したクローン犬猿では本家犬猿の構文を流用しているため、どの構文を引いても完全な短歌を生成するためには、スプレッドシートには所定の語彙項目を少なくとも1件以上登録しておく必要があります。

語彙項目は以下に挙げるものが必要です。各語彙項目がどんなものかは実際のスプレッドシートの例を見て察してください。

  • 名詞・・・2,3,4,6モーラの語彙
  • 修飾部・・・3,4,5,7モーラの語彙
  • 述部・・・3,4,5,6,7モーラの語彙

サイトの挙動について

「Spreadsheet URL」に有効なスプレッドシートのURLを貼るたびごとに指定されたスプレッドシートから語彙を読み込みます。デフォルトではすでに読み込まれている語彙と結合(concat)するかたちで語彙を保持します。「すでにある語彙とマージしない」にチェックすると新しくURLを貼るたびごとに読み込まれている語彙をスプレッドシートの語彙に差し替えます。

技術的な話

犬猿のモジュール化

本家犬猿のスクリプトはいかんせん10年近く前に書かれたものであり、お世辞にもモダンな雰囲気ではありません。以下に画像で引用しますが、こんな具合です。

権利的なあれもあってそのまま使うことはできないので、構文とデフォルトの語彙だけを拝借して、ES6に書き直しました。

import _  from "underscore"  
import { include } from "underscore.string"  

export default class Baboon {  
    constructor (vocab, recipe = null, hashtag = ["名詞", "修飾部", "述部"]) {  
        this.hashtag = {  
            m: hashtag[0],  
            s: hashtag[1],  
            j: hashtag[2]  
        }  
        this.vocab = _.isArray(vocab) ? vocab : []  
        if (_.isNull(recipe)) {  
            this.recipe = [  
                "m4+の+m3+j4+s5+s4+m2+j6+m2",  
                "s5+m3+の+m2+j6+m3+j4+s4+m3",  
                "m4+j5+s3+m4+は+m6+の+m3+j4",  
                "m4+j5+s3+m4+j4+s4+m4+j3",  
                "m4+j4+m3+の+m4+j5+s3+m4+j3",  
                "s5+m6+j6+s3+m3+j6+m2",  
                "m4+j5+s3+m4+j8+s5+m2",  
                "m4+j4+m3+j6+s7+s3+m4",  
                "s5+m6+j6+s7+m2+j5",  
                "s5+m2+j5+m4+は+s4+m2+j8",  
                "s5+s7+m2+j3+m6+j8",  
                "m2+j3+s3+m3+j6+m2+の+m3+j8",  
                "m4+j6+m2+ +s5+m2+j5+s3+m4",  
                "s5+m3+j4+s5+m3+の+m2+j5+m3",  
                "m4+は+m6+の+m2+j3+s4+m2+j6+m2",  
                "m4+j4+s4+m4+は+s7+m4+j3",  
                "s5+s4+m2+の+m4+j5+s3+m3+j4",  
                "s5+m4+j3+m4+j4+s4+m4+j3",  
                "m4+j8+s5+m3+の+m2+j4+m4",  
                "s5+m2+の+m3+j6+m6+は+s4+m3"  
            ]  
        } else {  
            this.recipe = _.isArray(recipe) ? recipe : []  
        }  
    }  
    pickWord ({ type, mora }) {  
        return _.chain(this.vocab)  
            .filter(el => { return el.mora === mora })  
            .filter(el => { return el.type === type })  
            .sample(1)  
            .pluck("word")  
            .value()  
    }  
    parseRecipe (str) {  
        const recipe = str.split("+")  
        return _.chain(recipe)  
            .map(el => {  
                if (el.match(/^[msj]+\d/)) { // console.log(el)  
                    let type = this.hashtag["m"]  
                    if (include(el, "s")) { type = this.hashtag["s"] }  
                    if (include(el, "j")) { type = this.hashtag["j"] }  
                    return {  
                        type: type,  
                        mora: _.last(el.split(""))  
                    }  
                } else { // console.log(el)  
                    return el  
                }  
            })  
            .value()  
    }  
    create () {  
        const recipe = _.sample(this.recipe)  
        return _.chain(this.parseRecipe(recipe))  
            .map(el => {  
                if (_.isObject(el)) {  
                    return this.pickWord(el)  
                } else {  
                    return el  
                }  
            })  
            .reduce((prev, el) => { return `${prev}${el}` }, "")  
            .value()  
    }  
}  

使う語彙を動的に差し替えたかったので、このクラスをcomputedのなかでnewしています。

CSVの読み込み

Gson - Open Source Google Sheets to JSONを使っています。これは実際にはNOWに建てたエンドポイントのなかでCSVをaxios.get()してcsvtojsonで変換しているだけなのですが、なんとなく便利なので使っています。