diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3115f9f..64fb55e 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -336,3 +336,58 @@ a:has(button) { justify-content: space-between; gap: 5px; } + +.sprite-list { + display: flex; + align-self: start; + flex-direction: column; +} + +.sprite { + display: flex; + gap: 5px; + margin-bottom: 5px; + align-items: center; +} + +.sprite-name { + background-color: #3D9970; + color: #fff; + padding: 2px 4px; +} + +.sprite .spawning { + color: #3D9970; +} + +.sprite .not-spawning { + color: #b5443a; +} + +.sprite-levels { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 5px; +} + +.sprite-map { + margin-bottom: 10px; + margin-top: 5px; +} + +.sprite-map summary { + font-size: 12px; +} + +.sprite-levels > div { + background-color: #111; + color: #fff; + font-family: monospace; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + text-transform: uppercase; + font-weight: bold; + padding: 3px 5px; +} diff --git a/app/views/instance/_chlog.html.erb b/app/views/instance/_chlog.html.erb new file mode 100644 index 0000000..54273c8 --- /dev/null +++ b/app/views/instance/_chlog.html.erb @@ -0,0 +1,63 @@ +

Challenge log

+ +
+ <% Bestiary.get_sprites_for_zone(instance.zone).each do |sprite| %> + <% is_spawning = forecast[0][:curr_weather].in?(sprite[:weather]) %> +
+
+ + <%= sprite[:name] %> +
+ <% if is_spawning %> +
is spawning!
+ <% else %> + <% next_pattern = forecast.find { |f| f[:curr_weather].in?(sprite[:weather]) } %> +
spawns in + <% if next_pattern.nil? %> + >300m + <% else %> + <%= ((next_pattern[:time] - Time.now.utc) / 1.minutes).ceil %>m + <% end %> +
+ <% end %> +
+ <% if is_spawning %> +
+ <% sprite[:sprite_levels].each do |lvl| %> +
+
+
lv<%= lvl[:lv] %>
+
+ <% if lvl[:mutates] %> + + <% elsif lvl[:adapts] %> + + <% end %> +
+
+ ~<%= lvl[:mx] %>/<%= lvl[:my] %> +
+ <% end %> +
+
+ + show map + + +
+ + <% sprite[:sprite_levels].each do |lvl| %> +
+ • +
+ LV<%= lvl[:lv] %> +
+ <% end %> +
+
+ <% end %> + <% end %> +
diff --git a/app/views/instance/_list.html.erb b/app/views/instance/_list.html.erb index 6c5c329..d94a6e0 100644 --- a/app/views/instance/_list.html.erb +++ b/app/views/instance/_list.html.erb @@ -34,7 +34,7 @@ <% pop = instance.pops.find { |pop| pop.name == nm[:name].parameterize } %> <% mins = ActiveSupport::Duration.build(Time.current - pop.created_at) %>
-
» <%= (120.minutes - mins).in_minutes.floor %>m
+
» <%= (120.minutes - mins).in_minutes.ceil %>m
@@ -55,14 +55,14 @@ <% end %> <% if nm[:weather] && forecast[0][:curr_weather] != nm[:weather] %> <% next_pattern = forecast.find { |f| f[:curr_weather] == nm[:weather] } %> - <%= Weather.get_weather_name(nm[:weather]) %> in <%= ((next_pattern[:time] - Time.now.utc) / 1.minutes).floor %>m + <%= Weather.get_weather_name(nm[:weather]) %> in <%= ((next_pattern[:time] - Time.now.utc) / 1.minutes).ceil %>m <% end %> <% if nm[:spawned_by][:weather] && forecast[0][:curr_weather] != nm[:spawned_by][:weather] %> <% next_pattern = forecast.find { |f| f[:curr_weather] == nm[:spawned_by][:weather] } %> - <%= Weather.get_weather_name(nm[:spawned_by][:weather]) %> in <%= ((next_pattern[:time] - Time.now.utc) / 1.minutes).floor %>m + <%= Weather.get_weather_name(nm[:spawned_by][:weather]) %> in <%= ((next_pattern[:time] - Time.now.utc) / 1.minutes).ceil %>m <% end %> <% if (nm[:night_only] || nm[:spawned_by][:night_only]) && is_day? %> -
Night in <%= ((Clock.to_earth_time(Clock.get_current_eorzea_time.change(hour: 18)) - Time.now.utc) / 1.minutes).floor %>m
+ Night in <%= ((Clock.to_earth_time(Clock.get_current_eorzea_time.change(hour: 18)) - Time.now.utc) / 1.minutes).ceil %>m <% end %>
@@ -87,4 +87,12 @@ <% end %> + + + + + + <%= form_with url: clone_instance_path(instance: @instance.public_id), html: { style: "display: inline-block;" } do |f| %> + <%= f.submit "clone instance" %> + <% end %> diff --git a/app/views/instance/show.html.erb b/app/views/instance/show.html.erb index a2854b0..c155c92 100644 --- a/app/views/instance/show.html.erb +++ b/app/views/instance/show.html.erb @@ -1,5 +1,5 @@
-
+
" hx-swap="outerHTML" hx-select="#container" hx-target="#container">
<%= link_to root_path do %>eureka.coffee logo<% end %> @@ -36,13 +36,14 @@ »
-
<%= ((@forecast[i + 1][:time] - Time.now.utc) / 1.minutes).floor %>m
+
<%= ((@forecast[i + 1][:time] - Time.now.utc) / 1.minutes).ceil %>m
<% end %>
<%= render partial: "fairies", locals: { instance: @instance } %> + <%= render partial: "chlog", locals: { instance: @instance, forecast: @forecast } %>
@@ -50,9 +51,3 @@ <%= javascript_include_tag "list" %>
- - - -<%= form_with url: clone_instance_path(instance: @instance.public_id), html: { style: "display: inline-block;" } do |f| %> - <%= f.submit "clone instance" %> -<% end %> diff --git a/config/initializers/data.rb b/config/initializers/data.rb index fedf8a3..e334c63 100644 --- a/config/initializers/data.rb +++ b/config/initializers/data.rb @@ -2,10 +2,12 @@ anemos_data = Tomlrb.load_file("./data/anemos.toml", symbolize_keys: true) pagos_data = Tomlrb.load_file("./data/pagos.toml", symbolize_keys: true) pyros_data = Tomlrb.load_file("./data/pyros.toml", symbolize_keys: true) hydatos_data = Tomlrb.load_file("./data/hydatos.toml", symbolize_keys: true) +bestiary_data = Tomlrb.load_file("./data/bestiary.toml", symbolize_keys: true) APP_DATA = { anemos: anemos_data, pagos: pagos_data, pyros: pyros_data, - hydatos: hydatos_data + hydatos: hydatos_data, + bestiary: bestiary_data } diff --git a/data/bestiary.toml b/data/bestiary.toml new file mode 100644 index 0000000..ad0476e --- /dev/null +++ b/data/bestiary.toml @@ -0,0 +1,236 @@ +[[bestiary]] +name = "Blizzard Sprite" +sprite = true +weather = ["snow"] +element = "ice" +zone = "anemos" +sprite_levels = [ + { lv = 2, mx = 21.7, my = 31.7 }, + { lv = 6, mx = 13.4, my = 23.9 }, + { lv = 10, mx = 22.7, my = 24.6 }, + { lv = 20, mx = 28.3, my = 14.4 }, + { lv = 22, mx = 34.3, my = 16.0 } +] + +[[bestiary]] +name = "Typhoon Sprite" +sprite = true +weather = ["gales"] +element = "wind" +zone = "anemos" +sprite_levels = [ + { lv = 5, mx = 15.1, my = 24.9 }, + { lv = 9, mx = 24.8, my = 23.7 }, + { lv = 12, mx = 16.4, my = 19.0 }, + { lv = 13, mx = 23.1, my = 20.4 }, + { lv = 15, mx = 28.7, my = 20.5 }, + { lv = 19, mx = 28.0, my = 16.6 }, + { lv = 21, mx = 32.1, my = 17.3 }, + { lv = 23, mx = 9.5, my = 17.6 }, + { lv = 25, mx = 9.6, my = 21.4 } +] + +[[bestiary]] +name = "Rain Sprite" +sprite = true +weather = ["showers"] +element = "water" +zone = "anemos" +sprite_levels = [ + { lv = 7, mx = 13.9, my = 20.5 }, + { lv = 9, mx = 22.2, my = 28.5 }, + { lv = 11, mx = 19.0, my = 24.4 }, + { lv = 14, mx = 26.1, my = 24.8 }, + { lv = 17, mx = 18.3, my = 14.8 }, + { lv = 18, mx = 20.8, my = 13.9 }, + { lv = 24, mx = 9.1, my = 19.8 } +] + +[[bestiary]] +name = "Ember Sprite" +sprite = true +weather = ["heat"] +element = "fire" +zone = "pagos" +sprite_levels = [ + { lv = 23, mx = 15.6, my = 27.4 }, + { lv = 27, mutates = true, mx = 28.6, my = 27.1 }, + { lv = 31, adapts = true, mx = 15.6, my = 22.0 }, + { lv = 35, adapts = true, mx = 8.4, my = 17.5 }, + { lv = 39, adapts = true, mx = 24.0, my = 16.7 } +] + +[[bestiary]] +name = "Snowmelt Sprite" +sprite = true +weather = ["fog"] +element = "water" +zone = "pagos" +sprite_levels = [ + { lv = 22, mx = 13.4, my = 25.4 }, + { lv = 26, mutates = true, mx = 27.3, my = 26.7 }, + { lv = 29, mx = 32.8, my = 24.8 }, + { lv = 34, mx = 6.9, my = 14.0 }, + { lv = 38, adapts = true, mx = 22.2, my = 16.3 } +] + +[[bestiary]] +name = "Snows. Sprite" +sprite = true +weather = ["snow", "blizzards"] +element = "ice" +zone = "pagos" +sprite_levels = [ + { lv = 20, mx = 9.4, my = 23.6 }, + { lv = 24, mx = 18.2, my = 28.1 }, + { lv = 28, adapts = true, mx = 30.9, my = 27.9 }, + { lv = 32, mutates = true, mx = 10.9, my = 12.9 }, + { lv = 36, mx = 22.3, my = 18.1 }, + { lv = 40, adapts = true, mx = 36.7, my = 15.5 } +] + +[[bestiary]] +name = "Thunders. Sprite" +sprite = true +weather = ["thunder"] +element = "lightning" +zone = "pagos" +sprite_levels = [ + { lv = 21, mx = 12.8, my = 27.9 }, + { lv = 25, mutates = true, mx = 21.1, my = 28.7 }, + { lv = 30, mx = 30.0, my = 22.8 }, + { lv = 33, mutates = true, mx = 10.6, my = 16.3 }, + { lv = 37, adapts = true, mx = 31.3, my = 17.3 } +] + +[[bestiary]] +name = "Typhoon Sprite" +sprite = true +weather = ["umbral_wind"] +element = "wind" +zone = "pyros" +sprite_levels = [ + { lv = 35, mx = 17.0, my = 25.8 }, + { lv = 40, mx = 29.1, my = 27.5 }, + { lv = 42, mx = 31.5, my = 32.5 }, + { lv = 42, mx = 28.2, my = 32.9 }, + { lv = 45, mx = 24.1, my = 18.7 }, + { lv = 45, mx = 18.1, my = 15.5 }, + { lv = 48, mx = 14.1, my = 9.1 }, + { lv = 49, mx = 15.2, my = 7.3 }, + { lv = 55, adapts = true, mx = 38.2, my = 16.4 }, + { lv = 55, adapts = true, mx = 15.4, my = 36.9 } +] + +[[bestiary]] +name = "Ember Sprite" +sprite = true +weather = ["heat"] +element = "fire" +zone = "pyros" +sprite_levels = [ + { lv = 38, mx = 13.1, my = 29.0 }, + { lv = 38, mx = 25.0, my = 24.4 }, + { lv = 38, mx = 25.3, my = 27.0 }, + { lv = 39, mx = 26.4, my = 23.9 }, + { lv = 39, mx = 11.4, my = 29.7 }, + { lv = 43, adapts = true, mx = 25.2, my = 37.7 }, + { lv = 43, adapts = true, mx = 19.0, my = 34.4 }, + { lv = 44, mx = 21.0, my = 32.2 }, + { lv = 53, mx = 29.7 , my = 17.2 }, + { lv = 53, mx = 35.8, my = 16.5 } +] + +[[bestiary]] +name = "Thunders. Sprite" +sprite = true +weather = ["thunder"] +element = "lightning" +zone = "pyros" +sprite_levels = [ + { lv = 36, mx = 17.5, my = 27.4 }, + { lv = 37, mx = 23.7, my = 26.8 }, + { lv = 41, mx = 24.0, my = 34.1 }, + { lv = 46, adapts = true, mx = 12.0, my = 17.3 }, + { lv = 51, mx = 25.7, my = 9.2 }, + { lv = 54, adapts = true, mx = 36.5, my = 15.2 }, + { lv = 54, adapts = true, mx = 12.1, my = 33.5 } +] + +[[bestiary]] +name = "Snows. Sprite" +sprite = true +weather = ["snow", "blizzards"] +element = "ice" +zone = "pyros" +sprite_levels = [ + { lv = 47, mx = 13.1, my = 14.5 }, + { lv = 50, mx = 24.9, my = 6.5 }, + { lv = 50, mx = 25.3, my = 12.2 }, + { lv = 52, adapts = true, mx = 27.4, my = 17.5 }, + { lv = 52, adapts = true, mx = 30.0, my = 12.3 } +] + +[[bestiary]] +name = "Thunders. Sprites" +sprite = true +weather = ["thunder"] +element = "lightning" +zone = "hydatos" +sprite_levels = [ + { lv = 53, adapts = true, mx = 11.6, my = 23.5 }, + { lv = 53, adapts = true, mx = 14.7, my = 25.0 }, + { lv = 57, mx = 7.7, my = 15.6 }, + { lv = 57, mx = 5.7, my = 21.2 }, + { lv = 61, mutates = true, mx = 25.6, my = 19.9 }, + { lv = 65, mx = 34.6, my = 17.0 }, + { lv = 65, mx = 30.9, my = 21.0 } +] + +[[bestiary]] +name = "Snows. Sprite" +sprite = true +weather = ["snow"] +element = "ice" +zone = "hydatos" +sprite_levels = [ + { lv = 52, mx = 16.4, my = 22.3 }, + { lv = 52, mx = 13.0, my = 14.1 }, + { lv = 56, adapts = true, mx = 10.4, my = 15.5 }, + { lv = 56, adapts = true, mx = 8.4, my = 19.7 }, + { lv = 56, adapts = true, mx = 10.8, my = 21.1 }, + { lv = 60, adapts = true, mx = 24.4, my = 17.8 }, + { lv = 64, adapts = true, mx = 34.9, my = 14.0 }, + { lv = 65, mx = 32.4, my = 28.7 } +] + +[[bestiary]] +name = "Death Sprite" +sprite = true +weather = ["gloom"] +element = "fire" +zone = "hydatos" +sprite_levels = [ + { lv = 50, mx = 19.4, my = 16.1 }, + { lv = 54, mx = 22.2, my = 23.2 }, + { lv = 58, mx = 3.6, my = 14.1 }, + { lv = 58, mx = 8.2, my = 12.7 }, + { lv = 58, mx = 10.6, my = 19.4 }, + { lv = 62, mx = 30.3, my = 27.2 }, + { lv = 62, mx = 35.9, my = 27.1 }, + { lv = 65, mx = 32.4, my = 28.7 } +] + +[[bestiary]] +name = "Snowmelt Sprite" +sprite = true +weather = ["showers"] +element = "water" +zone = "hydatos" +sprite_levels = [ + { lv = 51, mx = 16.2, my = 20.6 }, + { lv = 55, adapts = true, mx = 10.8, my = 26.9 }, + { lv = 59, mx = 3.8, my = 27.3 }, + { lv = 63, mutates = true, mx = 36.1, my = 18.5 }, + { lv = 65, mx = 32.4, my = 28.7 } +] diff --git a/lib/bestiary.rb b/lib/bestiary.rb new file mode 100644 index 0000000..6b4b23e --- /dev/null +++ b/lib/bestiary.rb @@ -0,0 +1,7 @@ +class Bestiary + def self.get_sprites_for_zone(zone) + b = APP_DATA[:bestiary][:bestiary] + + b.filter { |m| m[:sprite] && m[:zone] == zone } + end +end diff --git a/public/adaptation.png b/public/adaptation.png new file mode 100644 index 0000000..4575b5a Binary files /dev/null and b/public/adaptation.png differ diff --git a/public/maps/anemos_fw.jpg b/public/maps/anemos_fw.jpg new file mode 100644 index 0000000..544b045 Binary files /dev/null and b/public/maps/anemos_fw.jpg differ diff --git a/public/maps/hydatos_fw.jpg b/public/maps/hydatos_fw.jpg new file mode 100644 index 0000000..f3bdb2f Binary files /dev/null and b/public/maps/hydatos_fw.jpg differ diff --git a/public/maps/pagos_fw.jpg b/public/maps/pagos_fw.jpg new file mode 100644 index 0000000..226e9d7 Binary files /dev/null and b/public/maps/pagos_fw.jpg differ diff --git a/public/maps/pyros_fw.jpg b/public/maps/pyros_fw.jpg new file mode 100644 index 0000000..d6a3a7b Binary files /dev/null and b/public/maps/pyros_fw.jpg differ diff --git a/public/mutation.png b/public/mutation.png new file mode 100644 index 0000000..90a82cc Binary files /dev/null and b/public/mutation.png differ