Skip to content

Commit

Permalink
Refactor Rating to use Rating Type (#350)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkonidas authored Aug 12, 2023
1 parent 4129bcf commit 298be83
Show file tree
Hide file tree
Showing 21 changed files with 138 additions and 95 deletions.
32 changes: 14 additions & 18 deletions lib/plexus/apps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -93,34 +93,30 @@ defmodule Plexus.Apps do
end

defp with_scores(query) do
google_lib_micro_g = from Rating, where: [google_lib: :micro_g]
google_lib_none = from Rating, where: [google_lib: :none]
micro_g = from Rating, where: [rating_type: :micro_g]
native = from Rating, where: [rating_type: :native]

query
|> join(:left, [a], r_micro_g in subquery(google_lib_micro_g),
on: a.package == r_micro_g.app_package
)
|> join(:left, [a, _], r_none in subquery(google_lib_none),
on: a.package == r_none.app_package
)
|> group_by([a, r_micro_g, r_none], [a.package, r_micro_g.google_lib, r_none.google_lib])
|> select_merge([a, r_micro_g, r_none], %{
scores: [
%Score{
|> join(:left, [a], r_micro_g in subquery(micro_g), on: a.package == r_micro_g.app_package)
|> join(:left, [a, _], r_native in subquery(native), on: a.package == r_native.app_package)
|> group_by([a, r_micro_g, r_native], [a.package, r_micro_g.rating_type, r_native.rating_type])
|> select_merge([a, r_micro_g, r_native], %{
scores: %{
native: %Score{
app_package: a.package,
google_lib: :none,
rating_type: :native,
numerator:
fragment("CAST(ROUND(AVG(COALESCE(?, 0))::numeric, 2) AS FLOAT)", r_none.score),
total_count: count(r_none.id, :distinct)
fragment("CAST(ROUND(AVG(COALESCE(?, 0))::numeric, 2) AS FLOAT)", r_native.score),
total_count: count(r_native.id, :distinct)
},
%Score{
micro_g: %Score{
app_package: a.package,
google_lib: :micro_g,
rating_type: :micro_g,
numerator:
fragment("CAST(ROUND(AVG(COALESCE(?, 0))::numeric, 2) AS FLOAT)", r_micro_g.score),
total_count: count(r_micro_g.id, :distinct)
}
]
}
})
end

Expand Down
4 changes: 2 additions & 2 deletions lib/plexus/query_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ defmodule Plexus.QueryHelpers do
{:preload, associations}, query ->
from q in query, preload: ^associations

{:google_lib, google_lib}, query ->
from q in query, where: q.google_lib == ^google_lib
{:rating_type, rating_type}, query ->
from q in query, where: q.rating_type == ^rating_type

_, query ->
query
Expand Down
2 changes: 1 addition & 1 deletion lib/plexus/ratings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule Plexus.Ratings do
rom_name: String.t(),
rom_build: String.t(),
installation_source: String.t(),
google_lib: atom(),
rating_type: atom(),
score: pos_integer()
}) :: {:ok, Rating.t()} | {:error, Ecto.Changeset.t()}
def create_rating(params) do
Expand Down
4 changes: 2 additions & 2 deletions lib/plexus/schemas/rating.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule Plexus.Schemas.Rating do
field :android_version, :string
field :rom_name, :string
field :rom_build, :string
field :google_lib, Ecto.Enum, values: [:none, :micro_g]
field :rating_type, Ecto.Enum, values: [:native, :micro_g]
field :installation_source, :string
field :notes, :string
field :score, :integer
Expand All @@ -31,7 +31,7 @@ defmodule Plexus.Schemas.Rating do
:app_build_number,
:rom_name,
:rom_build,
:google_lib,
:rating_type,
:installation_source,
:score
]
Expand Down
2 changes: 1 addition & 1 deletion lib/plexus/schemas/score.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Plexus.Schemas.Score do
@primary_key false
embedded_schema do
field :app_package, :string
field :google_lib, Ecto.Enum, values: [:none, :micro_g]
field :rating_type, Ecto.Enum, values: [:native, :micro_g]
field :numerator, :integer, default: 0
field :denominator, :integer, default: 4
field :total_count, :integer, default: 0
Expand Down
12 changes: 4 additions & 8 deletions lib/plexus_web/controllers/api/v1/app_json.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,16 @@ defmodule PlexusWeb.API.V1.AppJSON do

defp data(%Score{} = score) do
%{
google_lib: score.google_lib,
rating_type: score.rating_type,
numerator: score.numerator,
denominator: score.denominator,
total_count: score.total_count
}
end

defp merge_scores(payload, scores) when is_list(scores) do
scores
|> Enum.reverse()
|> Enum.reduce(payload, fn score, acc ->
score_data = data(score)
Map.update(acc, :scores, [score_data], &[score_data | &1])
end)
defp merge_scores(payload, scores) when is_map(scores) do
data = Map.new(scores, fn {rating_type, score} -> {rating_type, data(score)} end)
Map.put(payload, :scores, data)
end

defp merge_scores(payload, _scores), do: payload
Expand Down
6 changes: 3 additions & 3 deletions lib/plexus_web/controllers/api/v1/rating_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ defmodule PlexusWeb.API.V1.RatingController do
rom_name: {:string, [required: true]},
rom_build: {:string, [required: true]},
installation_source: {:string, [required: true]},
google_lib: {google_lib_enum(), [required: true]},
rating_type: {rating_type_enum(), [required: true]},
notes: {:string, []},
score: {:integer, [required: true]}
}
Expand All @@ -45,8 +45,8 @@ defmodule PlexusWeb.API.V1.RatingController do
render(conn, :show, rating: rating)
end

defp google_lib_enum do
values = Ecto.Enum.values(Plexus.Schemas.Rating, :google_lib)
defp rating_type_enum do
values = Ecto.Enum.values(Plexus.Schemas.Rating, :rating_type)
{:parameterized, Ecto.Enum, Ecto.Enum.init(values: values)}
end

Expand Down
2 changes: 1 addition & 1 deletion lib/plexus_web/controllers/api/v1/rating_json.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule PlexusWeb.API.V1.RatingJSON do
installation_source: rating.installation_source,
score: %{numerator: rating.score, denominator: 4},
notes: rating.notes,
google_lib: rating.google_lib
rating_type: rating.rating_type
}
end
end
8 changes: 4 additions & 4 deletions lib/plexus_web/live/admin/app_live/index.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
<:col :let={{_dom_id, app}} label="Package">
<p class="text-sm text-gray-700"><%= app.package %></p>
</:col>
<:col :let={{_dom_id, %{scores: [native_score, _micro_g_score]}}} label="Native">
<.badge score={native_score} />
<:col :let={{_dom_id, app}} label="Native">
<.badge score={app.scores.native} />
</:col>
<:col :let={{_dom_id, %{scores: [_native_score, micro_g_score]}}} label="MicroG">
<.badge score={micro_g_score} />
<:col :let={{_dom_id, app}} label="MicroG">
<.badge score={app.scores.micro_g} />
</:col>
<:action :let={{_dom_id, app}}>
<div class="sr-only">
Expand Down
2 changes: 1 addition & 1 deletion lib/plexus_web/live/admin/app_live/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defmodule PlexusWeb.Admin.AppLive.Show do
assign(
assigns,
:score,
Enum.find(assigns.app.scores, &(&1.google_lib == assigns.google_lib))
assigns.app.scores[assigns.rating_type]
)

~H"""
Expand Down
6 changes: 3 additions & 3 deletions lib/plexus_web/live/admin/app_live/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@
</:item>

<:item title="Native">
<.score app={@app} google_lib={:none} />
<.score app={@app} rating_type={:native} />
<.link
navigate={~p"/admin/apps/#{@app}/ratings/none"}
navigate={~p"/admin/apps/#{@app}/ratings/native"}
class="block text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
>
View ratings
</.link>
</:item>
<:item title="MicroG">
<.score app={@app} google_lib={:micro_g} />
<.score app={@app} rating_type={:micro_g} />
<.link
navigate={~p"/admin/apps/#{@app}/ratings/micro_g"}
class="block text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700 self-end"
Expand Down
14 changes: 9 additions & 5 deletions lib/plexus_web/live/admin/rating_live/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@ defmodule PlexusWeb.Admin.RatingLive.Index do
alias Plexus.Ratings

@impl Phoenix.LiveView
def mount(%{"package" => package, "google_lib" => google_lib}, _session, socket) do
def mount(%{"package" => package, "rating_type" => rating_type}, _session, socket) do
if connected?(socket), do: Apps.subscribe(package)
rating_type = String.to_existing_atom(rating_type)

page =
Ratings.list_ratings(package,
google_lib: google_lib,
rating_type: rating_type,
page_size: 9999,
order_by: [desc: :app_build_number, desc: :updated_at]
)

app = Apps.get_app!(package, scores: true)

{:ok,
socket
|> assign(:google_lib, google_lib)
|> assign(:app, Apps.get_app!(package, scores: true))
|> assign(:rating_type, rating_type)
|> assign(:app, app)
|> assign(:score, app.scores[rating_type])
|> stream(:ratings, page.entries)}
end

Expand Down Expand Up @@ -53,7 +57,7 @@ defmodule PlexusWeb.Admin.RatingLive.Index do
end

def handle_info({:app_rating_updated, rating}, socket) do
if rating.google_lib == String.to_existing_atom(socket.assigns.google_lib) do
if rating.rating_type == String.to_existing_atom(socket.assigns.rating_type) do
{:noreply,
socket
|> put_flash(:info, "Rating Added")
Expand Down
4 changes: 2 additions & 2 deletions lib/plexus_web/live/admin/rating_live/index.html.heex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<.header>
<%= @app.name %> <%= if @google_lib == "none", do: "Native", else: "MicroG" %> Ratings
<%= @app.name %> <%= if @rating_type == :native, do: "Native", else: "MicroG" %> Ratings
<:subtitle>
<.badge score={Enum.find(@app.scores, &(to_string(&1.google_lib) == @google_lib))} />
<.badge score={@score} />
</:subtitle>
</.header>

Expand Down
2 changes: 1 addition & 1 deletion lib/plexus_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ defmodule PlexusWeb.Router do
live "/apps/:package", AppLive.Show, :show
live "/apps/:package/show/edit", AppLive.Show, :edit

live "/apps/:package/ratings/:google_lib", RatingLive.Index, :index
live "/apps/:package/ratings/:rating_type", RatingLive.Index, :index
end

scope "/api/v1", PlexusWeb.API.V1 do
Expand Down
6 changes: 3 additions & 3 deletions priv/repo/migrations/20230301014024_create_ratings.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Plexus.Repo.Migrations.CreateRatings do
add :app_build_number, :integer
add :rom_name, :string
add :rom_build, :string
add :google_lib, :string, null: false
add :rating_type, :string, null: false
add :score, :integer, null: false
add :installation_source, :text
add :notes, :text
Expand All @@ -22,7 +22,7 @@ defmodule Plexus.Repo.Migrations.CreateRatings do
end

create index(:ratings, [:app_package])
create index(:ratings, [:google_lib])
create index(:ratings, [:app_package, :google_lib])
create index(:ratings, [:rating_type])
create index(:ratings, [:app_package, :rating_type])
end
end
44 changes: 44 additions & 0 deletions priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,47 @@
#
# We recommend using the bang functions (`insert!`, `update!`
# and so on) as they will fail if something goes wrong.
alias Plexus.Schemas.App

for params <- [
%{
package: "com.beemdevelopment.aegis",
name: "Aegis",
icon_url:
"https://play-lh.googleusercontent.com/qDzsOmoRT9o6QTElCaRJElAtfYW-nnOadwIInb6bXSEKexB211SsEtSeZrF5xm_lKUY"
},
%{
package: "com.aurora.store",
name: "Aurora Store",
icon_url:
"https://f-droid.org/repo/com.aurora.store/en-US/icon_tbAhwq51NNd0liZcTg0cQNNvazxrWlj7bPCe_1TkCV8=.png"
},
%{
package: "com.x8bit.bitwarden",
name: "Bitwarden",
icon_url:
"https://play-lh.googleusercontent.com/-jz18EgBYlmeHlnsq_iltq6uLnYFtXAVR_gi_d0qEj0pANQ1MtrJIstJoCQtImlWKwc"
},
%{
package: "org.thoughtcrime.securesms",
name: "Signal",
icon_url:
"https://play-lh.googleusercontent.com/jCln_XT8Ruzp7loH1S6yM-ZzzpLP1kZ3CCdXVEo0tP2w5HNtWQds6lo6aLxLIjiW_X8"
},
%{
package: "com.google.android.youtube",
name: "YouTube",
icon_url:
"https://play-lh.googleusercontent.com/lMoItBgdPPVDJsNOVtP26EKHePkwBg-PkuY9NOrc-fumRtTFP4XhpUNk_22syN4Datc"
}
] do
app =
case Plexus.Repo.get(App, params.package) do
nil -> %App{package: params.package}
app -> app
end

app
|> App.changeset(params)
|> Plexus.Repo.insert_or_update!()
end
53 changes: 28 additions & 25 deletions test/plexus/apps_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ defmodule Plexus.AppsTest do

describe "list_apps/1" do
test "returns a page of apps" do
app = app_fixture()
assert %Scrivener.Page{entries: [^app]} = Apps.list_apps()
assert %Scrivener.Page{entries: apps} = Apps.list_apps()

for app <- apps do
assert is_struct(app, App)
end
end

test "with scores" do
app_fixture()
%Scrivener.Page{entries: apps} = Apps.list_apps(scores: true)

for app <- apps do
assert [%Score{google_lib: :none}, %Score{google_lib: :micro_g}] = app.scores
for %App{scores: scores} <- apps do
assert %Score{rating_type: :native} = scores.native
assert %Score{rating_type: :micro_g} = scores.micro_g
end
end
end
Expand All @@ -34,30 +38,29 @@ defmodule Plexus.AppsTest do

test "with scores" do
%{package: app_package} = app_fixture()
rating_fixture(%{app_package: app_package, score: 3, google_lib: :micro_g})
rating_fixture(%{app_package: app_package, score: 4, google_lib: :micro_g})
rating_fixture(%{app_package: app_package, score: 4, google_lib: :micro_g})
rating_fixture(%{app_package: app_package, score: 1, google_lib: :none})
rating_fixture(%{app_package: app_package, score: 2, google_lib: :none})
rating_fixture(%{app_package: app_package, score: 3, rating_type: :micro_g})
rating_fixture(%{app_package: app_package, score: 4, rating_type: :micro_g})
rating_fixture(%{app_package: app_package, score: 4, rating_type: :micro_g})
rating_fixture(%{app_package: app_package, score: 1, rating_type: :native})
rating_fixture(%{app_package: app_package, score: 2, rating_type: :native})

app = Apps.get_app!(app_package, scores: true)

assert [
%Score{
app_package: ^app_package,
google_lib: :none,
numerator: 1.5,
denominator: 4,
total_count: 2
},
%Score{
app_package: ^app_package,
google_lib: :micro_g,
numerator: 3.67,
denominator: 4,
total_count: 3
}
] = app.scores
assert %Score{
app_package: ^app_package,
rating_type: :native,
numerator: 1.5,
denominator: 4,
total_count: 2
} = app.scores.native

assert %Score{
app_package: ^app_package,
rating_type: :micro_g,
numerator: 3.67,
denominator: 4,
total_count: 3
} = app.scores.micro_g
end
end

Expand Down
Loading

0 comments on commit 298be83

Please sign in to comment.