diff --git a/backend/lib/backend/scheduler.ex b/backend/lib/backend/scheduler.ex index d2899d9..0041cf3 100644 --- a/backend/lib/backend/scheduler.ex +++ b/backend/lib/backend/scheduler.ex @@ -115,7 +115,8 @@ defmodule Backend.Scheduler do } -> time_diff_days = NaiveDateTime.diff(now, oldest_timestamp, :second) / (3600 * 24) - # (we're actually only ever updating, not inserting, so inserted_at will always be ignored...) + # (we're actually only ever updating, not inserting, so inserted_at will always be ignored... but ecto + # requires it) %{ domain: domain, statuses_per_day: status_count / time_diff_days, diff --git a/backend/lib/backend_web/views/graph_view.ex b/backend/lib/backend_web/views/graph_view.ex index b231177..3c8ca00 100644 --- a/backend/lib/backend_web/views/graph_view.ex +++ b/backend/lib/backend_web/views/graph_view.ex @@ -8,6 +8,15 @@ defmodule BackendWeb.GraphView do |> Enum.map(fn %{statuses_per_day: statuses_per_day} -> statuses_per_day end) |> Enum.filter(fn s -> s != nil end) + statuses_per_user_per_day = + nodes + |> Enum.filter(fn %{statuses_per_day: statuses_per_day, user_count: user_count} -> + statuses_per_day != nil and user_count != nil and user_count > 0 + end) + |> Enum.map(fn %{statuses_per_day: statuses_per_day, user_count: user_count} -> + statuses_per_day / user_count + end) + %{ graph: %{ nodes: render_many(nodes, GraphView, "node.json", as: :node), @@ -15,9 +24,14 @@ defmodule BackendWeb.GraphView do }, metadata: %{ ranges: %{ + # Make sure that these keys match what's in the "node.json" render function. statusesPerDay: [ Enum.min(statuses_per_day), Enum.max(statuses_per_day) + ], + statusesPerUserPerDay: [ + Enum.min(statuses_per_user_per_day), + Enum.max(statuses_per_user_per_day) ] } } @@ -31,6 +45,13 @@ defmodule BackendWeb.GraphView do false -> 1 end + statuses_per_user_per_day = + if node.statuses_per_day != nil and node.user_count != nil and node.user_count > 0 do + node.statuses_per_day / node.user_count + else + nil + end + # This is the format that cytoscape.js expects. %{ data: %{ @@ -38,7 +59,8 @@ defmodule BackendWeb.GraphView do label: node.domain, size: size, type: node.type, - statusesPerDay: node.statuses_per_day + statusesPerDay: node.statuses_per_day, + statusesPerUserPerDay: statuses_per_user_per_day }, position: %{ x: node.x, diff --git a/backend/lib/backend_web/views/instance_view.ex b/backend/lib/backend_web/views/instance_view.ex index 3c04b8e..91895a2 100644 --- a/backend/lib/backend_web/views/instance_view.ex +++ b/backend/lib/backend_web/views/instance_view.ex @@ -2,7 +2,6 @@ defmodule BackendWeb.InstanceView do use BackendWeb, :view alias BackendWeb.InstanceView import Backend.Util - require Logger def render("show.json", %{instance: instance, crawl: crawl}) do user_threshold = get_config(:personal_instance_threshold) @@ -31,6 +30,14 @@ defmodule BackendWeb.InstanceView do instance.peers |> Enum.filter(fn peer -> not peer.opt_out end) + statuses_per_user_per_day = + if instance.statuses_per_day != nil and instance.user_count != nil and + instance.user_count > 0 do + instance.statuses_per_day / instance.user_count + else + nil + end + %{ name: instance.domain, description: instance.description, @@ -43,7 +50,8 @@ defmodule BackendWeb.InstanceView do lastUpdated: last_updated, status: status, type: instance.type, - statusesPerDay: instance.statuses_per_day + statusesPerDay: instance.statuses_per_day, + statusesPerUserPerDay: statuses_per_user_per_day } end end diff --git a/frontend/src/components/atoms/GraphKey.tsx b/frontend/src/components/atoms/GraphKey.tsx index a978d2b..b290924 100644 --- a/frontend/src/components/atoms/GraphKey.tsx +++ b/frontend/src/components/atoms/GraphKey.tsx @@ -111,7 +111,7 @@ const renderQuantitativeKey = (range: number[]) => { {QUANTITATIVE_COLOR_SCHEME.map((color, idx) => ( - + ))} diff --git a/frontend/src/components/screens/InstanceScreen.tsx b/frontend/src/components/screens/InstanceScreen.tsx index 15a949b..d08c199 100644 --- a/frontend/src/components/screens/InstanceScreen.tsx +++ b/frontend/src/components/screens/InstanceScreen.tsx @@ -267,7 +267,8 @@ class InstanceScreenImpl extends React.PureComponent @@ -290,7 +291,7 @@ class InstanceScreenImpl extends React.PureComponent - Insularity{" "} + Insularity{" "} @@ -309,11 +310,11 @@ class InstanceScreenImpl extends React.PureComponent - Statuses / day{" "} + Statuses / day{" "} - The average number of statuses per day + The average number of statuses written each day on this instance,
over the last month. @@ -326,6 +327,25 @@ class InstanceScreenImpl extends React.PureComponent {(statusesPerDay && numeral.default(statusesPerDay).format("0.0")) || "Unknown"} + + + Statuses / person / day{" "} + + The average number of statuses written per person each day, +
+ over the last month. + + } + position={Position.TOP} + className={Classes.DARK} + > + +
+ + {(statusesPerUserPerDay && numeral.default(statusesPerUserPerDay).format("0.000")) || "Unknown"} + Known peers {(domainCount && numeral.default(domainCount).format("0,0")) || "Unknown"} diff --git a/frontend/src/redux/types.ts b/frontend/src/redux/types.ts index 3de16a2..5c21dac 100644 --- a/frontend/src/redux/types.ts +++ b/frontend/src/redux/types.ts @@ -49,6 +49,7 @@ export interface IInstanceDetails { status: string; type?: string; statusesPerDay?: number; + statusesPerUserPerDay?: number; } interface IGraphNode { diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 2396302..610a0a9 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -28,10 +28,17 @@ export const typeColorScheme: IQualitativeColorScheme = { }; export const activityColorScheme: IQuantitativeColorScheme = { cytoscapeDataKey: "statusesPerDay", - description: "The average number of statuses posted per day.", + description: "The average number of statuses posted per day. Note that this is colored by an exponential scale.", exponential: true, - name: "Activity", + name: "Activity (total)", + type: "quantitative" +}; +export const activityPerUserColorScheme: IQuantitativeColorScheme = { + cytoscapeDataKey: "statusesPerUserPerDay", + description: "The average number of statuses posted per person per day.", + exponential: false, + name: "Activity (per person)", type: "quantitative" }; -export const colorSchemes: IColorScheme[] = [typeColorScheme, activityColorScheme]; +export const colorSchemes: IColorScheme[] = [typeColorScheme, activityColorScheme, activityPerUserColorScheme]; diff --git a/frontend/src/util.ts b/frontend/src/util.ts index 653bd45..064f614 100644 --- a/frontend/src/util.ts +++ b/frontend/src/util.ts @@ -64,7 +64,7 @@ export const getBuckets = (min: number, max: number, steps: number, exponential: return logSpace.map(i => (i + translation) * scalingFactor); } else { // Linear - const bucketSize = Math.ceil((max - min) / steps); + const bucketSize = (max - min) / steps; return range(min, max, bucketSize); } };