mooncal 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/moon +24 -0
- data/lib/moon.rb +101 -0
- data/lib/moon_calc.rb +78 -0
- data/lib/moon_date.rb +51 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3a899696eeec601a7712c4bcb1fe60d4e1c0d1d267e7755cff408a365f23547f
|
4
|
+
data.tar.gz: 810a2c50960ea370404cd0f95e225aba64e8f61a376432781844c5c5ec8dfdef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4f1674ac492560531d7652114e0e192adcf7244240971f63b2adca8b729842a5e7237f742bf80876a8cbe7d897983a2e564a7fd11b99860b9e3cc0a821a3d32b
|
7
|
+
data.tar.gz: 42f8a6a342ed82802c110de618127931a7942bed2fcf08aa9b9e4908ef540e83be4579d6298e5424d98647f6831b4ab8955939c908d8c86815d94287c0ee25c7
|
data/bin/moon
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'moon'
|
5
|
+
|
6
|
+
### PARSE ARGS ###
|
7
|
+
|
8
|
+
arg, *other_args = ARGV
|
9
|
+
|
10
|
+
case arg
|
11
|
+
when "today"
|
12
|
+
puts MoonTerm.new.moon_day
|
13
|
+
when "week"
|
14
|
+
puts MoonTerm.new.moon_week
|
15
|
+
when "month"
|
16
|
+
puts MoonTerm.new.moon_month
|
17
|
+
when "-h"
|
18
|
+
puts MoonTerm.new.help_text
|
19
|
+
when "help"
|
20
|
+
puts MoonTerm.new.help_text
|
21
|
+
else
|
22
|
+
puts MoonTerm.new.moon_month
|
23
|
+
end
|
24
|
+
|
data/lib/moon.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'tty-table'
|
2
|
+
require 'pastel'
|
3
|
+
require_relative 'moon_date'
|
4
|
+
|
5
|
+
$pastel = Pastel.new
|
6
|
+
|
7
|
+
### MAIN ###
|
8
|
+
|
9
|
+
class MoonTerm
|
10
|
+
attr_reader :date
|
11
|
+
|
12
|
+
### CONSTANTS ###
|
13
|
+
TERM_HEIGHT, TERM_WIDTH = TTY::Screen.size
|
14
|
+
|
15
|
+
DAY_NAMES = [
|
16
|
+
"Monday",
|
17
|
+
"Tuesday",
|
18
|
+
"Wednesday",
|
19
|
+
"Thursday",
|
20
|
+
"Friday",
|
21
|
+
"Saturday",
|
22
|
+
"Sunday"
|
23
|
+
]
|
24
|
+
|
25
|
+
MOONS = {
|
26
|
+
new: ["\u{1F311}", "New Moon", "New"],
|
27
|
+
waxing_crescent: ["\u{1F312}", "Waxing Crescent", "WxC"],
|
28
|
+
first_quarter: ["\u{1F313}", "First Quarter", "FQ"],
|
29
|
+
waxing_gibbous: ["\u{1F314}", "Waxing Gibbous", "WxG"],
|
30
|
+
full: ["\u{1F315}", "Full Moon", "Full"],
|
31
|
+
waning_gibbous: ["\u{1F316}", "Waning Gibbous", "WnG"],
|
32
|
+
last_quarter: ["\u{1F317}", "Last Quarter", "LQ"],
|
33
|
+
waning_crescent: ["\u{1F318}", "Waning Crescent", "WnC"]
|
34
|
+
}
|
35
|
+
|
36
|
+
def initialize(date=MoonDate.today)
|
37
|
+
@date = date
|
38
|
+
end
|
39
|
+
|
40
|
+
def moon_day
|
41
|
+
header_string = "\n" + center_string("The Moon today (#{@date.strftime("%a, %b %e")}):") + "\n\n"
|
42
|
+
phase_string = center_string($pastel.bold(MOONS[@date.moon_phase][1])) + "\n"
|
43
|
+
moon_icon = center_string(MOONS[@date.moon_phase][0]) + "\n"
|
44
|
+
|
45
|
+
header_string + phase_string + moon_icon
|
46
|
+
end
|
47
|
+
|
48
|
+
def moon_week
|
49
|
+
table = TTY::Table.new(DAY_NAMES, [])
|
50
|
+
title = "\n" + center_string($pastel.bold("Moon Phases for the #{number_ord(@date.current_week)} week of #{@date.strftime("%B")}")) + "\n\n"
|
51
|
+
|
52
|
+
table << @date.month_days(true).each_slice(7).to_a[@date.current_week - 1].map do |day|
|
53
|
+
if day == @date then $pastel.bold(day.strftime("%b %e"))
|
54
|
+
elsif !day.nil? then day.strftime("%b %e")
|
55
|
+
else nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
table << @date.week_days(true).map { |day| day.nil? ? day : MOONS[day.moon_phase][0] }
|
59
|
+
|
60
|
+
title + center_table(table.render(multiline: true, alignment: [:center], padding: [0, 2, 0, 2])) + "\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
def moon_month
|
64
|
+
table = TTY::Table.new(DAY_NAMES, [])
|
65
|
+
days = @date.month_days(true).map do |day|
|
66
|
+
day.nil? ? day : (day == @date) ? "#{$pastel.bold(day.strftime("%d"))}\n#{MOONS[day.moon_phase][0]}" : "#{day.strftime("%d")}\n#{MOONS[day.moon_phase][0]}"
|
67
|
+
end
|
68
|
+
weeks = days.each_slice(7).to_a
|
69
|
+
|
70
|
+
weeks.each { |week| table << week }
|
71
|
+
|
72
|
+
"\n" + center_string($pastel.bold("Moon Phases for #{@date.strftime("%B %Y")}")) + "\n\n" +
|
73
|
+
center_table(table.render(multiline: true, alignment: [:center], padding:[0, 1, 0, 1])) + "\n"
|
74
|
+
end
|
75
|
+
|
76
|
+
def help_text
|
77
|
+
"\nUsage: moon [today | week | month | help | -h]"
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def number_ord(num)
|
83
|
+
case num
|
84
|
+
when 1 then num.to_s + "st"
|
85
|
+
when 2 then num.to_s + "nd"
|
86
|
+
when 3 then num.to_s + "rd"
|
87
|
+
else num.to_s + "th"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def center_string(str, width=TERM_WIDTH)
|
92
|
+
padding = ((width - $pastel.strip(str).length) / 2).floor
|
93
|
+
str.strip.prepend(" " * padding)
|
94
|
+
end
|
95
|
+
|
96
|
+
def center_table(rendered_table)
|
97
|
+
table_rows = rendered_table.split("\n")
|
98
|
+
padding = ((TERM_WIDTH - table_rows[1].length) / 2).floor
|
99
|
+
table_rows.map { |row| row.prepend(" " * padding) }.join("\n")
|
100
|
+
end
|
101
|
+
end
|
data/lib/moon_calc.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Lunar/Moon phases ruby class
|
2
|
+
#
|
3
|
+
# Code is based upon Bradley E. Schaefer''s moon phase algorithm.
|
4
|
+
# Ruby version based on JavaScript Phase Calculator by Stephen R. Schmitt
|
5
|
+
class MoonCalc
|
6
|
+
attr_reader :epoch, :phase, :days, :icon, :dist, :ll
|
7
|
+
|
8
|
+
# Return the current (or input a date) moon.
|
9
|
+
# Moon.new
|
10
|
+
# Moon.new(some_day)
|
11
|
+
#
|
12
|
+
# Methods available:
|
13
|
+
# phase => Phase of the moon as a sym
|
14
|
+
# days => Moon days
|
15
|
+
# icon => An integer from 0 to 29
|
16
|
+
# dist => Distance in earth radii
|
17
|
+
# ll => Moon ecliptic lat/lon
|
18
|
+
#
|
19
|
+
def initialize(epoch=Time.now)
|
20
|
+
@epoch = epoch
|
21
|
+
do_calc
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def calc_phase(p)
|
27
|
+
case p
|
28
|
+
when 0 then :new
|
29
|
+
when 1..6 then :waxing_crescent
|
30
|
+
when 7..9 then :first_quarter
|
31
|
+
when 10..12 then :waxing_gibbous
|
32
|
+
when 13..16 then :full
|
33
|
+
when 17..20 then :waning_gibbous
|
34
|
+
when 21..24 then :last_quarter
|
35
|
+
when 25..28 then :waning_crescent
|
36
|
+
else :new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def calc_coords(inter, phase)
|
41
|
+
phase = phase * 2 * Math::PI
|
42
|
+
dp = 2 * Math::PI * normalize((inter - 2451562.2 ) / 27.55454988)
|
43
|
+
@dist = 60.4 - 3.3 * Math.cos(dp) - 0.6 * Math.cos(2 * phase - dp) - 0.5 * Math.cos(2 * phase)
|
44
|
+
|
45
|
+
np = 2 * Math::PI * normalize((inter - 2451565.2) / 27.212220817)
|
46
|
+
la = 5.1 * Math.sin(np)
|
47
|
+
|
48
|
+
rp = normalize((inter - 2451555.8 ) / 27.321582241)
|
49
|
+
lo = 360 * rp + 6.3 * Math.sin(dp) + 1.3 * Math.sin(2 * phase - dp) + 0.7 * Math.sin(2 * phase)
|
50
|
+
@ll = [la, lo]
|
51
|
+
end
|
52
|
+
|
53
|
+
def do_calc
|
54
|
+
c_phase = 29.530588853
|
55
|
+
t_year = @epoch.year - ((12 - @epoch.month)/10).to_i
|
56
|
+
t_month = (@epoch.month + 9) % 12
|
57
|
+
|
58
|
+
t1 = (365.25 * (t_year + 4712)).to_i
|
59
|
+
t2 = (30.6 * t_month + 0.5).to_i
|
60
|
+
t3 = (((t_year / 100.0) + 49.0) * 0.75).to_i - 38
|
61
|
+
inter = t1 + t2 + @epoch.day + 59
|
62
|
+
inter -= t3 if inter > 2299160
|
63
|
+
phase = normalize((inter - 2451550.1) / c_phase)
|
64
|
+
res = phase * c_phase;
|
65
|
+
|
66
|
+
@days = (res * 100).to_i / 100
|
67
|
+
@icon = res.to_i % 30
|
68
|
+
@phase = calc_phase(@icon)
|
69
|
+
calc_coords(inter, phase)
|
70
|
+
end
|
71
|
+
|
72
|
+
def normalize(x)
|
73
|
+
x %= 1
|
74
|
+
x += 1 if x < 0
|
75
|
+
x
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/lib/moon_date.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'date'
|
2
|
+
require_relative 'moon_calc'
|
3
|
+
|
4
|
+
class MoonDate < Date
|
5
|
+
DAY_NAME = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
6
|
+
MONTH_NAME = ["January", "February", "March", "April", "May", "June",
|
7
|
+
"July", "August", "September", "October", "November", "December"]
|
8
|
+
|
9
|
+
def week_days(padded=false)
|
10
|
+
week_days = month_days.filter { |day| day.cweek == self.cweek }
|
11
|
+
padded ? pad_days(week_days) : week_days
|
12
|
+
end
|
13
|
+
|
14
|
+
def current_week
|
15
|
+
naive_cweek(self) - naive_cweek(MoonDate.new(self.year, self.month, 1)) + 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def day_name
|
19
|
+
DAY_NAME[self.cwday - 1]
|
20
|
+
end
|
21
|
+
|
22
|
+
def month_name
|
23
|
+
MONTH_NAME[self.month - 1]
|
24
|
+
end
|
25
|
+
|
26
|
+
def month_days(padded=false)
|
27
|
+
days = (0..31).filter { |day| Date.valid_date?(self.year, self.month, day) }.map do |day|
|
28
|
+
MoonDate.new(self.year, self.month, day)
|
29
|
+
end
|
30
|
+
|
31
|
+
padded ? pad_days(days) : days
|
32
|
+
end
|
33
|
+
|
34
|
+
def moon_phase
|
35
|
+
MoonCalc.new(self).phase
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def pad_days(days)
|
41
|
+
front_padding = days.first.cwday - 1
|
42
|
+
end_padding = 7 - days.last.cwday
|
43
|
+
|
44
|
+
Array.new(front_padding, nil) + days + Array.new(end_padding, nil)
|
45
|
+
end
|
46
|
+
|
47
|
+
def naive_cweek(date)
|
48
|
+
date.month == 1 && date.cweek == 53 ? 1 : date.month_days.first.cweek == 53 ? date.cweek + 1 : date.cweek
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mooncal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nikolai Kozak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-09-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tty-table
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.12'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pastel
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.8'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.8'
|
41
|
+
description: Print a moon phase calendar to your terminal!
|
42
|
+
email: nikokozak@gmail.com
|
43
|
+
executables:
|
44
|
+
- moon
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- bin/moon
|
49
|
+
- lib/moon.rb
|
50
|
+
- lib/moon_calc.rb
|
51
|
+
- lib/moon_date.rb
|
52
|
+
homepage:
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubygems_version: 3.2.15
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: Moon Phases!
|
75
|
+
test_files: []
|