four-pillars 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,320 @@
1
+ require 'date'
2
+
3
+ class FourPillarsLogic
4
+ JIKKAN = ["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
5
+ JYUNISHI = ["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
6
+ TSUHENSEI = ["比肩","劫財","食神","傷官","偏財","正財","偏官","正官","偏印","印綬"]
7
+ JYUNIUNSEI = ["長生","沐浴","冠帯","建禄","帝旺","衰","病","死","墓","絶","胎","養"]
8
+ GOGYO = ["木","火","土","金","水"]
9
+ KUUBOU = ["戌亥","申酉","午未","辰巳","寅卯","子丑"]
10
+
11
+ # 60干支表
12
+ def self.kanshi_array
13
+ a = []
14
+ 60.times do |i|
15
+ j1 = FourPillarsLogic::JIKKAN[i%10]
16
+ j2 = FourPillarsLogic::JYUNISHI[i%12]
17
+ a += [j1+j2]
18
+ end
19
+ return a
20
+ end
21
+ KANSHI_ARRAY = kanshi_array
22
+
23
+ # 60干支表
24
+ def self.kanshi_hash
25
+ h = {}
26
+ kanshi_array.each_with_index do |v,i|
27
+ h[v] = i+1
28
+ end
29
+ return h
30
+ end
31
+ KANSHI_HASH = kanshi_hash
32
+
33
+ # 陰干通表
34
+ def self.jikkan_in
35
+ j = [nil] * 10
36
+ [0,2,4,6,8].each do |i|
37
+ j[i] = JIKKAN[i+1]
38
+ j[i+1] = JIKKAN[i]
39
+ end
40
+ return j
41
+ end
42
+ JIKKAN_IN = jikkan_in
43
+ JYUNISHI_IN = JYUNISHI.reverse
44
+
45
+ # 十二運星エネルギー
46
+ def self.jyuniunsei_energy
47
+ h = {}
48
+ energies = [9,7,10,11,12,8,4,2,5,1,3,6]
49
+ 12.times do |i|
50
+ h[JYUNIUNSEI[i]] = energies[i]
51
+ end
52
+ return h
53
+ end
54
+ JYUNIUNSEI_ENERGY = jyuniunsei_energy
55
+
56
+ # 年月の節入り日時 (注:時 = 時間 x 60 + 分)
57
+ def self.load_setsuiri
58
+ l = []
59
+ h = {}
60
+ open(__dir__+"/four-pillars-setsuiri.txt").each do |line|
61
+ next if line.strip.empty? || line.start_with?("#")
62
+ vs = line.split(",")
63
+ if vs.count != 5 || vs[0].empty?
64
+ puts "Invalid row: #{line}"
65
+ next
66
+ end
67
+ vs.map! { |v| v.to_i }
68
+ h[vs[0]*100+vs[1]] = [vs[2],vs[3]*60+vs[4]]
69
+ l += [vs]
70
+ end
71
+ return h, l
72
+ end
73
+ SETSUIRI_HASH, SETSUIRI_LIST = load_setsuiri
74
+
75
+ # 生年月日時間, 性別(鑑定には使用しない)
76
+ attr_reader :birth_dt,:gender
77
+
78
+ def initialize(birth_dt,gender)
79
+ @birth_dt = birth_dt.map {|v| v.to_i }
80
+ @gender = gender
81
+ raise "Incorrect birth date: #{birth_dt}" if @birth_dt.count != 5
82
+ raise "Gender must be m,f or o(other): #{gender}" unless ['o','m','f'].include? @gender
83
+ raise "Year must be larger than 1863" if @birth_dt[0] < 1864
84
+ end
85
+
86
+ # 生年月日と性別
87
+ def input
88
+ y,m,d,h,i = @birth_dt
89
+ case @gender
90
+ when 'm' then
91
+ g = "男性"
92
+ when 'f' then
93
+ g = "女性"
94
+ else
95
+ g = ""
96
+ end
97
+ "#{y}年#{m}月#{d}日#{h}時#{i}分生 #{g}"
98
+ end
99
+
100
+ # 前月の日数
101
+ def days_of_previous_month
102
+ y,m,d,h,i = @birth_dt
103
+ (Date.new(y,m,1) - 1).day
104
+ end
105
+
106
+ # 前月の節入日
107
+ def setsuiri_of_previous_month
108
+ y,m,d,h,i = @birth_dt
109
+ if m == 1
110
+ y -= 1
111
+ m = 12
112
+ else
113
+ m -= 1
114
+ end
115
+ SETSUIRI_HASH[y*100+m] || [0,0]
116
+ end
117
+
118
+ # 生年月に対する節入日時を知っているか?
119
+ # このメソッドがfalseを返す場合、干支、蔵干が仮の節入日で計算されています。
120
+ def know_setsuiri?
121
+ y,m,d,h,i = @birth_dt
122
+ SETSUIRI_HASH.include? y*100+m
123
+ end
124
+
125
+ # 生年月に対応する節入り日時 ファイルに登録がない場合は、4日12時を返す
126
+ def setsuiri
127
+ y,m,d,h,i = @birth_dt
128
+ SETSUIRI_HASH[y*100+m] || [4,12*60]
129
+ end
130
+
131
+ # 生まれた日が節入日にあたる場合、true
132
+ def setsuiri?
133
+ return false unless know_setsuiri?
134
+ y,m,d,h,i = @birth_dt
135
+ setsuiri[0] == d
136
+ end
137
+
138
+ # 干支(日,月,年)
139
+ def kanshi
140
+ y,m,d,h,i = @birth_dt
141
+ sd, st = setsuiri
142
+ yd = y - 1864 # (till 1865.02.0?) = 甲子
143
+ yd -= 1 if m < 2 || (m == 2 && d < sd) || (m == 2 && d == sd && h*60+i < st)
144
+ md = (y - 1863) * 12 + (m - 12) # (till 1864.01.05) = 甲子
145
+ md -= 1 if d < sd || (d == sd && h*60+i < st)
146
+ dd = Date.new(y,m,d) - Date.new(1863,12,31) # 1923.10.18 = 甲子
147
+
148
+ return [KANSHI_ARRAY[dd % 60],KANSHI_ARRAY[md % 60],KANSHI_ARRAY[yd % 60]]
149
+ end
150
+
151
+ # 干支(数字)
152
+ def kanshi_as_number
153
+ kanshi.map {|v| KANSHI_HASH[v] }
154
+ end
155
+
156
+ # 蔵干数字
157
+ def zokan_number
158
+ y,m,d,h,i = @birth_dt
159
+ sd, st = setsuiri
160
+ if d < sd || (d == sd && h*60+i < st)
161
+ # 誕生日 + (前月の日数 - 前月の節入日) + 1
162
+ return d + (days_of_previous_month - setsuiri_of_previous_month[0]) + 1
163
+ else
164
+ # 誕生日 - 節入日 + 1
165
+ return d - sd + 1
166
+ end
167
+ end
168
+
169
+ def zokan
170
+ zokan_hash1 = {"子" => "癸","卯" => "乙","酉" => "辛"}
171
+ zokan_hash2 = {"午" => ["己",19,"丁"],"亥" => ["甲",12,"壬"]}
172
+ zokan_hash3 = {"丑" => ["癸",9,"辛",12,"己"],"寅" => ["戊",7,"丙",14,"甲"],
173
+ "辰" => ["乙",9,"癸",12,"戊"],"巳" => ["戊",5,"庚",14,"丙"],"未" => ["丁",9,"乙",12,"己"],
174
+ "申" => ["戊",10,"壬",13,"庚"],"戌" => ["辛",9,"丁",13,"戊"]}
175
+ zn = zokan_number
176
+ z = []
177
+ kanshi.each do |k|
178
+ j = k[1] # 十二支
179
+ if zokan_hash1.keys.include? j
180
+ z += [zokan_hash1[j]]
181
+ elsif zokan_hash2.keys.include? j
182
+ arr = zokan_hash2[j]
183
+ if zn <= arr[1]
184
+ z += [arr[0]]
185
+ else
186
+ z += [arr[2]]
187
+ end
188
+ elsif zokan_hash3.keys.include? j
189
+ arr = zokan_hash3[j]
190
+ if zn <= arr[1]
191
+ z += [arr[0]]
192
+ elsif zn <= arr[3]
193
+ z += [arr[2]]
194
+ else
195
+ z += [arr[4]]
196
+ end
197
+ end
198
+ end
199
+ return z
200
+ end
201
+
202
+ # 通変星(nil,月,年)
203
+ def tsuhensei
204
+ j = JIKKAN.index(kanshi[0][0])
205
+ if j % 2 == 0 # 陽
206
+ jikkan = JIKKAN
207
+ else # 陰
208
+ jikkan = JIKKAN_IN
209
+ end
210
+ j = jikkan.index(kanshi[0][0])
211
+ j_month = jikkan.index(kanshi[1][0])
212
+ j_year = jikkan.index(kanshi[2][0])
213
+ t_month = j_month - j
214
+ t_month += 10 if t_month < 0
215
+ t_year = j_year - j
216
+ t_year += 10 if t_year < 0
217
+ [nil,TSUHENSEI[t_month],TSUHENSEI[t_year]]
218
+ end
219
+
220
+ # 蔵干通変星
221
+ def zokan_tsuhensei
222
+ j = JIKKAN.index(kanshi[0][0])
223
+ if j % 2 == 0 # 陽
224
+ jikkan = JIKKAN
225
+ else # 陰
226
+ jikkan = JIKKAN_IN
227
+ end
228
+ j = jikkan.index(kanshi[0][0])
229
+ j_day = jikkan.index(zokan[0])
230
+ j_month = jikkan.index(zokan[1])
231
+ j_year = jikkan.index(zokan[2])
232
+ t_day = j_day - j
233
+ t_day += 10 if t_day < 0
234
+ t_month = j_month - j
235
+ t_month += 10 if t_month < 0
236
+ t_year = j_year - j
237
+ t_year += 10 if t_year < 0
238
+ [TSUHENSEI[t_day],TSUHENSEI[t_month],TSUHENSEI[t_year]]
239
+ end
240
+
241
+ # 十二運星
242
+ def jyuniunsei
243
+ j = JIKKAN.index(kanshi[0][0])
244
+ if j % 2 == 0 # 陽
245
+ jyunishi = JYUNISHI
246
+ else # 陰
247
+ jyunishi = JYUNISHI_IN
248
+ end
249
+ offset = [1,7,10,10,10,10,7,1,4,4][j] # 十二運表より求めたオフセット
250
+ j_day = jyunishi.index(kanshi[0][1])
251
+ j_month = jyunishi.index(kanshi[1][1])
252
+ j_year = jyunishi.index(kanshi[2][1])
253
+ u_day = (j_day + offset) % 12
254
+ u_month = (j_month + offset) % 12
255
+ u_year = (j_year + offset) % 12
256
+ [JYUNIUNSEI[u_day],JYUNIUNSEI[u_month],JYUNIUNSEI[u_year]]
257
+ end
258
+
259
+ def jyuniunsei_energy
260
+ jyuniunsei.map {|v| JYUNIUNSEI_ENERGY[v] }
261
+ end
262
+
263
+ # 空亡 = 天中殺
264
+ def kuubou
265
+ k_day = (kanshi_as_number[0] - 1) / 10
266
+ k_year = (kanshi_as_number[2] - 1) / 10
267
+ [KUUBOU[k_day],KUUBOU[k_year]]
268
+ end
269
+
270
+ # テーブル表示用に配列にして返す (デバッグ用)
271
+ # 0:干支, 1:干支数字, 2:蔵干, 3:通変星, 4:蔵干通変星, 5:十二運星
272
+ # 五行、天中殺、十二運星エネルギーは別途
273
+ def tell
274
+ m = [kanshi]
275
+ m += [kanshi_as_number]
276
+ m += [zokan]
277
+ m += [tsuhensei]
278
+ m += [zokan_tsuhensei]
279
+ m += [jyuniunsei]
280
+ m += [jyuniunsei_energy]
281
+ end
282
+
283
+ # 五行(十干)
284
+ def gogyo_jikkan
285
+ arr = []
286
+ 3.times do |i|
287
+ j = JIKKAN.index(kanshi[i][0])
288
+ arr += [(j % 2 == 0 ? "+" : "-") + GOGYO[j / 2]]
289
+ end
290
+ return arr
291
+ end
292
+
293
+ # 五行(十二支)
294
+ def gogyo_jyunishi
295
+ arr = []
296
+ gogyo_j = ["水","土","木","木","土","火","火","土","金","金","土","水"]
297
+ 3.times do |i|
298
+ j = JYUNISHI.index(kanshi[i][1])
299
+ arr += [(j % 2 == 0 ? "+" : "-") + gogyo_j[j]]
300
+ end
301
+ return arr
302
+ end
303
+ end
304
+
305
+ if __FILE__ == $0
306
+ require 'optparse'
307
+ Version = "1.0.0"
308
+
309
+ bd = ["1980","7","27","1","20"]
310
+ gender = 'm' # m or f
311
+
312
+ opt = OptionParser.new
313
+ opt.on('-b y,m,d,h,m') { |v| bd = v.split(",")}
314
+ opt.on('-g (m|f)') { |v| gender = v }
315
+ opt.parse!(ARGV)
316
+
317
+ res = FourPillarsLogic.new(bd,gender)
318
+ puts res.input
319
+ puts res.tell
320
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: four-pillars
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yosei Ito
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Tell your meishiki from your birthday and time.
14
+ email: y-itou@lumber-mill.co.jp
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/four-pillars-setsuiri.txt
20
+ - lib/four-pillars.rb
21
+ homepage: https://github.com/lumbermill/four-pillars
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 3.0.3
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Fortune telling
44
+ test_files: []