add color-coding by activity per person
This commit is contained in:
parent
09708e74ab
commit
4c1960c3b2
|
@ -115,7 +115,8 @@ defmodule Backend.Scheduler do
|
||||||
} ->
|
} ->
|
||||||
time_diff_days = NaiveDateTime.diff(now, oldest_timestamp, :second) / (3600 * 24)
|
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,
|
domain: domain,
|
||||||
statuses_per_day: status_count / time_diff_days,
|
statuses_per_day: status_count / time_diff_days,
|
||||||
|
|
|
@ -8,6 +8,15 @@ defmodule BackendWeb.GraphView do
|
||||||
|> Enum.map(fn %{statuses_per_day: statuses_per_day} -> statuses_per_day end)
|
|> Enum.map(fn %{statuses_per_day: statuses_per_day} -> statuses_per_day end)
|
||||||
|> Enum.filter(fn s -> s != nil 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: %{
|
graph: %{
|
||||||
nodes: render_many(nodes, GraphView, "node.json", as: :node),
|
nodes: render_many(nodes, GraphView, "node.json", as: :node),
|
||||||
|
@ -15,9 +24,14 @@ defmodule BackendWeb.GraphView do
|
||||||
},
|
},
|
||||||
metadata: %{
|
metadata: %{
|
||||||
ranges: %{
|
ranges: %{
|
||||||
|
# Make sure that these keys match what's in the "node.json" render function.
|
||||||
statusesPerDay: [
|
statusesPerDay: [
|
||||||
Enum.min(statuses_per_day),
|
Enum.min(statuses_per_day),
|
||||||
Enum.max(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
|
false -> 1
|
||||||
end
|
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.
|
# This is the format that cytoscape.js expects.
|
||||||
%{
|
%{
|
||||||
data: %{
|
data: %{
|
||||||
|
@ -38,7 +59,8 @@ defmodule BackendWeb.GraphView do
|
||||||
label: node.domain,
|
label: node.domain,
|
||||||
size: size,
|
size: size,
|
||||||
type: node.type,
|
type: node.type,
|
||||||
statusesPerDay: node.statuses_per_day
|
statusesPerDay: node.statuses_per_day,
|
||||||
|
statusesPerUserPerDay: statuses_per_user_per_day
|
||||||
},
|
},
|
||||||
position: %{
|
position: %{
|
||||||
x: node.x,
|
x: node.x,
|
||||||
|
|
|
@ -2,7 +2,6 @@ defmodule BackendWeb.InstanceView do
|
||||||
use BackendWeb, :view
|
use BackendWeb, :view
|
||||||
alias BackendWeb.InstanceView
|
alias BackendWeb.InstanceView
|
||||||
import Backend.Util
|
import Backend.Util
|
||||||
require Logger
|
|
||||||
|
|
||||||
def render("show.json", %{instance: instance, crawl: crawl}) do
|
def render("show.json", %{instance: instance, crawl: crawl}) do
|
||||||
user_threshold = get_config(:personal_instance_threshold)
|
user_threshold = get_config(:personal_instance_threshold)
|
||||||
|
@ -31,6 +30,14 @@ defmodule BackendWeb.InstanceView do
|
||||||
instance.peers
|
instance.peers
|
||||||
|> Enum.filter(fn peer -> not peer.opt_out end)
|
|> 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,
|
name: instance.domain,
|
||||||
description: instance.description,
|
description: instance.description,
|
||||||
|
@ -43,7 +50,8 @@ defmodule BackendWeb.InstanceView do
|
||||||
lastUpdated: last_updated,
|
lastUpdated: last_updated,
|
||||||
status: status,
|
status: status,
|
||||||
type: instance.type,
|
type: instance.type,
|
||||||
statusesPerDay: instance.statuses_per_day
|
statusesPerDay: instance.statuses_per_day,
|
||||||
|
statusesPerUserPerDay: statuses_per_user_per_day
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -111,7 +111,7 @@ const renderQuantitativeKey = (range: number[]) => {
|
||||||
<ColorKeyContainer>
|
<ColorKeyContainer>
|
||||||
<ColorBarContainer>
|
<ColorBarContainer>
|
||||||
{QUANTITATIVE_COLOR_SCHEME.map((color, idx) => (
|
{QUANTITATIVE_COLOR_SCHEME.map((color, idx) => (
|
||||||
<ColorBar color={color} />
|
<ColorBar color={color} key={color} />
|
||||||
))}
|
))}
|
||||||
</ColorBarContainer>
|
</ColorBarContainer>
|
||||||
<TextContainer>
|
<TextContainer>
|
||||||
|
|
|
@ -267,7 +267,8 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
|
||||||
lastUpdated,
|
lastUpdated,
|
||||||
insularity,
|
insularity,
|
||||||
type,
|
type,
|
||||||
statusesPerDay
|
statusesPerDay,
|
||||||
|
statusesPerUserPerDay
|
||||||
} = this.props.instanceDetails;
|
} = this.props.instanceDetails;
|
||||||
return (
|
return (
|
||||||
<StyledHTMLTable small={true} striped={true}>
|
<StyledHTMLTable small={true} striped={true}>
|
||||||
|
@ -290,7 +291,7 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
Insularity{" "}
|
Insularity{" "}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
<span>
|
<span>
|
||||||
|
@ -309,11 +310,11 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
Statuses / day{" "}
|
Statuses / day{" "}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
<span>
|
<span>
|
||||||
The average number of statuses per day
|
The average number of statuses written each day on this instance,
|
||||||
<br />
|
<br />
|
||||||
over the last month.
|
over the last month.
|
||||||
</span>
|
</span>
|
||||||
|
@ -326,6 +327,25 @@ class InstanceScreenImpl extends React.PureComponent<IInstanceScreenProps, IInst
|
||||||
</td>
|
</td>
|
||||||
<td>{(statusesPerDay && numeral.default(statusesPerDay).format("0.0")) || "Unknown"}</td>
|
<td>{(statusesPerDay && numeral.default(statusesPerDay).format("0.0")) || "Unknown"}</td>
|
||||||
</tr>
|
</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>
|
<tr>
|
||||||
<td>Known peers</td>
|
<td>Known peers</td>
|
||||||
<td>{(domainCount && numeral.default(domainCount).format("0,0")) || "Unknown"}</td>
|
<td>{(domainCount && numeral.default(domainCount).format("0,0")) || "Unknown"}</td>
|
||||||
|
|
|
@ -49,6 +49,7 @@ export interface IInstanceDetails {
|
||||||
status: string;
|
status: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
statusesPerDay?: number;
|
statusesPerDay?: number;
|
||||||
|
statusesPerUserPerDay?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IGraphNode {
|
interface IGraphNode {
|
||||||
|
|
|
@ -28,10 +28,17 @@ export const typeColorScheme: IQualitativeColorScheme = {
|
||||||
};
|
};
|
||||||
export const activityColorScheme: IQuantitativeColorScheme = {
|
export const activityColorScheme: IQuantitativeColorScheme = {
|
||||||
cytoscapeDataKey: "statusesPerDay",
|
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,
|
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"
|
type: "quantitative"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const colorSchemes: IColorScheme[] = [typeColorScheme, activityColorScheme];
|
export const colorSchemes: IColorScheme[] = [typeColorScheme, activityColorScheme, activityPerUserColorScheme];
|
||||||
|
|
|
@ -64,7 +64,7 @@ export const getBuckets = (min: number, max: number, steps: number, exponential:
|
||||||
return logSpace.map(i => (i + translation) * scalingFactor);
|
return logSpace.map(i => (i + translation) * scalingFactor);
|
||||||
} else {
|
} else {
|
||||||
// Linear
|
// Linear
|
||||||
const bucketSize = Math.ceil((max - min) / steps);
|
const bucketSize = (max - min) / steps;
|
||||||
return range(min, max, bucketSize);
|
return range(min, max, bucketSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue