aro 0.1.0
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/aro +74 -0
- data/bin/cli/constants.rb +37 -0
- data/bin/cli/create.rb +17 -0
- data/bin/cli/deck.rb +79 -0
- data/bin/cli/usage.rb +15 -0
- data/db/migrate/1763374647_create_decks.rb +17 -0
- data/db/migrate/1763432541_create_logs.rb +19 -0
- data/lib/aro/c.rb +32 -0
- data/lib/aro/create.rb +30 -0
- data/lib/aro/database.rb +113 -0
- data/lib/aro/environment.rb +3 -0
- data/lib/aro/i18n.rb +14 -0
- data/lib/aro/prompt.rb +21 -0
- data/lib/aro/version.rb +4 -0
- data/lib/aro.rb +39 -0
- data/lib/models/deck.rb +220 -0
- data/lib/models/log.rb +5 -0
- data/locale/en.cards.yml +472 -0
- data/locale/en.usage.yml +78 -0
- data/locale/en.yml +30 -0
- metadata +221 -0
data/lib/models/deck.rb
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
require :base64.to_s
|
|
2
|
+
require_relative :"./log".to_s
|
|
3
|
+
|
|
4
|
+
class Aro::Deck < ActiveRecord::Base
|
|
5
|
+
has_many :logs
|
|
6
|
+
|
|
7
|
+
DECK_FILE = ".deck"
|
|
8
|
+
CARD_DELIM = ","
|
|
9
|
+
DEV_TAROT_FILE = "/dev/tarot"
|
|
10
|
+
|
|
11
|
+
# update this for # of cards you will draw
|
|
12
|
+
DRAW_COUNT = 10
|
|
13
|
+
|
|
14
|
+
# do not modify
|
|
15
|
+
DISPLAY_WIDTH = Aro::Deck::DRAW_COUNT*Aro::Deck::DRAW_COUNT
|
|
16
|
+
HISTORY_SEPARATOR = "#{"-" * Aro::Deck::DISPLAY_WIDTH}"
|
|
17
|
+
|
|
18
|
+
# change to update how timestamps appear
|
|
19
|
+
DATE_FORMAT = "%Y:%m:%d:%H:%M:%S"
|
|
20
|
+
|
|
21
|
+
before_create :populate_cards
|
|
22
|
+
after_commit :generate_log
|
|
23
|
+
|
|
24
|
+
def self.make(new_name)
|
|
25
|
+
Aro::Create.new(new_name)
|
|
26
|
+
new_deck = Aro::Deck.create(name: new_name)
|
|
27
|
+
if Aro::Deck.current_deck.nil?
|
|
28
|
+
File.open(Aro::Deck::DECK_FILE, "w") do |file|
|
|
29
|
+
file.write(new_deck.id)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
new_deck
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.fresh_cards
|
|
36
|
+
I18n.t("cards.index").map{|c| "+#{c}"}.join(Aro::Deck::CARD_DELIM)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def populate_cards
|
|
40
|
+
self.cards = Aro::Deck.fresh_cards
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def generate_log
|
|
44
|
+
prev_cards = Base64::decode64(logs.last.card_data) if logs.any?
|
|
45
|
+
if prev_cards.present? && prev_cards != cards || prev_cards.nil?
|
|
46
|
+
logs.create(
|
|
47
|
+
card_data: Base64::encode64(cards),
|
|
48
|
+
drawn_data: Base64::encode64(drawn || "")
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.display_selection_menu
|
|
54
|
+
unless Aro::Deck.any?
|
|
55
|
+
Aro::P.p.say(I18n.t("cli.messages.no_decks"))
|
|
56
|
+
exit(CLI::EXIT_CODES[:SUCCESS])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
selection = Aro::P.p.select("choose a deck:") do |menu|
|
|
60
|
+
Aro::Deck.all.each{|d|
|
|
61
|
+
if d.id == Aro::Deck.current_deck&.id
|
|
62
|
+
menu.default d.id
|
|
63
|
+
end
|
|
64
|
+
menu.choice(d.name, d.id)
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
File.open(Aro::Deck::DECK_FILE, "w") do |file|
|
|
68
|
+
file.write(selection)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.current_deck
|
|
73
|
+
if File.exist?(DECK_FILE)
|
|
74
|
+
current_deck_id = File.read(DECK_FILE)
|
|
75
|
+
return Aro::Deck.find_by(id: current_deck_id)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.read_dev_tarot
|
|
80
|
+
dt = nil
|
|
81
|
+
return dt unless File.exist?(Aro::Deck::DEV_TAROT_FILE)
|
|
82
|
+
|
|
83
|
+
File.open(Aro::Deck::DEV_TAROT_FILE, "r"){|dtf| dt = dtf.read(4)}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.card_strip(card)
|
|
87
|
+
card.gsub(/[+-]/, "").strip
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def show
|
|
91
|
+
# displays the current deck's cards in their current order.
|
|
92
|
+
h_text = I18n.t("cli.messages.history_title", deck: name)
|
|
93
|
+
h_text += "\n"
|
|
94
|
+
h_text += Aro::Deck::HISTORY_SEPARATOR + "\n\n"
|
|
95
|
+
h_text += "#{name.upcase.center(Aro::Deck::DISPLAY_WIDTH)}\n\n"
|
|
96
|
+
logs.reverse.each_with_index{|l, i|
|
|
97
|
+
h_text += Aro::Deck::HISTORY_SEPARATOR + "\n"
|
|
98
|
+
h_text += l.created_at.strftime(Aro::Deck::DATE_FORMAT).center(Aro::Deck::DISPLAY_WIDTH) + "\n"
|
|
99
|
+
h_text += "#{logs.count - i} of #{logs.count}".rjust(Aro::Deck::DISPLAY_WIDTH) + "\n"
|
|
100
|
+
h_text += Aro::Deck::HISTORY_SEPARATOR + "\n\n"
|
|
101
|
+
h_text += get_display_for_cards(
|
|
102
|
+
Base64::decode64(l.card_data).split(Aro::Deck::CARD_DELIM)
|
|
103
|
+
)
|
|
104
|
+
h_text += Aro::Deck::HISTORY_SEPARATOR + "\n"
|
|
105
|
+
|
|
106
|
+
drawn_cards = Base64::decode64(l.drawn_data).split(Aro::Deck::CARD_DELIM)
|
|
107
|
+
|
|
108
|
+
if !drawn_cards.nil? && drawn_cards.any?
|
|
109
|
+
h_text += I18n.t("cli.messages.history_drawn").center(Aro::Deck::DISPLAY_WIDTH) + "\n"
|
|
110
|
+
h_text += Aro::Deck::HISTORY_SEPARATOR + "\n\n"
|
|
111
|
+
h_text += get_display_for_cards(
|
|
112
|
+
drawn_cards
|
|
113
|
+
)
|
|
114
|
+
h_text += "\n"
|
|
115
|
+
end
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# for now tests just expect text output
|
|
119
|
+
return h_text if Aro::IS_TEST.call
|
|
120
|
+
|
|
121
|
+
Aro::P.less(h_text)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def get_display_for_cards(input = []) # todo:, print_nums: false)
|
|
125
|
+
result = ""
|
|
126
|
+
input.each_with_index{|c, i|
|
|
127
|
+
if i == I18n.t("cards.index").count - 1
|
|
128
|
+
result += c.ljust(Aro::Deck::DISPLAY_WIDTH)
|
|
129
|
+
else
|
|
130
|
+
result += c.ljust(Aro::Deck::DRAW_COUNT) + ((i + 1) % Aro::Deck::DRAW_COUNT == 0 ? "\n" : "")
|
|
131
|
+
end
|
|
132
|
+
}
|
|
133
|
+
result += "\n"
|
|
134
|
+
result
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def explore
|
|
138
|
+
# allows user to browse each card in the current deck.
|
|
139
|
+
answer = Aro::P.p.select(
|
|
140
|
+
I18n.t("cli.messages.choose_card"),
|
|
141
|
+
# formatted for tty-prompt gem
|
|
142
|
+
cards.split(Aro::Deck::CARD_DELIM).map{|c| [I18n.t("cards.#{Aro::Deck.card_strip(c)}.name"), c]}.to_h,
|
|
143
|
+
per_page: 7,
|
|
144
|
+
cycle: true,
|
|
145
|
+
default: 1
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# TODO: display this nicer
|
|
149
|
+
Aro::P.p.say(I18n.t("cards.#{Aro::Deck.card_strip(answer)}"))
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def shuffle
|
|
153
|
+
# shuffles the current deck and generates a log record.
|
|
154
|
+
update(cards: cards.split(Aro::Deck::CARD_DELIM).shuffle.join(Aro::Deck::CARD_DELIM))
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def reset
|
|
158
|
+
# completely reset the deck. replace all drawn and reset order.
|
|
159
|
+
# all orientations will be set to upright.
|
|
160
|
+
update(cards: Aro::Deck.fresh_cards, drawn: "")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def replace
|
|
164
|
+
# replaces all drawn cards FIFO and puts them on the bottom of
|
|
165
|
+
# the deck. this will preserve all card orientations.
|
|
166
|
+
cards_arr = cards.split(Aro::Deck::CARD_DELIM) || []
|
|
167
|
+
drawn_arr = drawn&.split(Aro::Deck::CARD_DELIM) || []
|
|
168
|
+
|
|
169
|
+
# append each drawn card to cards
|
|
170
|
+
drawn_arr.each{|dc| cards_arr << dc }
|
|
171
|
+
|
|
172
|
+
# clear drawn
|
|
173
|
+
update(drawn: "", cards: cards_arr.join(Aro::Deck::CARD_DELIM))
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def draw
|
|
177
|
+
# draw a random card from the current deck.
|
|
178
|
+
dev_tarot = nil
|
|
179
|
+
|
|
180
|
+
# find a card that is not already drawn
|
|
181
|
+
while dev_tarot.nil? do
|
|
182
|
+
# preferred randomness
|
|
183
|
+
dev_tarot = nil # Aro::Deck.read_dev_tarot&.strip&.split("")
|
|
184
|
+
|
|
185
|
+
cards_arr = cards.split(Aro::Deck::CARD_DELIM) || []
|
|
186
|
+
cards_arr_stripped = cards_arr.map{|c| Aro::Deck.card_strip(c)}
|
|
187
|
+
|
|
188
|
+
if dev_tarot.nil?
|
|
189
|
+
# assume user does not have /dev/tarot device.
|
|
190
|
+
# generate random facade
|
|
191
|
+
facade = cards_arr.sample.split("")
|
|
192
|
+
dev_tarot = (
|
|
193
|
+
facade.first(2).join("") +
|
|
194
|
+
Aro::NUMERALS[
|
|
195
|
+
facade.select{|c| !facade.first(2).include?(c)}.join("").to_sym
|
|
196
|
+
].to_s
|
|
197
|
+
).split("")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
dev_tarot_converted = dev_tarot[1] + Aro::NUMERALS.key(
|
|
201
|
+
dev_tarot.select{|c| !dev_tarot.first(2).include?(c)}.join("").to_i
|
|
202
|
+
).to_s
|
|
203
|
+
if cards_arr_stripped.include?(dev_tarot_converted)
|
|
204
|
+
# dev_tarot is valid
|
|
205
|
+
drawn_arr = drawn&.split(Aro::Deck::CARD_DELIM) || []
|
|
206
|
+
dev_tarot = dev_tarot[0] + dev_tarot_converted
|
|
207
|
+
drawn_arr << dev_tarot
|
|
208
|
+
cards_arr.delete_at(cards_arr_stripped.index(dev_tarot_converted))
|
|
209
|
+
update(
|
|
210
|
+
cards: cards_arr.join(Aro::Deck::CARD_DELIM),
|
|
211
|
+
drawn: drawn_arr.join(Aro::Deck::CARD_DELIM)
|
|
212
|
+
)
|
|
213
|
+
else
|
|
214
|
+
# dev_tarot is invalid
|
|
215
|
+
dev_tarot = nil
|
|
216
|
+
sleep(1)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|