【JavaScript】数秘術への誘い

# ※注意※

筆者は数秘術については初心者なので、計算や数字の意味などに誤りが含まれるかもしれません。ご指摘いただければありがたいです。
※2019/11/09 タイトル変更。
※2019/12/08 計算式の修正 先天数の計算で不具合があったため、評価を先に行うように変更しました。
※2019/12/08 出力メッセージをシンプルに
※2020/02/08 計算式を修正
※2020/02/11 マスターナンバーに関する調査を追記

# 本項の目的
・数秘術に触れる
・数秘術をロジックで表現する。


# 数秘術とは

数秘術（Numerology）
生年月日や姓名を数字に置き換えて、計算を施し、最後に現れた数字を評価することによって性格や運勢を占う占術。
1~9の一桁の数値と、マスターナンバーと呼ばれるゾロ目11、22などに対応する意味があり、ここから結果を導き出す。どの数を含むか、また計算方式などは流派によって異なるので、自分に合うものを選ぶ。

Wikipedia:数秘術
https://ja.wikipedia.org/wiki/%E6%95%B0%E7%A7%98%E8%A1%93

ピタゴラスが創始者と言われるだけあり占いのオペレーションは論理的に簡潔していて、
スピリチュアルなイメージの占いを敬遠している人でもとっかかりやすい。

# 計算方法について

数値の意味、計算方法などなどは流派によって異なるようです。
本項では計算方法や数値の意味などは後述の動画チャンネルを参考にしています。

### 先天数
先天的にある数　能力・資質

生年月日の”日”のみの桁毎の数値を足す。
足した結果が2桁になる場合は1桁になるまで計算を繰り返す。
ただしマスターナンバー（11，22，33）が計算の途中で出現した場合はそれを採用する。
例：
02日　→　先天数：2
19日　→　1+9　→　10　→　1+0　→　先天数：1
11日　→　先天数：11
29日　→　2+9　→　先天数：11　

### 後天数
後天的に備わる数　メインの性格

生年月日の”年月日”の桁毎の数値を足す。
計算方法は先天数と同じ。
例：
1998年06月24日　→　1+9+9+8+0+6+2+4　→　39　→　3+9　→　12　→　1+2　→　後天数：3
2001年09月09日　→　2+0+0+1+0+9+0+9　→　21　→　2+1　→　後天数：3

### 尊敬数
好きになりやすい相手のもつ数　性別関係ない

生年月日の”月日”の桁毎の数値を足す。
計算方法は先天数と同じ。

#### ※先天数・後天数・尊敬数の数値の意味※
1・・・先導：リーダータイプの先導者。
2・・・母親：サポートタイプの母親役。
3・・・子供：隠しごとのできない子供。
4・・・堅実：真面目にコツコツ堅実な人。
5・・・自由：自由を愛する自由人。
6・・・仲間：仲間思いのやさしい人。
7・・・職人：独特な道を持っている職人。
8・・・調整：コミュ力の高いバランス調整役。
9・・・平和：頭の回転が速い優等生。
11・・・人の心が読める不思議ちゃん。
22・・・カリスマ絶対王者。
33・・・仏の心をもつ究極的ドＭ、宇宙人。

### ※例外※
上述の後天数の計算結果に２，４，６のいずれかが出た場合、
年月日それぞれを計算してから合算する。
例：
1996年09月06日　→　1+9+9+6+0+9+0+6　→　40　→　4+0　→　4
1996年09月06日　→　(1+9+9+6)+(0+9)+(0+6)　→　(2+5)+9+6　→　7+9+6　→　22　→　後天数：22

#本題
たいしたこともなく
数秘術をJavascriptで表現します。
重要なのは計算式のところだけ。

```javascript:ソースコード全文

javascript:(function(w){
  var fates = {
    "11":"人の心が読める不思議ちゃん",
    "22":"カリスマ絶対王者",
    "33":"仏の心をもつ究極的ドＭ宇宙人",
    "1":"リーダータイプの先導者",
    "2":"サポートタイプの母親役",
    "3":"隠しごとのできない子供",
    "4":"真面目にコツコツ堅実な人",
    "5":"自由を愛する自由人",
    "6":"仲間思いのやさしい人",
    "7":"独特な道を持っている職人",
    "8":"コミュ力の高いバランス調整役",
    "9":"頭の回転が速い優等生"
  };
  var wheel = function (x,obj) {
    if(Object.keys(obj).includes(x)) return x;
    var t=0;
    (""+x).split("").forEach(function(s){t+=+s;});
    t = ""+t;
    return wheel(t, obj);
  };
  var msg = [];
  var birth = w.prompt("生年月日を入力してください。\n（区切り文字なし 例：19981205）", "");
  if (isNaN(birth)||birth.length!=8) return alert("8桁の数値を入力してください");
  var by = birth.substring(0,4);
  var bm = birth.substring(4,6);
  var bd = birth.substring(6,8);
  var key;
  key=wheel(bd, fates);
  msg.push("先天数：" + key + " " + fates[key]);
  key=wheel(by+bm+bd, fates);
  if(["2","4","6"].includes(key)) {
    key=wheel(wheel(by,fates)+wheel(bm,fates)+wheel(bd,fates),fates);
  }
  msg.push("後天数：" + key + " " + fates[key]);
  alert(msg.join("\n"));
})(window);

```


ソースコードの意味はそれぞれ

```javascript
  // 数字と意味を紐付けるオブジェクト
  var fates = {
    "11":"人の心が読める不思議ちゃん",   // マスターナンバー
    "22":"カリスマ絶対王者",            // マスターナンバー
    "33":"仏の心をもつ究極的ドＭ宇宙人", // マスターナンバー
    "1":"リーダータイプの先導者",
    "2":"サポートタイプの母親役",
    "3":"隠しごとのできない子供",
    "4":"真面目にコツコツ堅実な人",
    "5":"自由を愛する自由人",
    "6":"仲間思いのやさしい人",
    "7":"独特な道を持っている職人",
    "8":"コミュ力の高いバランス調整役",
    "9":"頭の回転が速い優等生"
  };
```

```javascript
  // 計算式
  var wheel = function (x,obj) {
    if(Object.keys(obj).includes(x)) return x;// fatesオブジェクトのキーに含まれていればそれ以上計算しない
    var t=0;
    (""+x).split("").forEach(function(s){t+=+s;});// 暗黙キャストで文字列⇔数値変換しつつ、数値文字列をバラバラにして加算する。
    t = ""+t;
    return wheel(t, obj);// まだ計算できるうちは再帰的に計算を繰り返す
  };
```

```javascript
  // メッセージ作成
  var msg = [];
  var birth = w.prompt("生年月日を入力してください。\n（区切り文字なし 例：19981205）", "");
  if (isNaN(birth)||birth.length!=8) return alert("8桁の数値を入力してください");
  var by = birth.substring(0,4);
  var bm = birth.substring(4,6);
  var bd = birth.substring(6,8);
  var key;
  key=wheel(bd, fates);
  msg.push("先天数：" + key + " " + fates[key]);
  key=wheel(by+bm+bd, fates);
  if(["2","4","6"].includes(key)) {
    key=wheel(wheel(by,fates)+wheel(bm,fates)+wheel(bd,fates),fates);
  }
  msg.push("後天数：" + key + " " + fates[key]);

  alert(msg.join("\n"));
```

### 使い方
・ソースコード全文をブックマークレットとして登録する。
（urlのところにjavascript:からはじまるソース全文を貼り付けて保存。下図はChromeの例）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75797/8bd3910d-fb04-b493-deea-e5fd9f14b0b5.png)

・ブックマークレットをクリックすると生年月日、占いたい年月日の入力ダイアログが順次出てくるのでそれぞれ入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75797/a7410ced-0d5b-e576-be52-a11d6bf39020.png)

・OKを押すと先天数と後天数が表示されます。

# おまけ
運勢を計算できるようにしたもの

```javascript

(function(w){
  var fates = {
    "11":"人の心が読める不思議ちゃん",
    "22":"カリスマ絶対王者",
    "33":"仏の心をもつ究極的ドＭ宇宙人",
    "1":"リーダータイプの先導者",
    "2":"サポートタイプの母親役",
    "3":"隠しごとのできない子供",
    "4":"真面目にコツコツ堅実な人",
    "5":"自由を愛する自由人",
    "6":"仲間思いのやさしい人",
    "7":"独特な道を持っている職人",
    "8":"コミュ力の高いバランス調整役",
    "9":"頭の回転が速い優等生"
  };
  var fortunes = {
    "1":"始める",
    "2":"人間関係の",
    "3":"創造の",
    "4":"土台固めをする",
    "5":"変化の",
    "6":"育成の",
    "7":"技術を高める",
    "8":"達成の",
    "9":"選択の"
  };
  var wheel = function (x,obj) {
    if(Object.keys(obj).includes(x)) return x;
    var t=0;
    (""+x).split("").forEach(function(s){t+=+s;});
    t = ""+t;
    return wheel(t, obj);
  };
  var msg = [];
  var birth = w.prompt("生年月日を入力してください。\n（区切り文字なし 例：19981205）", "");
  if (isNaN(birth)||birth.length!=8) return alert("8桁の数値を入力してください");
  var by = birth.substring(0,4);
  var bm = birth.substring(4,6);
  var bd = birth.substring(6,8);
  var today = w.prompt("いつの運勢を占いますか？\n（区切り文字なし 例：19981205）", (function(d){
    return `${d.getFullYear()}${(d.getMonth()+1).toString().padStart(2, '0')}${d.getDate().toString().padStart(2, '0')}`;
  })(new Date()));
  if (isNaN(today)||today.length!=8) return alert("8桁の数値を入力してください");
  var ty = today.substring(0,4);
  var tm = today.substring(4,6);
  var td = today.substring(6,8);
  var bb = tm+td < bm+bd ? 1 : 0;
  var key;
  key=wheel(bd, fates);
  msg.push("先天数："+key+" "+fates[key]);
  key=wheel(by+bm+bd, fates);
  if(["2","4","6"].includes(key)) {
    key=wheel(wheel(by,fates)+wheel(bm,fates)+wheel(bd,fates),fates);
  }
  msg.push("後天数："+key+" "+fates[key]);
  var resp;
  key=resp=wheel(bm+bd, fates);
  msg.push("尊敬数："+key+" "+fates[key]);
  var fy = wheel(ty+(resp-bb+""), fortunes);
  var fm = wheel(fy+tm, fortunes);
  var fd = wheel(fm+td, fortunes);
  msg.push((key=fy) + " " + fortunes[key] + "年");
  msg.push((key=fm) + " " + fortunes[key] + "月");
  msg.push((key=fd) + " " + fortunes[key] + "日");

  alert(msg.join("\n"));
})(window);
```

#おまけ２
マスターナンバーのレアリティについて
下記の関数を用いて検証した。

### 調査関数

```js

(function(w){
  var fates = {
    "11":"人の心が読める不思議ちゃん",
    "22":"カリスマ絶対王者",
    "33":"仏の心をもつ究極的ドＭ宇宙人",
    "1":"リーダータイプの先導者",
    "2":"サポートタイプの母親役",
    "3":"隠しごとのできない子供",
    "4":"真面目にコツコツ堅実な人",
    "5":"自由を愛する自由人",
    "6":"仲間思いのやさしい人",
    "7":"独特な道を持っている職人",
    "8":"コミュ力の高いバランス調整役",
    "9":"頭の回転が速い優等生"
  };
  var wheel = function (x,obj) {
    if(Object.keys(obj).includes(x)) return x;
    var t=0;
    (""+x).split("").forEach(function(s){t+=+s;});
    t = ""+t;
    return wheel(t, obj);
  };
  
  var date8 = function(d){
    return `${d.getFullYear()}${(d.getMonth()+1).toString().padStart(2, '0')}${d.getDate().toString().padStart(2, '0')}`;
  };
  
  var datelist = (function(s,e){
    var list = [];
    for(var d = s; d < e; d.setDate(d.getDate()+1)) {
      list.push(date8(d));
    }
    return list;
  })(new Date("1990-1-1"),new Date("2010-12-31"));
  
  datelist.forEach(function(birth){

    var by = birth.substring(0,4);
    var bm = birth.substring(4,6);
    var bd = birth.substring(6,8);
    var senten,kouten,sonkei;
    senten=wheel(bd, fates);
    kouten=wheel(by+bm+bd, fates);
    if(["2","4","6"].includes(kouten)) {
      kouten=wheel(wheel(by,fates)+wheel(bm,fates)+wheel(bd,fates),fates);
    }
    sonkei=wheel(bm+bd, fates);
    console.log(birth+": "+senten+"-"+kouten+"-"+sonkei);
  
  });
})(window);
```

【結果１】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75797/9151f8c4-f7ef-747e-837a-dbc4bbb127cc.png)

調査は1990年～2010年の21年間（2000±10年）を対象に実施した。
20年間の各日付について先天数、後天数、尊敬数を導出し、先天数後天数のマスターナンバーをカウントした（結果１：7000行超におよぶため割愛）。
この期間の結果のみをみて判断することはできませんが、傾向として
・マスターナンバー１１は比較的出やすく、全期間にわたってまんべんなく存在する。
・マスターナンバー２２、３３は出現に偏りが見られる。
　特に３３は２０００年以降の出現率が極端に下がる。

マスターナンバーの出現率（先天数、後天数いずれかにマスターナンバーを持つ誕生日を集計）は
(740+1245)/7670　≒　26%（およそ4人に1人）

先天数、後天数ともにマスターナンバーの出現率は
120/7670　≒　1.6%（100人に1～2人）

先天数、後天数、尊敬数すべてにマスターナンバーを持つ誕生日は結果２の6件のみ。

【結果２】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75797/a3250a6c-789a-b6cb-08cf-e18e1aced666.png)





# 参考
S.S.Channnel　セフィラ・スゥの占いちゃんねる
https://www.youtube.com/channel/UCHKJMmZJjLpkjZDPp_miSzg
占い師を生業とするVTuber（＝FTuber）として、YouTubeで活動されています。
占いによるお悩み相談、占い講座、ゲームのプレイ配信、Live2D開発などなど幅広い活動をされています。占いについて詳しく解説されているアーカイブなどもありますのでご興味あればぜひ