Class: FourPillarsLogic

Inherits:
Object
  • Object
show all
Defined in:
lib/four-pillars.rb

Constant Summary collapse

JIKKAN =
["","","","","","","","","",""]
JYUNISHI =
["","","","","","","","","","","",""]
TSUHENSEI =
["比肩","劫財","食神","傷官","偏財","正財","偏官","正官","偏印","印綬"]
JYUNIUNSEI =
["長生","沐浴","冠帯","建禄","帝旺","","","","","","",""]
GOGYO =
["","","","",""]
KUUBOU =
["戌亥","申酉","午未","辰巳","寅卯","子丑"]
SHUGOSHIN =
[["丁庚丙","丙戊","壬戊","甲庚","丙甲","丙甲戊","丁甲戊","丙壬","戊丙","丙辛"],
["丁庚甲","丙甲","甲壬","甲庚","丙甲","丙甲","丙甲丁","丙壬甲","丙甲","丙壬戊"],
["丙癸","丙癸","壬庚","甲庚","丙甲癸","丙戊甲","丙甲戊","己壬庚","庚丙戊","辛丙"],
["庚丁丙","丙癸","壬庚己","庚甲","丙甲癸","甲丙癸","丁甲庚","壬甲","戊辛","庚辛"],
["庚丁壬","癸丙","壬甲","甲庚","甲丙癸","丙甲癸","甲丁","壬甲","甲庚","丙甲辛"],
["癸庚丁","癸辛","壬庚","甲庚","甲癸丙","癸丙辛","壬戊丙","壬癸甲","壬庚辛","辛壬"],
["癸丁庚","癸丙","壬庚","壬庚","壬甲丙","癸丙辛","壬癸庚","壬癸己","癸庚辛","辛壬"],
["","癸丙甲","壬庚","甲壬","癸丙甲","癸丙","丁甲","壬甲庚","辛甲","辛壬癸"],
["庚丁壬","丙癸","壬戊","甲庚丙","丙癸甲","丙癸","丁甲","壬甲","戊丁","丁甲"],
["庚丁丙癸","丙癸","","甲庚丙","丙癸","丙癸","丁甲丙","","甲庚","辛丙"],
["癸庚丁甲","癸辛甲","甲壬","甲庚","甲丙癸","甲丙","甲壬","壬甲","甲丙戊","辛甲癸"],
["癸丁丙戊","丙戊","甲戊庚","甲庚","甲丙","丙甲戊","丁甲丙","壬丙","戊丙庚","辛戊"]]
KANSHI_ARRAY =
kanshi_array
KANSHI_HASH =
kanshi_hash
JIKKAN_IN =
jikkan_in
JYUNISHI_IN =
JYUNISHI.reverse
JYUNIUNSEI_ENERGY =
jyuniunsei_energy

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(birth_dt, gender) ⇒ FourPillarsLogic

Returns a new instance of FourPillarsLogic.



121
122
123
124
125
126
127
# File 'lib/four-pillars.rb', line 121

def initialize(birth_dt,gender)
  @birth_dt = birth_dt.map {|v| v.to_i }
  @gender = gender
  raise "Incorrect birth date: #{birth_dt}" if @birth_dt.count != 5
  raise "Gender must be m,f or o(other): #{gender}" unless ['o','m','f'].include? @gender
  raise "Year must be larger than 1863" if @birth_dt[0] < 1864
end

Instance Attribute Details

#birth_dtObject (readonly)

生年月日時間, 性別(大運の向きに使用)



119
120
121
# File 'lib/four-pillars.rb', line 119

def birth_dt
  @birth_dt
end

#genderObject (readonly)

生年月日時間, 性別(大運の向きに使用)



119
120
121
# File 'lib/four-pillars.rb', line 119

def gender
  @gender
end

Class Method Details

.jikkan_inObject

陰干通表



46
47
48
49
50
51
52
53
# File 'lib/four-pillars.rb', line 46

def self.jikkan_in
  j = [nil] * 10
  [0,2,4,6,8].each do |i|
    j[i] = JIKKAN[i+1]
    j[i+1] = JIKKAN[i]
  end
  return j
end

.jyuniunsei(j_day, j_src) ⇒ Object

日柱の十干, 十二支



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/four-pillars.rb', line 99

def self.jyuniunsei(j_day,j_src) # 日柱の十干, 十二支
  j = JIKKAN.index(j_day)
  if j % 2 == 0 # 陽
    jyunishi = JYUNISHI
  else # 陰
    jyunishi = JYUNISHI_IN
  end
  offset = [1,7,10,10,10,10,7,1,4,4][j] # 十二運表より求めたオフセット
  ji = jyunishi.index(j_src)
  JYUNIUNSEI[(ji + offset) % 12]
end

.jyuniunsei_energyObject

十二運星エネルギー



58
59
60
61
62
63
64
65
# File 'lib/four-pillars.rb', line 58

def self.jyuniunsei_energy
  h = {}
  energies = [9,7,10,11,12,8,4,2,5,1,3,6]
  12.times do |i|
    h[JYUNIUNSEI[i]] = energies[i]
  end
  return h
end

.kanshi_arrayObject

60干支表



24
25
26
27
28
29
30
31
32
# File 'lib/four-pillars.rb', line 24

def self.kanshi_array
  a = []
  60.times do |i|
    j1 = FourPillarsLogic::JIKKAN[i%10]
    j2 = FourPillarsLogic::JYUNISHI[i%12]
    a += [j1+j2]
  end
  return a
end

.kanshi_hashObject

60干支表



36
37
38
39
40
41
42
# File 'lib/four-pillars.rb', line 36

def self.kanshi_hash
  h = {}
  kanshi_array.each_with_index do |v,i|
    h[v] = i+1
  end
  return h
end

.load_setsuiriObject

年月の節入り日時 (注:時 = 時間 x 60 + 分)



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/four-pillars.rb', line 69

def self.load_setsuiri
  l = []
  h = {}
  open(__dir__+"/four-pillars-setsuiri.txt").each do |line|
    next if line.strip.empty? || line.start_with?("#")
    vs = line.split(",")
    if vs.count != 5 || vs[0].empty?
      puts "Invalid row: #{line}"
      next
    end
    vs.map! { |v| v.to_i }
    h[vs[0]*100+vs[1]] = [vs[2],vs[3]*60+vs[4]]
    l += [vs]
  end
  return h, l
end

.plus_jikkan?(jikkan) ⇒ Boolean

十干の陰陽 陽:true 陰:false

Returns:

  • (Boolean)


112
113
114
115
116
# File 'lib/four-pillars.rb', line 112

def self.plus_jikkan?(jikkan)
  i = JIKKAN.index(jikkan)
  raise "Invalid jikkan: #{jikkan}" if i.nil?
  return i % 2 == 0
end

.tsuhensei(j_day, j_src) ⇒ Object

通変星



88
89
90
91
92
93
94
95
96
97
# File 'lib/four-pillars.rb', line 88

def self.tsuhensei(j_day,j_src) # 日柱の十干、月柱または年柱の十干
  if plus_jikkan?(j_day) # 陽
    jikkan = JIKKAN
  else # 陰
    jikkan = JIKKAN_IN
  end
  t = jikkan.index(j_src) - jikkan.index(j_day)
  t += 10 if t < 0
  TSUHENSEI[t]
end

Instance Method Details

#days_of_current_monthObject

今月の日数



150
151
152
153
# File 'lib/four-pillars.rb', line 150

def days_of_current_month
  y,m,d,h,i = @birth_dt
  Date.new(y,m,1).next_month.prev_day.day
end

#days_of_previous_monthObject

前月の日数



144
145
146
147
# File 'lib/four-pillars.rb', line 144

def days_of_previous_month
  y,m,d,h,i = @birth_dt
  (Date.new(y,m,1) - 1).day
end

#equivalent_kanshi(only_jikkan = false) ⇒ Object



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/four-pillars.rb', line 374

def equivalent_kanshi(only_jikkan=false)
  if only_jikkan
    k = kanshi.map {|v| v[0] } # 日,月,年柱の十干
  else
    k = kanshi
  end
  if k[0] == k[1] && k[1] == k[2]
    return [[0,1],[0,2],[1,2]]
  elsif k[0] == k[1]
    return [[0,1]]
  elsif k[0] == k[2]
    return [[0,2]]
  elsif k[1] == k[2]
    return [[1,2]]
  else
    return []
  end
end

#gogyo_jikkanObject

五行(十干)



325
326
327
328
329
330
331
332
# File 'lib/four-pillars.rb', line 325

def gogyo_jikkan
  arr = []
  3.times do |i|
    j = JIKKAN.index(kanshi[i][0])
    arr += [(j % 2 == 0 ? "+" : "-") + GOGYO[j / 2]]
  end
  return arr
end

#gogyo_jyunishiObject

五行(十二支)



335
336
337
338
339
340
341
342
343
# File 'lib/four-pillars.rb', line 335

def gogyo_jyunishi
  arr = []
  gogyo_j = ["","","","","","","","","","","",""]
  3.times do |i|
    j = JYUNISHI.index(kanshi[i][1])
    arr += [(j % 2 == 0 ? "+" : "-") + gogyo_j[j]]
  end
  return arr
end

#inputObject

生年月日と性別



130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/four-pillars.rb', line 130

def input
  y,m,d,h,i = @birth_dt
  case @gender
  when 'm' then
    g = "男性"
  when 'f' then
    g = "女性"
  else
    g = ""
  end
  "#{y}#{m}#{d}#{h}#{i}分生 #{g}"
end

#jyuniunseiObject

十二運星



292
293
294
295
296
297
# File 'lib/four-pillars.rb', line 292

def jyuniunsei
  d = FourPillarsLogic::jyuniunsei(kanshi[0][0],kanshi[0][1])
  m = FourPillarsLogic::jyuniunsei(kanshi[0][0],kanshi[1][1])
  y = FourPillarsLogic::jyuniunsei(kanshi[0][0],kanshi[2][1])
  [d,m,y]
end

#jyuniunsei_energyObject

十二運星エネルギー



300
301
302
# File 'lib/four-pillars.rb', line 300

def jyuniunsei_energy
  jyuniunsei.map {|v| JYUNIUNSEI_ENERGY[v] }
end

#kanshiObject

干支(日,月,年)



200
201
202
203
204
205
206
207
208
209
210
# File 'lib/four-pillars.rb', line 200

def kanshi
  y,m,d,h,i = @birth_dt
  sd, st = setsuiri
  yd = y - 1864 # (till 1865.02.0?) = 甲子
  yd -= 1 if m < 2 || (m == 2 && d < sd) || (m == 2 && d == sd && h*60+i < st)
  md = (y - 1863) * 12 + (m - 12) # (till 1864.01.05) = 甲子
  md -= 1 if d < sd || (d == sd && h*60+i < st)
  dd = Date.new(y,m,d) - Date.new(1863,12,31) # 1923.10.18 = 甲子

  return [KANSHI_ARRAY[dd % 60],KANSHI_ARRAY[md % 60],KANSHI_ARRAY[yd % 60]]
end

#kanshi_as_numberObject

干支(数字)



213
214
215
# File 'lib/four-pillars.rb', line 213

def kanshi_as_number
  kanshi.map {|v| KANSHI_HASH[v] }
end

#know_setsuiri?Boolean

生年月に対する節入日時を知っているか? このメソッドがfalseを返す場合、干支、蔵干が仮の節入日で計算されています。

Returns:

  • (Boolean)


181
182
183
184
# File 'lib/four-pillars.rb', line 181

def know_setsuiri?
  y,m,d,h,i = @birth_dt
  SETSUIRI_HASH.include? y*100+m
end

#kuubouObject

空亡 = 天中殺



305
306
307
308
309
# File 'lib/four-pillars.rb', line 305

def kuubou
  k_day = (kanshi_as_number[0] - 1) / 10
  k_year = (kanshi_as_number[2] - 1) / 10
  [KUUBOU[k_day],KUUBOU[k_year]]
end

#nacchinObject

納音



405
406
407
408
409
410
411
412
413
414
415
# File 'lib/four-pillars.rb', line 405

def nacchin
  # 十干が同じで十二支が 沖 の関係にある
  v = []
  eq = equivalent_kanshi(true)
  eq.each do |e|
    k0 = kanshi[e[0]][1]
    k1 = kanshi[e[1]][1]
    v += [e] if on_distance?(k0,k1,6)
  end
  return v
end

#on_distance?(j1, j2, d = 6) ⇒ Boolean

Returns:

  • (Boolean)


393
394
395
396
# File 'lib/four-pillars.rb', line 393

def on_distance?(j1,j2,d=6)
  i = JYUNISHI.index(j1)
  return j2 == JYUNISHI[(i+d) % 12]
end

#ricchinObject

律音



399
400
401
402
# File 'lib/four-pillars.rb', line 399

def ricchin
  # 干支(十干・十二支)が同じ
  equivalent_kanshi(false)
end

#setsuiriObject

生年月に対応する節入り日時 ファイルに登録がない場合は、4日12時を返す



187
188
189
190
# File 'lib/four-pillars.rb', line 187

def setsuiri
  y,m,d,h,i = @birth_dt
  SETSUIRI_HASH[y*100+m] || [4,12*60]
end

#setsuiri?Boolean

生まれた日が節入日にあたる場合、true

Returns:

  • (Boolean)


193
194
195
196
197
# File 'lib/four-pillars.rb', line 193

def setsuiri?
  return false unless know_setsuiri?
  y,m,d,h,i = @birth_dt
  setsuiri[0] == d
end

#setsuiri_of_next_monthObject

翌月の節入日



168
169
170
171
172
173
174
175
176
177
# File 'lib/four-pillars.rb', line 168

def setsuiri_of_next_month
  y,m,d,h,i = @birth_dt
  if m == 12
    y += 1
    m = 1
  else
    m += 1
  end
  SETSUIRI_HASH[y*100+m] || [0,0]
end

#setsuiri_of_previous_monthObject

前月の節入日



156
157
158
159
160
161
162
163
164
165
# File 'lib/four-pillars.rb', line 156

def setsuiri_of_previous_month
  y,m,d,h,i = @birth_dt
  if m == 1
    y -= 1
    m = 12
  else
    m -= 1
  end
  SETSUIRI_HASH[y*100+m] || [0,0]
end

#shugoshinObject

守護神



346
347
348
349
350
351
# File 'lib/four-pillars.rb', line 346

def shugoshin
  # 日柱の十干と月柱の十二支
  x = JIKKAN.index(kanshi[0][0])
  y = JYUNISHI.index(kanshi[1][1])
  SHUGOSHIN[y][x].split("")
end

#shukumeiObject

宿命中殺



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/four-pillars.rb', line 354

def shukumei
  s = []
  t = kuubou # 天中殺 0:上段, 1:下段
  k = kanshi.map {|v| v[1] } # 日,月,年柱の干支
  if t[0].include? k[2]
    s += ["生年中殺"]
  end
  if t[0].include? k[1]
    s += ["生月中殺"]
  end
  if t[1].include? k[0]
    s += ["生日中殺"]
  end
  f = false
  f = true if kanshi_as_number.include? 11 #甲戌
  f = true if kanshi_as_number.include? 12 #乙亥
  s += ["日座中殺"] if f
  return s
end

#shukumei_daihankaiObject

宿命大半会



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/four-pillars.rb', line 418

def shukumei_daihankai
  # 十干が同じで十二支が三合会局の関係にある
  v = []
  eq = equivalent_kanshi(true)
  eq.each do |e|
    k0 = kanshi[e[0]][1]
    k1 = kanshi[e[1]][1]
    v += [e] if on_distance?(k0,k1,4)
  end
  eq.each do |e|
    k0 = kanshi[e[0]][1]
    k1 = kanshi[e[1]][1]
    v += [e] if on_distance?(k0,k1,8)
  end
  return v
end

#taiunObject

大運 [順行 or 逆行, year] or [nil,nil](if gender is not male nor female)



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# File 'lib/four-pillars.rb', line 436

def taiun
  return [nil,nil] unless ['m','f'].include? @gender
  k = gogyo_jikkan[2][0]
  t = @birth_dt[3] * 60 + @birth_dt[4] # 生まれた時間
  if (@gender == 'm' && k == "+") || (@gender == 'f' && k == '-')
    order = "順行"
    d = setsuiri[0] - birth_dt[2]
    if d > 0 # A 生まれた日が節入り前の場合 (節入り日―誕生日+1)÷3
      year = ((d + 1) / 3.0).round
    elsif d == 0 # 節入り日
      #〈順行〉節入時間「前」=1年  「後」=10年
      if t <= setsuiri[1]
        year = 1
      else
        year = 10
      end
    else # B 生まれた日が節入り後の場合  (誕生月の日数―誕生日+1+翌月の節入り日)÷3
      s = days_of_current_month - birth_dt[2] + 1 + setsuiri_of_next_month[0]
      year = (s / 3.0).round
    end
  else
    order = "逆行"
    if setsuiri?
      #〈逆行〉節入時間「前」=10年 「後」=1年
      if t < setsuiri[1]
        year = 10
      else
        year = 1
      end
    else
      year = (zokan_number / 3.0).round
    end
  end
  return [order,year]
end

#taiun_tableObject



472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
# File 'lib/four-pillars.rb', line 472

def taiun_table
  order,year = taiun
  return [] if order.nil?
  d = order == '順行' ? 1 : -1
  j_day = kanshi[0][0] # 日柱の十干
  k = kanshi_as_number[1] - 1 # 月柱の干支番号
  rows = []
  # [0,1,"癸亥","偏印","死",2]
  y1, y2 = 0, year
  8.times do |i|
    k_month = KANSHI_ARRAY[k] # 月柱の干支
    t = FourPillarsLogic::tsuhensei(j_day,k_month[0])
    j = FourPillarsLogic::jyuniunsei(j_day,k_month[1])
    je = JYUNIUNSEI_ENERGY[j]
    rows += [[y1,y2,k_month,t,j,je]]
    if y1 == 0
      y1 = year
    else
      y1 += 10
    end
    y2 += 10
    k += d
    k = 59 if k < 0
    k = 0 if k > 59
  end
  return rows
end

#tellObject

テーブル表示用に配列にして返す (デバッグ用) 0:干支, 1:干支数字, 2:蔵干, 3:通変星, 4:蔵干通変星, 5:十二運星 五行、天中殺、十二運星エネルギーは別途



314
315
316
317
318
319
320
321
322
# File 'lib/four-pillars.rb', line 314

def tell
  m = [kanshi]
  m += [kanshi_as_number]
  m += [zokan]
  m += [tsuhensei]
  m += [zokan_tsuhensei]
  m += [jyuniunsei]
  m += [jyuniunsei_energy]
end

#tsuhenseiObject

通変星(nil,月,年)



264
265
266
267
268
# File 'lib/four-pillars.rb', line 264

def tsuhensei
  m = FourPillarsLogic::tsuhensei(kanshi[0][0],kanshi[1][0])
  y = FourPillarsLogic::tsuhensei(kanshi[0][0],kanshi[2][0])
  [nil,m,y]
end

#zokanObject



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/four-pillars.rb', line 230

def zokan
  zokan_hash1 = {"" => "","" => "","" => ""}
  zokan_hash2 = {"" => ["",19,""],"" => ["",12,""]}
  zokan_hash3 = {"" => ["",9,"",12,""],"" => ["",7,"",14,""],
    "" => ["",9,"",12,""],"" => ["",5,"",14,""],"" => ["",9,"",12,""],
    "" => ["",10,"",13,""],"" => ["",9,"",13,""]}
  zn = zokan_number
  z = []
  kanshi.each do |k|
    j = k[1] # 十二支
    if zokan_hash1.keys.include? j
      z += [zokan_hash1[j]]
    elsif zokan_hash2.keys.include? j
      arr = zokan_hash2[j]
      if zn <= arr[1]
        z += [arr[0]]
      else
        z += [arr[2]]
      end
    elsif zokan_hash3.keys.include? j
      arr = zokan_hash3[j]
      if zn <= arr[1]
        z += [arr[0]]
      elsif zn <= arr[3]
        z += [arr[2]]
      else
        z += [arr[4]]
      end
    end
  end
  return z
end

#zokan_numberObject

蔵干数字



218
219
220
221
222
223
224
225
226
227
228
# File 'lib/four-pillars.rb', line 218

def zokan_number
  y,m,d,h,i = @birth_dt
  sd, st = setsuiri
  if d < sd || (d == sd && h*60+i < st)
    # 誕生日 + (前月の日数 - 前月の節入日) + 1
    return d + (days_of_previous_month - setsuiri_of_previous_month[0]) + 1
  else
    # 誕生日 - 節入日 + 1
    return d - sd + 1
  end
end

#zokan_tsuhenseiObject

蔵干通変星



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/four-pillars.rb', line 271

def zokan_tsuhensei
  j = JIKKAN.index(kanshi[0][0])
  if j % 2 == 0 # 陽
    jikkan = JIKKAN
  else # 陰
    jikkan = JIKKAN_IN
  end
  j = jikkan.index(kanshi[0][0])
  j_day = jikkan.index(zokan[0])
  j_month = jikkan.index(zokan[1])
  j_year = jikkan.index(zokan[2])
  t_day = j_day - j
  t_day += 10 if t_day < 0
  t_month = j_month - j
  t_month += 10 if t_month < 0
  t_year = j_year - j
  t_year += 10 if t_year < 0
  [TSUHENSEI[t_day],TSUHENSEI[t_month],TSUHENSEI[t_year]]
end