Skip to content

Commit 4b2f1c7

Browse files
committed
Refactor resource and facilities to share more code
1 parent 58d0b9c commit 4b2f1c7

File tree

11 files changed

+284
-432
lines changed

11 files changed

+284
-432
lines changed

assets/js/app.js

+61-56
Original file line numberDiff line numberDiff line change
@@ -16,85 +16,90 @@
1616
//
1717

1818
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
19-
import "phoenix_html"
19+
import "phoenix_html";
2020
// Establish Phoenix Socket and LiveView configuration.
21-
import { Socket } from "phoenix"
22-
import { LiveSocket } from "phoenix_live_view"
23-
import topbar from "../vendor/topbar"
21+
import { Socket } from "phoenix";
22+
import { LiveSocket } from "phoenix_live_view";
23+
import topbar from "../vendor/topbar";
2424

2525
// if the duration is zero, return "done"
2626
// if the duration is less than a minute, return "{seconds}s"
2727
// if the duration is less than an hour, return "{minutes}m {seconds}s"
2828
// if the duration is less than a day, return "{hours}h {minutes}m {seconds}s"
2929
// if the duration is less than a year, return "{days}d {hours}h {minutes}m {seconds}s"
3030
function formatDuration(seconds) {
31-
if (seconds === 0) {
32-
return "done"
33-
}
34-
35-
let minutes = Math.floor(seconds / 60)
36-
let hours = Math.floor(minutes / 60)
37-
let days = Math.floor(hours / 24)
38-
let years = Math.floor(days / 365)
31+
if (seconds === 0) {
32+
return "done";
33+
}
3934

40-
if (years > 0) {
41-
return `${years}y ${days % 365}d ${hours % 24}h ${minutes % 60}m ${seconds % 60}s`
42-
} else if (days > 0) {
43-
return `${days}d ${hours % 24}h ${minutes % 60}m ${seconds % 60}s`
44-
} else if (hours > 0) {
45-
return `${hours}h ${minutes % 60}m ${seconds % 60}s`
46-
} else if (minutes > 0) {
47-
return `${minutes}m ${seconds % 60}s`
48-
} else {
49-
return `${seconds}s`
50-
}
35+
let minutes = Math.floor(seconds / 60);
36+
let hours = Math.floor(minutes / 60);
37+
let days = Math.floor(hours / 24);
38+
let years = Math.floor(days / 365);
5139

40+
if (years > 0) {
41+
return `${years}y ${days % 365}d ${hours % 24}h ${minutes % 60}m ${
42+
seconds % 60
43+
}s`;
44+
} else if (days > 0) {
45+
return `${days}d ${hours % 24}h ${minutes % 60}m ${seconds % 60}s`;
46+
} else if (hours > 0) {
47+
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
48+
} else if (minutes > 0) {
49+
return `${minutes}m ${seconds % 60}s`;
50+
} else {
51+
return `${seconds}s`;
52+
}
5253
}
5354

54-
let Hooks = {}
55+
let Hooks = {};
5556

5657
Hooks.Countdown = {
57-
tick() {
58-
let seconds = Math.floor((this.target - new Date()) / 1000)
59-
if (seconds <= 0) {
60-
this.el.innerHTML = "done"
61-
pushEvent("update_timers", this.el, {})
62-
return
63-
} else {
64-
this.el.innerHTML = formatDuration(seconds)
65-
this.timeout = setTimeout(() => this.tick(), 1000)
66-
}
67-
},
68-
mounted() {
69-
this.target = new Date(this.el.dataset.target)
70-
this.tick()
71-
},
72-
destroyed() {
73-
clearTimeout(this.timeout)
74-
},
75-
updated() {
76-
clearTimeout(this.timeout)
77-
this.mounted()
58+
tick() {
59+
let seconds = Math.floor((this.target - new Date()) / 1000);
60+
if (seconds <= 0) {
61+
this.el.innerHTML = "done";
62+
setTimeout(() => {
63+
this.pushEvent("countdown-ended", {});
64+
console.debug("sent countdown-ended event");
65+
}, 500);
66+
return;
67+
} else {
68+
this.el.innerHTML = formatDuration(seconds);
69+
this.timeout = setTimeout(() => this.tick(), 1000);
7870
}
79-
}
71+
},
72+
mounted() {
73+
this.target = new Date(this.el.dataset.target);
74+
this.tick();
75+
},
76+
updated() {
77+
clearTimeout(this.timeout);
78+
this.mounted();
79+
},
80+
destroyed() {
81+
clearTimeout(this.timeout);
82+
},
83+
};
8084

81-
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
85+
let csrfToken = document
86+
.querySelector("meta[name='csrf-token']")
87+
.getAttribute("content");
8288
let liveSocket = new LiveSocket("/live", Socket, {
83-
params: { _csrf_token: csrfToken },
84-
hooks: Hooks
85-
})
89+
params: { _csrf_token: csrfToken },
90+
hooks: Hooks,
91+
});
8692

8793
// Show progress bar on live navigation and form submits
88-
topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" })
89-
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
90-
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
94+
topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" });
95+
window.addEventListener("phx:page-loading-start", (_info) => topbar.show(300));
96+
window.addEventListener("phx:page-loading-stop", (_info) => topbar.hide());
9197

9298
// connect if there are any LiveViews on the page
93-
liveSocket.connect()
99+
liveSocket.connect();
94100

95101
// expose liveSocket on window for web console debug logs and latency simulation:
96102
// >> liveSocket.enableDebug()
97103
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
98104
// >> liveSocket.disableLatencySim()
99-
window.liveSocket = liveSocket
100-
105+
window.liveSocket = liveSocket;

lib/galaxies/accounts.ex

+2-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ defmodule Galaxies.Accounts do
120120
Repo.all(
121121
from pe in PlanetEvent,
122122
join: p in Planet,
123-
on: pe.planet_id == p.id and p.player_id == ^player_id
123+
on: pe.planet_id == p.id and p.player_id == ^player_id,
124+
where: pe.type in ^PlanetEvent.get_fleet_event_ids()
124125
)
125126
end
126127

lib/galaxies/planets.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ defmodule Galaxies.Planets do
6363
add_resources(planet_id, -cost_metal, -cost_crystal, -cost_deuterium)
6464

6565
# TODO: replace with a real formula
66-
construction_duration_seconds = :math.pow(level, 2) |> trunc()
66+
construction_duration_seconds = :math.pow(2, level) |> trunc()
6767

6868
event_id = Ecto.UUID.generate()
6969
now = DateTime.utc_now(:second)
@@ -121,7 +121,7 @@ defmodule Galaxies.Planets do
121121
end)
122122

123123
# TODO: replace with a real formula
124-
construction_duration_seconds = level + 1
124+
construction_duration_seconds = :math.pow(2, level) |> trunc()
125125

126126
now = DateTime.utc_now(:second)
127127

lib/galaxies/planets/events/building_construction_complete.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ defmodule Galaxies.Planets.Events.BuildingConstructionComplete do
135135

136136
# update enqueued_building to reflect new start and end times
137137
# TODO: replace with a real formula
138-
construction_duration_seconds = 2 * level
138+
construction_duration_seconds = :math.pow(2, level) |> trunc()
139139
completed_at = DateTime.add(started_at, construction_duration_seconds, :second)
140140

141141
Repo.update!(

lib/galaxies/planets/planet_event.ex

+24-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,20 @@ defmodule Galaxies.Planets.PlanetEvent do
44
"""
55
use Galaxies.Schema
66

7-
@atom_values_mapping [building_construction: 1, technology_research_complete: 2]
7+
@atom_values_mapping [
8+
# location events
9+
building_construction: 10,
10+
technology_research_complete: 11,
11+
# fleet events
12+
fleet_attack: 20,
13+
fleet_collect: 21,
14+
fleet_colonize: 22,
15+
fleet_destroy: 23,
16+
fleet_recycle: 24,
17+
fleet_spy: 25,
18+
fleet_transport: 26,
19+
fleet_transfer: 27
20+
]
821

922
schema "planet_events" do
1023
# this type allows storing primary keys from multiple tables so that we can have
@@ -22,4 +35,14 @@ defmodule Galaxies.Planets.PlanetEvent do
2235

2336
timestamps(updated_at: false, type: :utc_datetime)
2437
end
38+
39+
def get_fleet_event_ids do
40+
Enum.reduce(@atom_values_mapping, [], fn {event, id}, acc ->
41+
if id in 20..30 do
42+
[event | acc]
43+
else
44+
acc
45+
end
46+
end)
47+
end
2548
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
defmodule GalaxiesWeb.CommonComponents do
2+
alias GalaxiesWeb.Numbers
3+
use Phoenix.Component
4+
5+
use Gettext, backend: GalaxiesWeb.Gettext
6+
7+
def build_queue(assigns) do
8+
# TODO look into replacing with <.table>
9+
~H"""
10+
<div>
11+
<h4 class="text-base font-medium leading-4 text-gray-800">
12+
Active Build Queue
13+
</h4>
14+
</div>
15+
<div class="mt-2 flow-root">
16+
<div class="mx-4 my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
17+
<div class="inline-block min-w-full py-2 align-middle">
18+
<table class="min-w-full divide-y divide-gray-300">
19+
<thead>
20+
<tr>
21+
<th
22+
scope="col"
23+
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8"
24+
>
25+
Building
26+
</th>
27+
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
28+
Level
29+
</th>
30+
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
31+
Time to Complete
32+
</th>
33+
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8">
34+
<span class="sr-only">Cancel</span>
35+
</th>
36+
</tr>
37+
</thead>
38+
<tbody class="divide-y divide-gray-200">
39+
<tr>
40+
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm text-gray-900 sm:pl-6 lg:pl-8">
41+
{hd(@events).building.name}
42+
</td>
43+
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
44+
{hd(@events).level}
45+
</td>
46+
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
47+
<span
48+
id="build-queue-countdown"
49+
phx-hook="Countdown"
50+
data-target={DateTime.add(hd(@events).completed_at, 2, :second)}
51+
>
52+
{Numbers.format_countdown(
53+
DateTime.diff(hd(@events).completed_at, DateTime.utc_now())
54+
)}
55+
</span>
56+
</td>
57+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
58+
<a
59+
href="#"
60+
phx-click={"cancel:#{hd(@events).id}"}
61+
class="text-indigo-600 hover:text-indigo-900"
62+
>
63+
Cancel<span class="sr-only">, {hd(@events).building.name}</span>
64+
</a>
65+
</td>
66+
</tr>
67+
<tr :for={queued <- tl(@events)}>
68+
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm text-gray-900 sm:pl-6 lg:pl-8">
69+
{queued.building.name}
70+
</td>
71+
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
72+
{queued.level}
73+
</td>
74+
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
75+
-
76+
</td>
77+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
78+
<a href="#" class="text-indigo-600 hover:text-indigo-900">
79+
Cancel<span class="sr-only">, {queued.building.name}</span>
80+
</a>
81+
</td>
82+
</tr>
83+
</tbody>
84+
</table>
85+
</div>
86+
</div>
87+
</div>
88+
"""
89+
end
90+
end

0 commit comments

Comments
 (0)