aromancer 0.0.7 → 0.0.8
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 +4 -4
- data/.DS_Store +0 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/checksums/aromancer-0.0.8.gem.sha512 +1 -0
- data/lib/aromancer/api.rb +7 -26
- data/lib/aromancer/cli.rb +134 -0
- data/lib/aromancer/routes.rb +91 -114
- data/lib/aromancer/serve.rb +35 -0
- data/lib/aromancer/server.rb +0 -1
- data/lib/aromancer/storage.rb +152 -36
- data/lib/aromancer/version.rb +1 -1
- data/lib/aromancer/websocket.rb +29 -8
- data/lib/aromancer.rb +11 -130
- data/lib/reiquire.rb +2 -0
- data/listen.rb +0 -4
- data/locale/en.yml +2 -1
- data/pre-commit.git.template +5 -0
- data/tasks/make.rake +2 -2
- metadata +6 -3
- data/LICENSE.txt +0 -21
- data/gem_graph.png +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da80d9c4f943470ac226c37651e21eaa5ee12128beb9c00264b43ace9845c61c
|
|
4
|
+
data.tar.gz: c55101847c0d3e6c14d7c821dc9fdf31d4e114d614d97957b7162ab995d5a02e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 706112cc7fbf39edadef53eb6ac54a73c4e43d17f0f3b288cb9c795ba937bc38ec8427bb74ddcfbd8c84411483c520a8d9ac9b576f4371c1f0c656c2e36adb69
|
|
7
|
+
data.tar.gz: 91aa390ba4cf322eef5e616053cce00ebaba35ef0b9d13e051f2ba71a08bdf7c7ba5a9669d0279f88e7a67ed619a2cddba2b36f5eddc52854f691f2b74458fbc
|
data/.DS_Store
ADDED
|
Binary file
|
data/CODE_OF_CONDUCT.md
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
8
8
|
* Behaviour which can be reasonably considered harassment will not be tolerated.
|
|
9
9
|
|
|
10
|
-
If you have any concerns about
|
|
10
|
+
If you have any concerns about behavior within this project, please contact us at ["i2097i@hotmail.com"](mailto:"i2097i@hotmail.com").
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ea42cb760ae909d4de2b750f3ca7f125d58b9e9147886927e8f5b7dd81a80913152d6052c1c517a99a0733e7d3b15de86d3083d1f82d5341e4c8f1e3364222a2
|
data/lib/aromancer/api.rb
CHANGED
|
@@ -24,23 +24,12 @@ module Aromancer
|
|
|
24
24
|
body: response.body.to_s
|
|
25
25
|
}
|
|
26
26
|
Aromancer::Storage.set_last_error(le)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# rescue StandardError => e
|
|
34
|
-
# end
|
|
35
|
-
|
|
36
|
-
# signed_out = signed_out &&
|
|
37
|
-
# !error_body.nil? &&
|
|
38
|
-
# error_body.keys.include?(:error_message.to_s) &&
|
|
39
|
-
# error_body["error_message"] == "not signed in"
|
|
40
|
-
|
|
41
|
-
if signed_out
|
|
42
|
-
Aromancer::Storage.instance.clear_cache!
|
|
43
|
-
Aromancer::Storage.set_signed_out_flag(signed_out)
|
|
27
|
+
|
|
28
|
+
if response.status == 401
|
|
29
|
+
Aromancer::Storage.set_signed_out_flag(true)
|
|
30
|
+
player = Aromancer::Storage.get_player
|
|
31
|
+
player["api_key"] = nil
|
|
32
|
+
Aromancer::Storage.set_player(player)
|
|
44
33
|
end
|
|
45
34
|
end
|
|
46
35
|
|
|
@@ -93,17 +82,9 @@ module Aromancer
|
|
|
93
82
|
|
|
94
83
|
def self.sign_out
|
|
95
84
|
result = Aromancer::Server.sign_out
|
|
96
|
-
# clear storage
|
|
97
|
-
Aromancer::Storage.instance.clear_cache!
|
|
98
|
-
Aromancer::Storage.set_signed_out_flag(false)
|
|
99
85
|
Aromancer::Storage.set_player(nil)
|
|
100
|
-
Aromancer::Storage.set_legends(nil)
|
|
101
|
-
Aromancer::Storage.set_arena(nil)
|
|
102
|
-
Aromancer::Storage.set_stream(nil)
|
|
103
|
-
Aromancer::Storage.set_last_error(nil)
|
|
104
|
-
|
|
105
86
|
Aromancer::Websocket.instance.disconnect
|
|
106
|
-
|
|
87
|
+
Aromancer::Storage.recreate!
|
|
107
88
|
register_error(result) if result.status != 200
|
|
108
89
|
end
|
|
109
90
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
cli.rb
|
|
6
|
+
|
|
7
|
+
aromancer cli
|
|
8
|
+
|
|
9
|
+
by i2097i
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
module Aromancer
|
|
14
|
+
# instance runs on main thread
|
|
15
|
+
class Cli
|
|
16
|
+
include Singleton
|
|
17
|
+
|
|
18
|
+
attr_accessor :ui_thread, :ws_thread, :ui_busy, :ws_busy, :last_render, :error_timeout
|
|
19
|
+
|
|
20
|
+
THROTTLE_MS = 0.1
|
|
21
|
+
|
|
22
|
+
# user entry point
|
|
23
|
+
def self.run
|
|
24
|
+
Aromancer::Websocket.instance
|
|
25
|
+
Aromancer::Storage.instance
|
|
26
|
+
|
|
27
|
+
self.instance.last_render = 0
|
|
28
|
+
self.instance.error_timeout = Time.now.to_i
|
|
29
|
+
|
|
30
|
+
# load player on-start
|
|
31
|
+
Aromancer::Api.set_active_legend_id(nil) unless Aromancer::Storage.get_player.nil?
|
|
32
|
+
|
|
33
|
+
Thread.main[:route] = :authentication
|
|
34
|
+
Thread.main[:menu_runners] = {}
|
|
35
|
+
Thread.main[:menu_options] = {}
|
|
36
|
+
Aromancer::Prompt.say(I18n.t("shared.welcome", version: Aromancer::VERSION))
|
|
37
|
+
Aromancer::Prompt.say(I18n.t("shared.server_url", url: Aromancer::Storage::get_server_url))
|
|
38
|
+
self.instance.start_ui_thread
|
|
39
|
+
self.instance.start_ws_thread
|
|
40
|
+
loop do
|
|
41
|
+
begin
|
|
42
|
+
self.instance.ui_thread.join
|
|
43
|
+
rescue NoMethodError => e
|
|
44
|
+
if Aromancer::Storage.get_preference(:debug)
|
|
45
|
+
Aromancer::Prompt.say(I18n.t("shared.last_error"))
|
|
46
|
+
Aromancer::Prompt.say(JSON.pretty_generate(e[:body.to_s]))
|
|
47
|
+
Aromancer::Prompt.say("sleeping 5 on main thread...")
|
|
48
|
+
sleep(5)
|
|
49
|
+
end
|
|
50
|
+
self.instance.start_ui_thread
|
|
51
|
+
self.instance.start_ws_thread
|
|
52
|
+
sleep(1)
|
|
53
|
+
rescue Interrupt => e
|
|
54
|
+
Aromancer::Prompt.say("interrupt on main thread...exiting immediately.")
|
|
55
|
+
exit
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def start_ui_thread(force = false)
|
|
61
|
+
return if (@ui_busy || Time.now - @last_render < 2.0) && !force
|
|
62
|
+
|
|
63
|
+
@ui_busy = true
|
|
64
|
+
self.ui_thread&.exit
|
|
65
|
+
self.ui_thread&.kill
|
|
66
|
+
Thread.main[:menu_runners] = {}
|
|
67
|
+
Thread.main[:menu_options] = {}
|
|
68
|
+
Aromancer::Prompt.instance.reload!
|
|
69
|
+
self.ui_thread = Thread.new do
|
|
70
|
+
loop do
|
|
71
|
+
menu_options = Thread.main[:menu_options][Thread.main[:route]]
|
|
72
|
+
menu_runners = Thread.main[:menu_runners][Thread.main[:route]]
|
|
73
|
+
unless menu_options.nil? ||
|
|
74
|
+
menu_runners.nil? ||
|
|
75
|
+
menu_options.empty? ||
|
|
76
|
+
menu_runners.empty?
|
|
77
|
+
|
|
78
|
+
Aromancer::Routes.resume
|
|
79
|
+
sleep(THROTTLE_MS)
|
|
80
|
+
Aromancer.print_hud
|
|
81
|
+
|
|
82
|
+
v = Aromancer::Prompt.p.select("", menu_options, show_help: :always, cycle: true, per_page: 11)
|
|
83
|
+
Aromancer.print_hud
|
|
84
|
+
runners = menu_runners.select{|r| r[:value] == v}
|
|
85
|
+
runners = menu_runners.select{|r| r[:value].nil?} if runners.empty?
|
|
86
|
+
|
|
87
|
+
if runners.any?
|
|
88
|
+
r = runners.first
|
|
89
|
+
r[:proc].call(v)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
else
|
|
93
|
+
sleep(THROTTLE_MS)
|
|
94
|
+
Aromancer::Routes.resume
|
|
95
|
+
end
|
|
96
|
+
Aromancer::Cli.instance.ui_busy = false
|
|
97
|
+
Aromancer::Cli.instance.last_render = Time.now
|
|
98
|
+
sleep(THROTTLE_MS)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def start_ws_thread
|
|
104
|
+
return if @ws_busy
|
|
105
|
+
@ws_busy = true
|
|
106
|
+
self.ws_thread&.exit
|
|
107
|
+
self.ws_thread&.kill
|
|
108
|
+
self.ws_thread = Thread.new do
|
|
109
|
+
Aromancer::Websocket.instance.disconnect
|
|
110
|
+
loop do
|
|
111
|
+
player = Aromancer::Storage.get_player
|
|
112
|
+
if player.nil? ||
|
|
113
|
+
player["active_legend_id"].nil?
|
|
114
|
+
@ws_busy = true
|
|
115
|
+
Aromancer::Websocket.instance.disconnect
|
|
116
|
+
elsif !player["api_key"].nil? &&
|
|
117
|
+
!player["active_legend_id"].nil? &&
|
|
118
|
+
(Aromancer::Websocket.instance.socket.nil? || Aromancer::Websocket.instance.socket.closed?)
|
|
119
|
+
# attempt websocket connection
|
|
120
|
+
@ws_busy = true
|
|
121
|
+
Aromancer::Websocket.instance.connect
|
|
122
|
+
if Aromancer::Storage.get_arena.nil?
|
|
123
|
+
Aromancer::Api.load_arena
|
|
124
|
+
sleep(1)
|
|
125
|
+
Aromancer::Cli.instance.start_ui_thread(true)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
@ws_busy = false
|
|
129
|
+
sleep(1)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
data/lib/aromancer/routes.rb
CHANGED
|
@@ -46,24 +46,10 @@ module Aromancer
|
|
|
46
46
|
).first
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def self.arena_data
|
|
50
|
-
arena = Aromancer::Storage.get_arena
|
|
51
|
-
if arena.nil?
|
|
52
|
-
Aromancer::Api.load_arena
|
|
53
|
-
sleep(1)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
if arena.nil?
|
|
57
|
-
Aromancer.print_last_error("routes.legend.arena_failed")
|
|
58
|
-
Aromancer::Prompt.p.ask(I18n.t("shared.key_press"))
|
|
59
|
-
Aromancer::Api.set_active_legend_id(nil)
|
|
60
|
-
else
|
|
61
|
-
arena
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
49
|
def self.authentication
|
|
66
|
-
|
|
50
|
+
unless Aromancer::Storage.get_player.nil? ||
|
|
51
|
+
Aromancer::Storage.get_player["api_key"].nil?
|
|
52
|
+
|
|
67
53
|
Aromancer::Storage.set_signed_out_flag(false)
|
|
68
54
|
return main_menu
|
|
69
55
|
end
|
|
@@ -87,6 +73,9 @@ module Aromancer
|
|
|
87
73
|
}},
|
|
88
74
|
{value: :configure, proc: Proc.new{
|
|
89
75
|
configure
|
|
76
|
+
}},
|
|
77
|
+
{value: :exit, proc: Proc.new{
|
|
78
|
+
exit
|
|
90
79
|
}}
|
|
91
80
|
]
|
|
92
81
|
Thread.main[:route] = __method__.to_sym
|
|
@@ -94,7 +83,7 @@ module Aromancer
|
|
|
94
83
|
|
|
95
84
|
def self.configure
|
|
96
85
|
cls
|
|
97
|
-
|
|
86
|
+
Aromancer.print_large_text(Thread.main[:route].to_s)
|
|
98
87
|
Aromancer::Prompt.say(I18n.t("routes.configure.title", name: Aromancer.to_s.downcase))
|
|
99
88
|
[
|
|
100
89
|
Aromancer::Storage.get_server_url,
|
|
@@ -210,6 +199,7 @@ module Aromancer
|
|
|
210
199
|
|
|
211
200
|
return authentication if player.nil?
|
|
212
201
|
|
|
202
|
+
Aromancer.print_large_text
|
|
213
203
|
Thread.main[:menu_options][__method__.to_sym] ||= [
|
|
214
204
|
{name: I18n.t("routes.main_menu.new_game"), value: :new},
|
|
215
205
|
{name: I18n.t("routes.main_menu.load_game"), value: :load},
|
|
@@ -252,7 +242,7 @@ module Aromancer
|
|
|
252
242
|
}},
|
|
253
243
|
{value: :exit, proc: Proc.new{
|
|
254
244
|
exit
|
|
255
|
-
}}
|
|
245
|
+
}}
|
|
256
246
|
]
|
|
257
247
|
Thread.main[:route] = __method__.to_sym
|
|
258
248
|
end
|
|
@@ -277,18 +267,8 @@ module Aromancer
|
|
|
277
267
|
]
|
|
278
268
|
Thread.main[:menu_runners][__method__.to_sym] = [
|
|
279
269
|
{value: :continue, proc: Proc.new{
|
|
280
|
-
Aromancer::Storage.instance.clear_cache!
|
|
281
270
|
Aromancer::Api.create_legend(params)
|
|
282
271
|
legend_menu
|
|
283
|
-
# Aromancer::Api.get_legends
|
|
284
|
-
|
|
285
|
-
# unless active_legend.nil? || active_legend["id"] != Aromancer::Storage.get_player["active_legend_id"]
|
|
286
|
-
# Aromancer.print_last_error
|
|
287
|
-
# sleep(1)
|
|
288
|
-
# main_menu
|
|
289
|
-
# else
|
|
290
|
-
# legend_menu
|
|
291
|
-
# end
|
|
292
272
|
}},
|
|
293
273
|
{value: :cancel, proc: Proc.new{
|
|
294
274
|
Aromancer::Prompt.say(I18n.t("routes.new_game.cancelled"))
|
|
@@ -306,7 +286,6 @@ module Aromancer
|
|
|
306
286
|
|
|
307
287
|
# if legend_array.nil?, load player's legends
|
|
308
288
|
if legend_array.nil?
|
|
309
|
-
Aromancer::Storage.instance.clear_cache!
|
|
310
289
|
Aromancer::Api.get_legends
|
|
311
290
|
legend_array = Aromancer::Storage.get_legends
|
|
312
291
|
unless legend_array.any?
|
|
@@ -328,20 +307,19 @@ module Aromancer
|
|
|
328
307
|
end
|
|
329
308
|
|
|
330
309
|
Thread.main[:menu_runners][__method__.to_sym] = [
|
|
331
|
-
{value: :back, proc: Proc.new{
|
|
310
|
+
{value: :back, proc: Proc.new{
|
|
311
|
+
Aromancer::Api.set_active_legend_id(nil)
|
|
312
|
+
main_menu
|
|
313
|
+
}},
|
|
332
314
|
] + legend_array.map{|l|
|
|
333
315
|
{
|
|
334
316
|
value: l["id"],
|
|
335
317
|
proc: Proc.new{
|
|
336
318
|
Aromancer::Api.set_active_legend_id(l["id"])
|
|
319
|
+
sleep(1)
|
|
320
|
+
Aromancer::Api.get_legends
|
|
337
321
|
|
|
338
|
-
|
|
339
|
-
Aromancer.print_last_error
|
|
340
|
-
sleep(1)
|
|
341
|
-
main_menu
|
|
342
|
-
else
|
|
343
|
-
legend_menu
|
|
344
|
-
end
|
|
322
|
+
legend_menu
|
|
345
323
|
}
|
|
346
324
|
}
|
|
347
325
|
}
|
|
@@ -370,61 +348,80 @@ module Aromancer
|
|
|
370
348
|
|
|
371
349
|
def self.legend_menu
|
|
372
350
|
cls
|
|
373
|
-
legend
|
|
374
|
-
|
|
375
|
-
legend_array = Aromancer::Storage.get_legends
|
|
376
351
|
al = active_legend
|
|
377
|
-
|
|
378
|
-
|
|
352
|
+
al_status = ((al || {})["status"] || "").to_sym
|
|
353
|
+
arena = Aromancer::Storage.get_arena
|
|
354
|
+
if !al_status.nil? &&
|
|
355
|
+
![:started, :paused].include?(al_status) &&
|
|
356
|
+
!al.nil? &&
|
|
357
|
+
!arena.nil?
|
|
358
|
+
|
|
359
|
+
stream(display_only: true) # display entire stream
|
|
360
|
+
Aromancer::Prompt.print_divider(al["value_display"])
|
|
361
|
+
Aromancer::Prompt.say(arena["title"])
|
|
362
|
+
Aromancer::Prompt.say(arena["players"].map{|p| "#{p["alias"]}(#{p["status"]}): #{p["score"]}"}.join(" | "))
|
|
363
|
+
Thread.main[:route] = __method__.to_sym
|
|
364
|
+
case al_status
|
|
365
|
+
when :created
|
|
366
|
+
Aromancer::Api.get_legends
|
|
367
|
+
|
|
379
368
|
Thread.main[:menu_options][__method__.to_sym] = [
|
|
380
369
|
{name: I18n.t("shared.key_press"), value: :key_press}
|
|
381
370
|
]
|
|
382
371
|
Thread.main[:menu_runners][__method__.to_sym] = [
|
|
383
372
|
{value: :key_press, proc: Proc.new{
|
|
384
|
-
Aromancer::Prompt.say(I18n.t("routes.legend.
|
|
373
|
+
Aromancer::Prompt.say(I18n.t("routes.legend.returning_to_", route: :legends))
|
|
385
374
|
Aromancer::Api.set_active_legend_id(nil)
|
|
375
|
+
sleep(1)
|
|
386
376
|
legends
|
|
387
377
|
}}
|
|
388
378
|
]
|
|
389
|
-
|
|
390
|
-
return
|
|
391
|
-
elsif al["status"] == "created"
|
|
379
|
+
when :complete
|
|
392
380
|
Thread.main[:menu_options][__method__.to_sym] = [
|
|
393
|
-
{name:
|
|
381
|
+
{name: I18n.t("shared.key_press"), value: :key_press}
|
|
394
382
|
]
|
|
395
383
|
Thread.main[:menu_runners][__method__.to_sym] = [
|
|
396
|
-
{value: :
|
|
397
|
-
|
|
384
|
+
{value: :key_press, proc: Proc.new{
|
|
385
|
+
Aromancer::Prompt.say(I18n.t("routes.legend.returning_to_", route: :legends))
|
|
398
386
|
Aromancer::Api.set_active_legend_id(nil)
|
|
399
387
|
legends
|
|
400
388
|
}}
|
|
401
389
|
]
|
|
402
|
-
Thread.main[:route] = __method__.to_sym
|
|
403
|
-
return
|
|
404
|
-
elsif active_legend["player"] && (active_legend["player"]["words"] || []).count == 0
|
|
405
|
-
Aromancer::Api.load_arena
|
|
406
|
-
return
|
|
407
390
|
end
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
391
|
+
return
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
arena = Aromancer::Storage.get_arena
|
|
395
|
+
if arena.nil? || arena["turn_player"].nil?
|
|
396
|
+
Aromancer::Prompt.say(I18n.t("shared.waiting"))
|
|
397
|
+
Thread.main[:menu_options][__method__.to_sym] = []
|
|
398
|
+
Thread.main[:menu_runners][__method__.to_sym] = []
|
|
399
|
+
sleep(1)
|
|
400
|
+
Aromancer::Api.get_legends
|
|
401
|
+
Aromancer::Api.load_arena
|
|
402
|
+
return
|
|
412
403
|
end
|
|
413
404
|
|
|
405
|
+
legend
|
|
406
|
+
|
|
407
|
+
Thread.main[:route] = __method__.to_sym
|
|
408
|
+
|
|
414
409
|
hide_sentences_pref = Aromancer::Storage.get_preference(:hide_sentences)
|
|
415
410
|
hide_sentences_pref_value = "#{hide_sentences_pref ? "" : "hide_"}signed_sentences".to_sym
|
|
416
411
|
hide_stream_pref = Aromancer::Storage.get_preference(:hide_stream)
|
|
417
412
|
hide_stream_pref_value = "#{hide_stream_pref ? "" : "hide_"}title".to_sym
|
|
418
|
-
|
|
419
|
-
Thread.main[:route] = __method__.to_sym
|
|
420
413
|
Thread.main[:menu_options][__method__.to_sym] = [
|
|
421
|
-
{name: I18n.t("routes.legend.unspoken_words"), value: :words},
|
|
422
|
-
{name: I18n.t("routes.legend.spoken_words"), value: :spoken_words},
|
|
423
|
-
{name: I18n.t("routes.legend.unsigned_sentences"), value: :unsigned_sentences},
|
|
424
414
|
{name: I18n.t("routes.legend.#{hide_sentences_pref_value}"), value: hide_sentences_pref_value},
|
|
425
415
|
{name: I18n.t("routes.stream.#{hide_stream_pref_value}"), value: hide_stream_pref_value},
|
|
426
416
|
{name: I18n.t("routes.main_menu.title"), value: :main_menu}
|
|
427
417
|
]
|
|
418
|
+
if arena["turn_player"]["id"] == Aromancer::Storage.get_player["id"]
|
|
419
|
+
[
|
|
420
|
+
{name: I18n.t("routes.legend.unspoken_words"), value: :words},
|
|
421
|
+
{name: I18n.t("routes.legend.spoken_words"), value: :spoken_words},
|
|
422
|
+
{name: I18n.t("routes.legend.unsigned_sentences"), value: :unsigned_sentences}
|
|
423
|
+
].reverse.each{|mo| Thread.main[:menu_options][__method__.to_sym].insert(0, mo)}
|
|
424
|
+
end
|
|
428
425
|
|
|
429
426
|
Thread.main[:menu_runners][__method__.to_sym] = [
|
|
430
427
|
{value: :words, proc: Proc.new{ words }},
|
|
@@ -447,48 +444,7 @@ module Aromancer
|
|
|
447
444
|
|
|
448
445
|
def self.legend
|
|
449
446
|
Aromancer::Prompt.say(I18n.t("shared.navigate", route: :legend)) if Aromancer::Storage.get_preference(:debug)
|
|
450
|
-
Aromancer::
|
|
451
|
-
arena = arena_data
|
|
452
|
-
al = active_legend
|
|
453
|
-
al_status = ((al || {})["status"] || "").to_sym
|
|
454
|
-
if !al.nil? &&
|
|
455
|
-
[:created, :complete].include?(al_status)
|
|
456
|
-
|
|
457
|
-
stream(display_only: true) # display entire stream
|
|
458
|
-
Aromancer::Prompt.print_divider(al["value_display"])
|
|
459
|
-
Aromancer::Prompt.say(arena["title"])
|
|
460
|
-
Aromancer::Prompt.say(arena["players"].map{|p| "#{p["alias"]}(#{p["score"]})"}.join(" | "))
|
|
461
|
-
|
|
462
|
-
if al_status == :complete
|
|
463
|
-
Thread.main[:menu_options][:legend_menu] = [
|
|
464
|
-
{name: I18n.t("shared.key_press"), value: :key_press}
|
|
465
|
-
]
|
|
466
|
-
Thread.main[:menu_runners][:legend_menu] = [
|
|
467
|
-
{value: :key_press, proc: Proc.new{
|
|
468
|
-
Aromancer::Prompt.say(I18n.t("routes.legend.returning_to_main"))
|
|
469
|
-
Aromancer::Api.set_active_legend_id(nil)
|
|
470
|
-
legends
|
|
471
|
-
}}
|
|
472
|
-
]
|
|
473
|
-
else
|
|
474
|
-
Aromancer::Api.get_legends
|
|
475
|
-
|
|
476
|
-
Thread.main[:menu_options][:legend_menu] = [
|
|
477
|
-
{name: I18n.t("shared.back"), value: :back},
|
|
478
|
-
{name: I18n.t("shared.key_press"), value: :key_press}
|
|
479
|
-
]
|
|
480
|
-
Thread.main[:menu_runners][:legend_menu] = [
|
|
481
|
-
{value: :back, proc: Proc.new{
|
|
482
|
-
Aromancer::Prompt.say(I18n.t("routes.legend.returning_to_main"))
|
|
483
|
-
Aromancer::Api.set_active_legend_id(nil)
|
|
484
|
-
legends
|
|
485
|
-
}},
|
|
486
|
-
{value: :key_press, proc: Proc.new{ legend_menu }}
|
|
487
|
-
]
|
|
488
|
-
end
|
|
489
|
-
return
|
|
490
|
-
end
|
|
491
|
-
|
|
447
|
+
arena = Aromancer::Storage.get_arena
|
|
492
448
|
return if arena.nil? || arena["turn_player"].nil?
|
|
493
449
|
|
|
494
450
|
turn_player = arena["turn_player"]
|
|
@@ -578,7 +534,12 @@ module Aromancer
|
|
|
578
534
|
cls
|
|
579
535
|
legend
|
|
580
536
|
|
|
581
|
-
arena =
|
|
537
|
+
arena = Aromancer::Storage.get_arena
|
|
538
|
+
if arena["player"].nil? || arena["player"]["words"].nil?
|
|
539
|
+
Aromancer::Api.load_arena
|
|
540
|
+
sleep(1)
|
|
541
|
+
main_menu
|
|
542
|
+
end
|
|
582
543
|
Thread.main[:menu_options][__method__.to_sym] = [
|
|
583
544
|
{name: I18n.t("shared.back"), value: :back}
|
|
584
545
|
] + arena["player"]["words"].map{|w| {name: w["value_display"], value: w["id"]}}
|
|
@@ -597,7 +558,7 @@ module Aromancer
|
|
|
597
558
|
cls
|
|
598
559
|
legend
|
|
599
560
|
|
|
600
|
-
arena =
|
|
561
|
+
arena = Aromancer::Storage.get_arena
|
|
601
562
|
Thread.main[:menu_options][__method__.to_sym] = [
|
|
602
563
|
{name: I18n.t("shared.back"), value: :back}
|
|
603
564
|
] + arena["scroll_words"].map{|w| {name: w["value_display"], value: w["id"]}}
|
|
@@ -616,7 +577,7 @@ module Aromancer
|
|
|
616
577
|
cls
|
|
617
578
|
legend
|
|
618
579
|
|
|
619
|
-
arena =
|
|
580
|
+
arena = Aromancer::Storage.get_arena
|
|
620
581
|
Thread.main[:menu_options][__method__.to_sym] = [
|
|
621
582
|
{name: I18n.t("shared.back"), value: :back}
|
|
622
583
|
] + arena["sentences"].map{|s| {name: s["value_display"], value: s["id"]}}
|
|
@@ -646,11 +607,12 @@ module Aromancer
|
|
|
646
607
|
selected_word = possibilities["word"]
|
|
647
608
|
for_type = possibilities["for_type"].to_sym
|
|
648
609
|
|
|
649
|
-
arena =
|
|
610
|
+
arena = Aromancer::Storage.get_arena
|
|
650
611
|
player_words = arena["player"]["words"]
|
|
651
612
|
|
|
652
613
|
choices = [{name: I18n.t("shared.back"), value: :back}]
|
|
653
|
-
if for_type == :player_word
|
|
614
|
+
if for_type == :player_word &&
|
|
615
|
+
arena["turn_player"]["id"] == Aromancer::Storage.get_player["id"]
|
|
654
616
|
|
|
655
617
|
# show place on scroll option if selected word is from player's words
|
|
656
618
|
choices << {
|
|
@@ -659,8 +621,11 @@ module Aromancer
|
|
|
659
621
|
}
|
|
660
622
|
end
|
|
661
623
|
|
|
662
|
-
|
|
624
|
+
unless arena["turn_player"]["id"] != Aromancer::Storage.get_player["id"]
|
|
625
|
+
choices += options.map{|o| {name: "#{o["humanized_title"]} -> weight: #{o["total_weight"]}", value: o}}
|
|
626
|
+
end
|
|
663
627
|
|
|
628
|
+
_muh_method = __method__.to_sym
|
|
664
629
|
Thread.main[:menu_options][__method__.to_sym] = choices
|
|
665
630
|
Thread.main[:menu_runners][__method__.to_sym] = [
|
|
666
631
|
{value: :back, proc: Proc.new{
|
|
@@ -674,12 +639,24 @@ module Aromancer
|
|
|
674
639
|
end
|
|
675
640
|
}},
|
|
676
641
|
{value: :player_word, proc: Proc.new{
|
|
642
|
+
Aromancer::Prompt.say(I18n.t("shared.waiting"))
|
|
643
|
+
Thread.main[:menu_options][_muh_method] = []
|
|
644
|
+
Thread.main[:menu_runners][_muh_method] = []
|
|
677
645
|
Aromancer::Api.submit_turn(request_uuid)
|
|
678
|
-
|
|
646
|
+
# websockets will trigger this for other player after turn is submitted
|
|
647
|
+
Aromancer::Api.get_legends
|
|
648
|
+
Aromancer::Api.load_arena
|
|
649
|
+
sleep(1)
|
|
679
650
|
}},
|
|
680
651
|
{value: nil, proc: Proc.new{|o|
|
|
652
|
+
Aromancer::Prompt.say(I18n.t("shared.waiting"))
|
|
653
|
+
Thread.main[:menu_options][_muh_method] = []
|
|
654
|
+
Thread.main[:menu_runners][_muh_method] = []
|
|
681
655
|
Aromancer::Api.submit_turn(request_uuid, {option_uuid: o[:uuid.to_s]})
|
|
682
|
-
|
|
656
|
+
# websockets will trigger this for other player after turn is submitted
|
|
657
|
+
Aromancer::Api.get_legends
|
|
658
|
+
Aromancer::Api.load_arena
|
|
659
|
+
sleep(1)
|
|
683
660
|
}}
|
|
684
661
|
]
|
|
685
662
|
Thread.main[:route_params] = [selected_word_id]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
serve.rb
|
|
6
|
+
|
|
7
|
+
aromancer serve functionality.
|
|
8
|
+
|
|
9
|
+
by i2097i
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
module Aromancer
|
|
14
|
+
class Serve
|
|
15
|
+
SERVER_NAME = :"#{Aromancer.to_s.downcase}_serve".to_s
|
|
16
|
+
|
|
17
|
+
def self.run
|
|
18
|
+
unless Dir.exist?(serve_dir)
|
|
19
|
+
system(:"git clone git@github.com:arowmancy/#{SERVER_NAME}.git #{serve_dir}".to_s)
|
|
20
|
+
end
|
|
21
|
+
FileUtils.chdir serve_dir do
|
|
22
|
+
branch = "v#{Aromancer::VERSION}"
|
|
23
|
+
system(:"git checkout #{branch}".to_s)
|
|
24
|
+
system(:"git pull origin #{branch}".to_s)
|
|
25
|
+
system(:"bin/setup".to_s)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def self.serve_dir
|
|
32
|
+
File.join(Aromancer.home_directory, SERVER_NAME)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/aromancer/server.rb
CHANGED
data/lib/aromancer/storage.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
=begin
|
|
2
4
|
|
|
3
5
|
storage.rb
|
|
@@ -12,18 +14,116 @@ module Aromancer
|
|
|
12
14
|
class Storage
|
|
13
15
|
include Singleton
|
|
14
16
|
|
|
17
|
+
VALID_KEYS = [
|
|
18
|
+
:arena,
|
|
19
|
+
:last_error,
|
|
20
|
+
:legends,
|
|
21
|
+
:player,
|
|
22
|
+
:preference_debug,
|
|
23
|
+
:preference_force_ssl,
|
|
24
|
+
:preference_hide_sentences,
|
|
25
|
+
:preference_hide_stream,
|
|
26
|
+
:server_url_host,
|
|
27
|
+
:server_url_port,
|
|
28
|
+
:server_url_scheme,
|
|
29
|
+
:signed_out_flag,
|
|
30
|
+
:stream,
|
|
31
|
+
:websocket_path,
|
|
32
|
+
:websocket_scheme
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
PERSISTED_KEYS = [
|
|
36
|
+
:last_error,
|
|
37
|
+
:player,
|
|
38
|
+
:preference_debug,
|
|
39
|
+
:preference_force_ssl,
|
|
40
|
+
:preference_hide_sentences,
|
|
41
|
+
:preference_hide_stream,
|
|
42
|
+
:server_url_host,
|
|
43
|
+
:server_url_port,
|
|
44
|
+
:server_url_scheme,
|
|
45
|
+
:websocket_path,
|
|
46
|
+
:websocket_scheme
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
URI_KEYS = [
|
|
50
|
+
:scheme,
|
|
51
|
+
:host,
|
|
52
|
+
:port
|
|
53
|
+
]
|
|
54
|
+
|
|
15
55
|
DEFAULT_SERVER = "http://127.0.0.1"
|
|
16
56
|
|
|
17
|
-
|
|
57
|
+
DEFAULT_PREFERENCES = {
|
|
58
|
+
preference_debug: false,
|
|
59
|
+
preference_force_ssl: false,
|
|
60
|
+
preference_hide_sentences: true,
|
|
61
|
+
preference_hide_stream: true,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
attr_accessor :storage_open, :cache, :clear_flag, :parser_error
|
|
18
65
|
|
|
19
66
|
def initialize
|
|
67
|
+
reload!
|
|
68
|
+
ensure_default_preferences_exist
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def ensure_default_preferences_exist
|
|
72
|
+
DEFAULT_PREFERENCES.keys.each{|d_key|
|
|
73
|
+
current_value = get_key(d_key)
|
|
74
|
+
if current_value.nil? || ![TrueClass, FalseClass].include?(current_value.class)
|
|
75
|
+
set_key(d_key.to_s, DEFAULT_PREFERENCES[d_key])
|
|
76
|
+
end
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def reload!
|
|
81
|
+
@storage_open = false
|
|
82
|
+
@clear_flag = false
|
|
83
|
+
@parser_error = nil
|
|
20
84
|
clear_cache!
|
|
21
85
|
FileUtils.mkdir_p(Aromancer.home_directory)
|
|
22
86
|
end
|
|
23
87
|
|
|
24
88
|
def clear_cache!
|
|
89
|
+
if @storage_open
|
|
90
|
+
@clear_flag = true
|
|
91
|
+
return
|
|
92
|
+
end
|
|
93
|
+
@clear_flag = false
|
|
25
94
|
@storage_open = false
|
|
26
|
-
|
|
95
|
+
|
|
96
|
+
@cache = {} # clear'd
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def self.snapshot_config
|
|
100
|
+
current_config = {}
|
|
101
|
+
|
|
102
|
+
PERSISTED_KEYS.each{|p_key|
|
|
103
|
+
current_config[p_key] = Aromancer::Storage.instance.get_key(p_key)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
current_config
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def self.valid_config?(config)
|
|
110
|
+
return false unless config.kind_of?(Hash)
|
|
111
|
+
|
|
112
|
+
config.keys.all?{|k| PERSISTED_KEYS.include?(k.to_sym)}
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.restore_config(config)
|
|
116
|
+
return nil unless valid_config?(config)
|
|
117
|
+
PERSISTED_KEYS.each{|p_key|
|
|
118
|
+
Aromancer::Storage.instance.set_key(p_key, config[p_key])
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def self.recreate!
|
|
123
|
+
current_config = snapshot_config
|
|
124
|
+
FileUtils.rm_rf(storage_filepath)
|
|
125
|
+
Aromancer::Storage.instance.reload!
|
|
126
|
+
restore_config(current_config)
|
|
27
127
|
end
|
|
28
128
|
|
|
29
129
|
def self.storage_filepath
|
|
@@ -50,33 +150,33 @@ module Aromancer
|
|
|
50
150
|
|
|
51
151
|
def self.get_preference(preference, default: nil)
|
|
52
152
|
p_key = "preference_#{preference}"
|
|
53
|
-
|
|
54
|
-
if
|
|
55
|
-
instance.set_key(p_key, default)
|
|
56
|
-
|
|
153
|
+
pref = Aromancer::Storage.instance.get_key(p_key)
|
|
154
|
+
if pref.nil? && !default.nil?
|
|
155
|
+
Aromancer::Storage.instance.set_key(p_key, default)
|
|
156
|
+
pref = Aromancer::Storage.instance.get_key(p_key)
|
|
57
157
|
end
|
|
58
|
-
|
|
158
|
+
pref
|
|
59
159
|
end
|
|
60
160
|
|
|
61
161
|
def self.set_preference(preference, value)
|
|
62
162
|
p_key = "preference_#{preference}"
|
|
63
|
-
instance.set_key(p_key, value)
|
|
163
|
+
Aromancer::Storage.instance.set_key(p_key, value)
|
|
64
164
|
end
|
|
65
165
|
|
|
66
166
|
def self.toggle_preference(key)
|
|
67
|
-
v = get_preference(key)
|
|
167
|
+
v = get_preference(key, default: DEFAULT_PREFERENCES["preference_#{key}"])
|
|
68
168
|
set_preference(key, !v)
|
|
69
169
|
end
|
|
70
170
|
|
|
71
171
|
def self.toggle_force_ssl
|
|
72
172
|
toggle_preference(:force_ssl)
|
|
73
173
|
v = get_preference(:force_ssl)
|
|
74
|
-
|
|
75
|
-
|
|
174
|
+
Aromancer::Storage.set_key(:server_url_scheme, "http#{v ? :s : ""}")
|
|
175
|
+
Aromancer::Storage.set_key(:websocket_scheme, "ws#{v ? :s : ""}")
|
|
76
176
|
end
|
|
77
177
|
|
|
78
178
|
def self.set_signed_out_flag(flag)
|
|
79
|
-
|
|
179
|
+
instance.set_key(:signed_out_flag, flag)
|
|
80
180
|
end
|
|
81
181
|
|
|
82
182
|
def self.get_signed_out_flag
|
|
@@ -84,7 +184,7 @@ module Aromancer
|
|
|
84
184
|
end
|
|
85
185
|
|
|
86
186
|
def self.set_player(player_hash)
|
|
87
|
-
|
|
187
|
+
instance.set_key(:player, player_hash)
|
|
88
188
|
end
|
|
89
189
|
|
|
90
190
|
def self.get_player
|
|
@@ -92,7 +192,7 @@ module Aromancer
|
|
|
92
192
|
end
|
|
93
193
|
|
|
94
194
|
def self.set_legends(legends_array)
|
|
95
|
-
|
|
195
|
+
instance.set_key(:legends, legends_array)
|
|
96
196
|
end
|
|
97
197
|
|
|
98
198
|
def self.get_legends
|
|
@@ -100,7 +200,7 @@ module Aromancer
|
|
|
100
200
|
end
|
|
101
201
|
|
|
102
202
|
def self.set_arena(arena_hash)
|
|
103
|
-
|
|
203
|
+
instance.set_key(:arena, arena_hash)
|
|
104
204
|
end
|
|
105
205
|
|
|
106
206
|
def self.get_arena
|
|
@@ -108,7 +208,7 @@ module Aromancer
|
|
|
108
208
|
end
|
|
109
209
|
|
|
110
210
|
def self.set_stream(stream_array)
|
|
111
|
-
|
|
211
|
+
instance.set_key(:stream, stream_array)
|
|
112
212
|
end
|
|
113
213
|
|
|
114
214
|
def self.get_stream
|
|
@@ -116,25 +216,18 @@ module Aromancer
|
|
|
116
216
|
end
|
|
117
217
|
|
|
118
218
|
def self.set_last_error(error_hash)
|
|
119
|
-
|
|
219
|
+
instance.set_key(:last_error, error_hash)
|
|
120
220
|
end
|
|
121
221
|
|
|
122
222
|
def self.get_last_error
|
|
123
223
|
Aromancer::Storage.instance.get_key(:last_error)
|
|
124
224
|
end
|
|
125
225
|
|
|
126
|
-
URI_KEYS = [
|
|
127
|
-
:scheme,
|
|
128
|
-
:host,
|
|
129
|
-
:port
|
|
130
|
-
]
|
|
131
|
-
|
|
132
226
|
def self.set_server_url(server_url)
|
|
133
227
|
uri = URI.parse(server_url)
|
|
134
228
|
if uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
|
|
135
229
|
URI_KEYS.each{|k|
|
|
136
|
-
|
|
137
|
-
Aromancer::Storage.instance.set_key("server_url_#{k}", uri.select(k).first)
|
|
230
|
+
instance.set_key("server_url_#{k}", uri.select(k).first)
|
|
138
231
|
}
|
|
139
232
|
elsif get_server_url.nil?
|
|
140
233
|
set_server_url(DEFAULT_SERVER)
|
|
@@ -159,12 +252,12 @@ module Aromancer
|
|
|
159
252
|
def self.get_websocket_url
|
|
160
253
|
# default scheme is ws
|
|
161
254
|
w_scheme = Aromancer::Storage.instance.get_key(:websocket_scheme)
|
|
162
|
-
|
|
255
|
+
instance.set_key(:websocket_scheme, :ws) if w_scheme.nil?
|
|
163
256
|
w_scheme = Aromancer::Storage.instance.get_key(:websocket_scheme)
|
|
164
257
|
|
|
165
258
|
# default path is broadcast
|
|
166
259
|
w_path = Aromancer::Storage.instance.get_key(:websocket_path)
|
|
167
|
-
|
|
260
|
+
instance.set_key(:websocket_path, :broadcast) if w_path.nil?
|
|
168
261
|
w_path = Aromancer::Storage.instance.get_key(:websocket_path)
|
|
169
262
|
|
|
170
263
|
# asserts host and port not nil
|
|
@@ -180,7 +273,9 @@ module Aromancer
|
|
|
180
273
|
|
|
181
274
|
# ensure default for key exists
|
|
182
275
|
@cache[key] = {value: nil, persisted: false} unless @cache.keys.include?(key)
|
|
183
|
-
|
|
276
|
+
if false && (@cache[:preference_debug.to_s] || {value: DEFAULT_PREFERENCES[:preference_debug]})[:value]
|
|
277
|
+
Aromancer::Prompt.say("#{__method__} > @cache[#{key}]=#{@cache[key]}")
|
|
278
|
+
end
|
|
184
279
|
# return cache value if storage open or the cache value is persisted
|
|
185
280
|
return @cache[key][:value] if @storage_open || @cache[key][:persisted]
|
|
186
281
|
|
|
@@ -188,12 +283,17 @@ module Aromancer
|
|
|
188
283
|
@storage_open = true
|
|
189
284
|
storage_contents = {}
|
|
190
285
|
begin
|
|
286
|
+
@parser_error = nil
|
|
191
287
|
# read storage
|
|
192
|
-
storage_contents = JSON.parse(File.read(Aromancer::Storage.storage_filepath))
|
|
288
|
+
storage_contents = JSON.parse(File.read(Aromancer::Storage.storage_filepath, encoding: "UTF-8"))
|
|
193
289
|
rescue StandardError => e
|
|
194
290
|
@storage_open = false
|
|
195
|
-
|
|
196
|
-
|
|
291
|
+
if @parser_error.nil?
|
|
292
|
+
@parser_error = e
|
|
293
|
+
return get_key(key)
|
|
294
|
+
else
|
|
295
|
+
raise @parser_error
|
|
296
|
+
end
|
|
197
297
|
end
|
|
198
298
|
|
|
199
299
|
# only update the cache value if present in storage
|
|
@@ -203,20 +303,26 @@ module Aromancer
|
|
|
203
303
|
@cache[key][:persisted] = false
|
|
204
304
|
end
|
|
205
305
|
|
|
306
|
+
value = @cache[key][:value]
|
|
206
307
|
@storage_open = false
|
|
207
|
-
@
|
|
308
|
+
clear_cache! if @clear_flag
|
|
309
|
+
return value
|
|
208
310
|
end
|
|
209
311
|
|
|
210
312
|
def set_key(key, value)
|
|
211
313
|
key = key.to_s
|
|
212
314
|
|
|
213
315
|
# ensure default for key exists
|
|
214
|
-
@cache[key] = {value:
|
|
316
|
+
@cache[key] = {value: value, persisted: false} unless @cache.keys.include?(key)
|
|
215
317
|
|
|
216
318
|
# assign new cache value and set persisted to false
|
|
217
319
|
@cache[key][:value] = value
|
|
218
320
|
@cache[key][:persisted] = false
|
|
219
321
|
|
|
322
|
+
if @storage_open && (@cache[:preference_debug.to_s] || {value: DEFAULT_PREFERENCES[:preference_debug]})[:value]
|
|
323
|
+
puts Thread.current.backtrace
|
|
324
|
+
Aromancer::Prompt.say("#{__method__} > @cache[#{key}]=#{@cache[key]}")
|
|
325
|
+
end
|
|
220
326
|
# return if storage open
|
|
221
327
|
# non-persisted cache values update next cycle
|
|
222
328
|
return if @storage_open
|
|
@@ -225,12 +331,17 @@ module Aromancer
|
|
|
225
331
|
@storage_open = true
|
|
226
332
|
storage_contents = {}
|
|
227
333
|
begin
|
|
334
|
+
@parser_error = nil
|
|
228
335
|
# read storage
|
|
229
|
-
storage_contents = JSON.parse(File.read(Aromancer::Storage.storage_filepath))
|
|
336
|
+
storage_contents = JSON.parse(File.read(Aromancer::Storage.storage_filepath, encoding: "UTF-8"))
|
|
230
337
|
rescue StandardError => e
|
|
231
338
|
@storage_open = false
|
|
232
|
-
|
|
233
|
-
|
|
339
|
+
if @parser_error.nil?
|
|
340
|
+
@parser_error = e
|
|
341
|
+
return get_key(key)
|
|
342
|
+
else
|
|
343
|
+
raise @parser_error
|
|
344
|
+
end
|
|
234
345
|
end
|
|
235
346
|
|
|
236
347
|
# update storage and cache
|
|
@@ -246,8 +357,13 @@ module Aromancer
|
|
|
246
357
|
f.write(storage_contents.to_json)
|
|
247
358
|
end
|
|
248
359
|
|
|
360
|
+
if (@cache[:preference_debug.to_s] || {value: DEFAULT_PREFERENCES[:preference_debug]})[:value]
|
|
361
|
+
Aromancer::Prompt.say("#{__method__} > @cache[#{key}]=#{@cache[key]}")
|
|
362
|
+
end
|
|
363
|
+
|
|
249
364
|
# close storage
|
|
250
365
|
@storage_open = false
|
|
366
|
+
clear_cache! if @clear_flag
|
|
251
367
|
end
|
|
252
368
|
end
|
|
253
369
|
end
|
data/lib/aromancer/version.rb
CHANGED
data/lib/aromancer/websocket.rb
CHANGED
|
@@ -22,9 +22,18 @@ module Aromancer
|
|
|
22
22
|
|
|
23
23
|
attr_accessor :socket
|
|
24
24
|
|
|
25
|
+
def self.channel_identifier
|
|
26
|
+
{identifier: {channel: :PlayerChannel.to_s, id: Aromancer::Storage.get_player["id"]}.to_json}
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
def connect
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
if !self.socket.nil? && self.socket.closed?
|
|
31
|
+
disconnect
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
return if !self.socket.nil? ||
|
|
35
|
+
Aromancer::Storage.get_player["api_key"].nil? ||
|
|
36
|
+
Aromancer::Storage.get_player["active_legend_id"].nil?
|
|
28
37
|
|
|
29
38
|
begin
|
|
30
39
|
self.socket = WebSocket::Client::Simple.connect(Aromancer::Storage.get_websocket_url, {headers: Aromancer::Server.auth_header})
|
|
@@ -45,8 +54,10 @@ module Aromancer
|
|
|
45
54
|
legend_id = payload["message"]["id"]
|
|
46
55
|
lid = Aromancer::Storage.get_player&.symbolize_keys[:active_legend_id]
|
|
47
56
|
if !lid.nil? && lid == legend_id.to_i
|
|
57
|
+
Aromancer::Storage.instance.clear_cache!
|
|
58
|
+
Aromancer::Api.get_legends
|
|
48
59
|
Aromancer::Api.load_arena
|
|
49
|
-
sleep(
|
|
60
|
+
sleep(1)
|
|
50
61
|
Aromancer::Cli.instance.start_ui_thread
|
|
51
62
|
end
|
|
52
63
|
when :legends
|
|
@@ -57,10 +68,7 @@ module Aromancer
|
|
|
57
68
|
end
|
|
58
69
|
|
|
59
70
|
self.socket.on :open do
|
|
60
|
-
r = {
|
|
61
|
-
command: "subscribe",
|
|
62
|
-
identifier: {channel: "PlayerChannel"}.to_json
|
|
63
|
-
}.to_json
|
|
71
|
+
r = {"command": :subscribe.to_s}.merge(Aromancer::Websocket.channel_identifier).to_json
|
|
64
72
|
Aromancer::Websocket.instance.socket.send(r)
|
|
65
73
|
end
|
|
66
74
|
|
|
@@ -69,7 +77,10 @@ module Aromancer
|
|
|
69
77
|
end
|
|
70
78
|
|
|
71
79
|
self.socket.on :error do |e|
|
|
72
|
-
|
|
80
|
+
if Aromancer::Storage.get_preference(:debug)
|
|
81
|
+
Aromancer::Prompt.say("#{self.class.name} socket.on :error")
|
|
82
|
+
Aromancer::Prompt.say(e.inspect)
|
|
83
|
+
end
|
|
73
84
|
Aromancer::Websocket.instance.disconnect
|
|
74
85
|
end
|
|
75
86
|
end
|
|
@@ -78,5 +89,15 @@ module Aromancer
|
|
|
78
89
|
self.socket&.close
|
|
79
90
|
self.socket = nil
|
|
80
91
|
end
|
|
92
|
+
|
|
93
|
+
# todo: websockets only in-game
|
|
94
|
+
# https://docs.anycable.io/misc/action_cable_protocol#perform-actions
|
|
95
|
+
# def self.set_active_legend_id(id)
|
|
96
|
+
# return if self.instance.socket.nil?
|
|
97
|
+
# r = {"command": :message.to_s}.merge(Aromancer::Websocket.channel_identifier).merge({
|
|
98
|
+
# data: {action: :player.to_s, active_legend_id: id}.to_json
|
|
99
|
+
# }).to_json
|
|
100
|
+
# self.instance.socket.send(r)
|
|
101
|
+
# end
|
|
81
102
|
end
|
|
82
103
|
end
|
data/lib/aromancer.rb
CHANGED
|
@@ -14,8 +14,7 @@ require_relative :reiquire.to_s
|
|
|
14
14
|
Reiquire::aromancer
|
|
15
15
|
|
|
16
16
|
module Aromancer
|
|
17
|
-
|
|
18
|
-
ERROR_EXPIRATION = 7.77.to_f
|
|
17
|
+
ERROR_EXPIRATION = 11.11.to_f
|
|
19
18
|
FONT = TTY::Font.new(:standard)
|
|
20
19
|
DATE_FORMAT = "%A %d %b %Y %I:%M:%S %p"
|
|
21
20
|
TIME_FORMAT = "%I:%M:%S %p"
|
|
@@ -25,130 +24,8 @@ module Aromancer
|
|
|
25
24
|
check: "\u2713"
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
unless Dir.exist?("#{Aromancer.to_s.downcase}_serve")
|
|
31
|
-
system("git clone git@github.com:arowmancy/aromancer_serve.git")
|
|
32
|
-
end
|
|
33
|
-
FileUtils.chdir :aromancer_serve.to_s do
|
|
34
|
-
system("bin/setup")
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# instance runs on main thread
|
|
40
|
-
class Cli
|
|
41
|
-
include Singleton
|
|
42
|
-
|
|
43
|
-
attr_accessor :ui_thread, :ws_thread, :busy, :ws_busy, :last_render, :error_timeout
|
|
44
|
-
|
|
45
|
-
# user entry point
|
|
46
|
-
def self.run
|
|
47
|
-
# ensure preferences exist
|
|
48
|
-
Aromancer::Storage.get_preference(:debug, default: false)
|
|
49
|
-
Aromancer::Storage.get_preference(:force_ssl, default: true)
|
|
50
|
-
Aromancer::Storage.get_preference(:hide_sentences, default: true)
|
|
51
|
-
Aromancer::Storage.get_preference(:hide_stream, default: true)
|
|
52
|
-
|
|
53
|
-
self.instance.last_render = 0
|
|
54
|
-
self.instance.error_timeout = Time.now.to_i
|
|
55
|
-
|
|
56
|
-
# load player on-start
|
|
57
|
-
Aromancer::Api.set_active_legend_id(nil) unless Aromancer::Storage.get_player.nil?
|
|
58
|
-
|
|
59
|
-
Thread.main[:route] = :authentication
|
|
60
|
-
Thread.main[:menu_runners] = {}
|
|
61
|
-
Thread.main[:menu_options] = {}
|
|
62
|
-
Aromancer::Prompt.say(I18n.t("shared.welcome", version: Aromancer::VERSION))
|
|
63
|
-
Aromancer::Prompt.say(I18n.t("shared.server_url", url: Aromancer::Storage::get_server_url))
|
|
64
|
-
self.instance.start_ui_thread
|
|
65
|
-
self.instance.start_ws_thread
|
|
66
|
-
loop do
|
|
67
|
-
begin
|
|
68
|
-
self.instance.ui_thread.join
|
|
69
|
-
rescue NoMethodError => e
|
|
70
|
-
if Aromancer::Storage.get_preference(:debug)
|
|
71
|
-
Aromancer::Prompt.say(I18n.t("shared.last_error"))
|
|
72
|
-
Aromancer::Prompt.say(JSON.pretty_generate(e[:body.to_s]))
|
|
73
|
-
Aromancer::Prompt.say("sleeping 5 on main thread...")
|
|
74
|
-
sleep(5)
|
|
75
|
-
end
|
|
76
|
-
self.instance.start_ui_thread
|
|
77
|
-
self.instance.start_ws_thread
|
|
78
|
-
sleep(1)
|
|
79
|
-
rescue Interrupt => e
|
|
80
|
-
Aromancer::Prompt.say("interrupt on main thread...exiting immediately.")
|
|
81
|
-
exit
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def get_view(view_key)
|
|
87
|
-
Thread.main[:menu_options][view_key.to_sym]
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def start_ui_thread(force = false)
|
|
91
|
-
return if (@busy || Time.now - @last_render < 2.0) && !force
|
|
92
|
-
|
|
93
|
-
@busy = true
|
|
94
|
-
self.ui_thread&.exit
|
|
95
|
-
self.ui_thread&.kill
|
|
96
|
-
Thread.main[:menu_runners] = {}
|
|
97
|
-
Thread.main[:menu_options] = {}
|
|
98
|
-
Aromancer::Prompt.instance.reload!
|
|
99
|
-
self.ui_thread = Thread.new do
|
|
100
|
-
loop do
|
|
101
|
-
menu_options = Thread.main[:menu_options][Thread.main[:route]]
|
|
102
|
-
menu_runners = Thread.main[:menu_runners][Thread.main[:route]]
|
|
103
|
-
unless menu_options.nil? || menu_runners.nil?
|
|
104
|
-
Aromancer::Routes.resume
|
|
105
|
-
Aromancer.print_hud
|
|
106
|
-
sleep(THROTTLE_MS)
|
|
107
|
-
v = Aromancer::Prompt.p.select("", menu_options, show_help: :always, cycle: true, per_page: 11)
|
|
108
|
-
runners = menu_runners.select{|r| r[:value] == v}
|
|
109
|
-
runners = menu_runners.select{|r| r[:value].nil?} if runners.empty?
|
|
110
|
-
|
|
111
|
-
if runners.any?
|
|
112
|
-
r = runners.first
|
|
113
|
-
r[:proc].call(v)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
else
|
|
117
|
-
Aromancer::Routes.resume
|
|
118
|
-
end
|
|
119
|
-
Aromancer::Cli.instance.busy = false
|
|
120
|
-
Aromancer::Cli.instance.last_render = Time.now
|
|
121
|
-
sleep(THROTTLE_MS)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def start_ws_thread
|
|
127
|
-
return if @ws_busy
|
|
128
|
-
@ws_busy = true
|
|
129
|
-
self.ws_thread.kill unless self.ws_thread.nil?
|
|
130
|
-
self.ws_thread = Thread.new do
|
|
131
|
-
Aromancer::Websocket.instance.disconnect
|
|
132
|
-
loop do
|
|
133
|
-
player = Aromancer::Storage.get_player
|
|
134
|
-
if player.nil?
|
|
135
|
-
@ws_busy = true
|
|
136
|
-
Aromancer::Websocket.instance.disconnect
|
|
137
|
-
elsif !player["api_key"].nil?
|
|
138
|
-
# attempt websocket connection
|
|
139
|
-
@ws_busy = true
|
|
140
|
-
Aromancer::Websocket.instance.connect
|
|
141
|
-
end
|
|
142
|
-
@ws_busy = false
|
|
143
|
-
sleep(4)
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def self.get_font(text = :aromancer.to_s, letter_spacing = 1)
|
|
151
|
-
Aromancer::FONT.write(text, letter_spacing: letter_spacing).split("\n")
|
|
27
|
+
def self.print_large_text(text = Aromancer.to_s.downcase, letter_spacing = 1)
|
|
28
|
+
Aromancer::Prompt.say(Aromancer::FONT.write(text, letter_spacing: letter_spacing))
|
|
152
29
|
end
|
|
153
30
|
|
|
154
31
|
def self.home_directory
|
|
@@ -165,7 +42,10 @@ module Aromancer
|
|
|
165
42
|
|
|
166
43
|
def self.print_hud
|
|
167
44
|
print_last_error
|
|
168
|
-
|
|
45
|
+
ws_status_symbol = (
|
|
46
|
+
Aromancer::Websocket.instance.socket.nil? || Aromancer::Websocket.instance.socket.closed?
|
|
47
|
+
) ? UNICODE[:close] : UNICODE[:check]
|
|
48
|
+
websocket_status = "#{Aromancer::Storage.instance.get_key(:websocket_scheme)}: #{ws_status_symbol}"
|
|
169
49
|
player_status = if Aromancer::Storage.get_player.nil?
|
|
170
50
|
I18n.t("routes.main_menu.not_signed_in")
|
|
171
51
|
else
|
|
@@ -184,14 +64,15 @@ module Aromancer
|
|
|
184
64
|
return
|
|
185
65
|
end
|
|
186
66
|
|
|
187
|
-
last_error = Aromancer::Storage.get_last_error
|
|
188
|
-
return if last_error.nil?
|
|
67
|
+
last_error = Aromancer::Storage.get_last_error&.symbolize_keys
|
|
189
68
|
|
|
190
|
-
|
|
69
|
+
return if last_error.nil?
|
|
191
70
|
message = last_error[:body]
|
|
192
71
|
begin
|
|
193
72
|
message = JSON.parse(message).symbolize_keys
|
|
194
73
|
message = message[:error_message] if message.keys.include?(:error_message)
|
|
74
|
+
rescue TypeError => e
|
|
75
|
+
message = last_error[:body]
|
|
195
76
|
rescue JSON::ParserError => e
|
|
196
77
|
message = last_error[:body]
|
|
197
78
|
end
|
data/lib/reiquire.rb
CHANGED
data/listen.rb
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
require :listen.to_s
|
|
2
2
|
|
|
3
3
|
listener = Listen.to(*[:lib.to_s, :bin.to_s, :spec.to_s, :locale.to_s], only: /[\.rb\.yml]/) {|modified, added, removed|
|
|
4
|
-
# puts modified
|
|
5
|
-
# puts added
|
|
6
|
-
# puts removed
|
|
7
|
-
# system("exec rake make")
|
|
8
4
|
system("exec rake install")
|
|
9
5
|
}
|
|
10
6
|
listener.start
|
data/locale/en.yml
CHANGED
|
@@ -13,6 +13,7 @@ en:
|
|
|
13
13
|
update_confirm: "confirm update [%{new_value}] (enter y): "
|
|
14
14
|
signed_in_as: "authenticated as %{as}"
|
|
15
15
|
last_error: "error (%{status}). %{error}"
|
|
16
|
+
waiting: "waiting..."
|
|
16
17
|
back: "back"
|
|
17
18
|
exit: "exit"
|
|
18
19
|
routes:
|
|
@@ -68,7 +69,7 @@ en:
|
|
|
68
69
|
place_on_scroll: "place %{word} on the scroll."
|
|
69
70
|
options_for_word: "available options for the %{word} word."
|
|
70
71
|
last_error: "last error"
|
|
71
|
-
|
|
72
|
+
returning_to_: "returning to %{route}..."
|
|
72
73
|
your_alchemy: "alchemy"
|
|
73
74
|
legends:
|
|
74
75
|
help: ""
|
data/tasks/make.rake
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aromancer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- i2097i
|
|
@@ -227,6 +227,7 @@ executables:
|
|
|
227
227
|
extensions: []
|
|
228
228
|
extra_rdoc_files: []
|
|
229
229
|
files:
|
|
230
|
+
- ".DS_Store"
|
|
230
231
|
- ".gitignore"
|
|
231
232
|
- ".rspec"
|
|
232
233
|
- ".ruby-version"
|
|
@@ -235,7 +236,6 @@ files:
|
|
|
235
236
|
- Gemfile
|
|
236
237
|
- Gemfile.lock
|
|
237
238
|
- LICENSE
|
|
238
|
-
- LICENSE.txt
|
|
239
239
|
- README.md
|
|
240
240
|
- Rakefile
|
|
241
241
|
- aromancer.gemspec
|
|
@@ -247,12 +247,14 @@ files:
|
|
|
247
247
|
- checksums/aromancer-0.0.5.gem.sha512
|
|
248
248
|
- checksums/aromancer-0.0.6.gem.sha512
|
|
249
249
|
- checksums/aromancer-0.0.7.gem.sha512
|
|
250
|
-
-
|
|
250
|
+
- checksums/aromancer-0.0.8.gem.sha512
|
|
251
251
|
- lib/aromancer.rb
|
|
252
252
|
- lib/aromancer/.DS_Store
|
|
253
253
|
- lib/aromancer/api.rb
|
|
254
|
+
- lib/aromancer/cli.rb
|
|
254
255
|
- lib/aromancer/prompt.rb
|
|
255
256
|
- lib/aromancer/routes.rb
|
|
257
|
+
- lib/aromancer/serve.rb
|
|
256
258
|
- lib/aromancer/server.rb
|
|
257
259
|
- lib/aromancer/storage.rb
|
|
258
260
|
- lib/aromancer/version.rb
|
|
@@ -260,6 +262,7 @@ files:
|
|
|
260
262
|
- lib/reiquire.rb
|
|
261
263
|
- listen.rb
|
|
262
264
|
- locale/en.yml
|
|
265
|
+
- pre-commit.git.template
|
|
263
266
|
- sig/aromancer.rbs
|
|
264
267
|
- tasks/console.rake
|
|
265
268
|
- tasks/make.rake
|
data/LICENSE.txt
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 i2097i
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
all copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
THE SOFTWARE.
|
data/gem_graph.png
DELETED
|
Binary file
|