refactor discourse createGraph (#1409)
This is a minor refactor to re-organize the createGraph function in the Discourse plugin to use a class under the hood. Using a hidden class makes sense because there is a fair bit of shared state that's needed while creating the graph. The proximate cause for this refactor is tha adding reference edges will bloat the `addPost` section of the function, which was already a little too complex. Simply shoving in more complexity would make it unweidy. So I opted for this minor refactor. It's internal-only (no public APIs are changed). Test plan: `yarn test` passes. As noted, refactor is internal-only. This is progress towards [Discourse reference and mention detection][1]. [1]: https://discourse.sourcecred.io/t/discourse-reference-mention-detection/270
This commit is contained in:
parent
d4804a7a68
commit
e1a73ac368
|
@ -128,27 +128,59 @@ export function likesEdge(serverUrl: string, like: LikeAction): Edge {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createGraph(serverUrl: string, data: DiscourseData): Graph {
|
export function createGraph(serverUrl: string, data: DiscourseData): Graph {
|
||||||
|
const gc = new _GraphCreator(serverUrl, data);
|
||||||
|
return gc.graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GraphCreator {
|
||||||
|
graph: Graph;
|
||||||
|
serverUrl: string;
|
||||||
|
data: DiscourseData;
|
||||||
|
topicIdToTitle: Map<TopicId, string>;
|
||||||
|
|
||||||
|
constructor(serverUrl: string, data: DiscourseData) {
|
||||||
if (serverUrl.endsWith("/")) {
|
if (serverUrl.endsWith("/")) {
|
||||||
throw new Error(`by convention, serverUrl should not end with /`);
|
throw new Error(`by convention, serverUrl should not end with /`);
|
||||||
}
|
}
|
||||||
const g = new Graph();
|
this.serverUrl = serverUrl;
|
||||||
const topicIdToTitle: Map<TopicId, string> = new Map();
|
this.data = data;
|
||||||
|
this.graph = new Graph();
|
||||||
|
this.topicIdToTitle = new Map();
|
||||||
|
|
||||||
for (const username of data.users()) {
|
for (const username of data.users()) {
|
||||||
g.addNode(userNode(serverUrl, username));
|
this.graph.addNode(userNode(serverUrl, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const topic of data.topics()) {
|
for (const topic of data.topics()) {
|
||||||
topicIdToTitle.set(topic.id, topic.title);
|
this.topicIdToTitle.set(topic.id, topic.title);
|
||||||
g.addNode(topicNode(serverUrl, topic));
|
this.graph.addNode(topicNode(serverUrl, topic));
|
||||||
g.addEdge(authorsTopicEdge(serverUrl, topic));
|
this.graph.addEdge(authorsTopicEdge(serverUrl, topic));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const post of data.posts()) {
|
for (const post of data.posts()) {
|
||||||
const topicTitle = topicIdToTitle.get(post.topicId) || "[unknown topic]";
|
this.addPost(post);
|
||||||
g.addNode(postNode(serverUrl, post, topicTitle));
|
}
|
||||||
g.addEdge(authorsPostEdge(serverUrl, post));
|
|
||||||
g.addEdge(topicContainsPostEdge(serverUrl, post));
|
for (const like of data.likes()) {
|
||||||
|
this.graph.addEdge(likesEdge(serverUrl, like));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addPost(post: Post) {
|
||||||
|
const topicTitle =
|
||||||
|
this.topicIdToTitle.get(post.topicId) || "[unknown topic]";
|
||||||
|
this.graph.addNode(postNode(this.serverUrl, post, topicTitle));
|
||||||
|
this.graph.addEdge(authorsPostEdge(this.serverUrl, post));
|
||||||
|
this.graph.addEdge(topicContainsPostEdge(this.serverUrl, post));
|
||||||
|
this.maybeAddPostRepliesEdge(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any post that is not the first post in the thread is a reply to some post.
|
||||||
|
* This method adds those reply edges. It is a bit hairy to work around unintuitive
|
||||||
|
* choices in the Discourse API.
|
||||||
|
*/
|
||||||
|
maybeAddPostRepliesEdge(post: Post) {
|
||||||
let replyToPostIndex = post.replyToPostIndex;
|
let replyToPostIndex = post.replyToPostIndex;
|
||||||
if (replyToPostIndex == null && post.indexWithinTopic > 1) {
|
if (replyToPostIndex == null && post.indexWithinTopic > 1) {
|
||||||
// For posts that are a reply to the first posts (or, depending on how you look at it,
|
// For posts that are a reply to the first posts (or, depending on how you look at it,
|
||||||
|
@ -158,16 +190,13 @@ export function createGraph(serverUrl: string, data: DiscourseData): Graph {
|
||||||
replyToPostIndex = 1;
|
replyToPostIndex = 1;
|
||||||
}
|
}
|
||||||
if (replyToPostIndex != null) {
|
if (replyToPostIndex != null) {
|
||||||
const basePostId = data.findPostInTopic(post.topicId, replyToPostIndex);
|
const basePostId = this.data.findPostInTopic(
|
||||||
|
post.topicId,
|
||||||
|
replyToPostIndex
|
||||||
|
);
|
||||||
if (basePostId != null) {
|
if (basePostId != null) {
|
||||||
g.addEdge(postRepliesEdge(serverUrl, post, basePostId));
|
this.graph.addEdge(postRepliesEdge(this.serverUrl, post, basePostId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const like of data.likes()) {
|
|
||||||
g.addEdge(likesEdge(serverUrl, like));
|
|
||||||
}
|
|
||||||
|
|
||||||
return g;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue