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.
@@ -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
data/lib/models/log.rb ADDED
@@ -0,0 +1,5 @@
1
+ require_relative './deck'
2
+
3
+ class Aro::Log < ActiveRecord::Base
4
+ belongs_to :deck, :class_name => :"Aro::Deck".to_s
5
+ end