add color-coding by activity per person

This commit is contained in:
Tao Bror Bojlén 2019-08-02 19:37:26 +03:00
parent 09708e74ab
commit 4c1960c3b2
No known key found for this signature in database
GPG Key ID: C6EC7AAB905F9E6F
8 changed files with 72 additions and 13 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -111,7 +111,7 @@ const renderQuantitativeKey = (range: number[]) => {
<ColorKeyContainer>
<ColorBarContainer>
{QUANTITATIVE_COLOR_SCHEME.map((color, idx) => (
<ColorBar color={color} />
<ColorBar color={color} key={color} />
))}
</ColorBarContainer>
<TextContainer>

View File

@ -267,7 +267,8 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
lastUpdated,
insularity,
type,
statusesPerDay
statusesPerDay,
statusesPerUserPerDay
} = this.props.instanceDetails;
return (
<StyledHTMLTable small={true} striped={true}>
@ -290,7 +291,7 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
</tr>
<tr>
<td>
Insularity{" "}
Insularity{" "}
<Tooltip
content={
<span>
@ -309,11 +310,11 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
</tr>
<tr>
<td>
Statuses / day{" "}
Statuses / day{" "}
<Tooltip
content={
<span>
The average number of statuses per day
The average number of statuses written each day on this instance,
<br />
over the last month.
</span>
@ -326,6 +327,25 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
</td>
<td>{(statusesPerDay && numeral.default(statusesPerDay).format("0.0")) || "Unknown"}</td>
</tr>
<tr>
<td>
Statuses / person / day{" "}
<Tooltip
content={
<span>
The average number of statuses written per person each day,
<br />
over the last month.
</span>
}
position={Position.TOP}
className={Classes.DARK}
>
<Icon icon={IconNames.HELP} iconSize={Icon.SIZE_STANDARD} />
</Tooltip>
</td>
<td>{(statusesPerUserPerDay && numeral.default(statusesPerUserPerDay).format("0.000")) || "Unknown"}</td>
</tr>
<tr>
<td>Known peers</td>
<td>{(domainCount && numeral.default(domainCount).format("0,0")) || "Unknown"}</td>

View File

@ -49,6 +49,7 @@ export interface IInstanceDetails {
status: string;
type?: string;
statusesPerDay?: number;
statusesPerUserPerDay?: number;
}
interface IGraphNode {

View File

@ -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];

View File

@ -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);
}
};