Graph database Analysis of the Steam Network
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
7.5 KiB

  1. package net.jrtechs.www.graphDB;
  2. import net.jrtechs.www.server.Player;
  3. import net.jrtechs.www.SteamAPI.APIConnection;
  4. import java.util.ArrayList;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. /**
  9. * Does graph based operations with {@link Player}
  10. * and {@link RemoteConnection}
  11. *
  12. * @author Jeffery Russell 5-26-17
  13. */
  14. public class SteamGraph
  15. {
  16. /** Connection to the graph server */
  17. private RemoteConnection con;
  18. /** Connection to steam api */
  19. private APIConnection api;
  20. /**
  21. * Constructs object with a graph connection
  22. * and a steam api connection
  23. */
  24. public SteamGraph()
  25. {
  26. this.con = new RemoteConnection();
  27. this.api = new APIConnection();
  28. }
  29. /**
  30. * Checks if a player is already in the graph
  31. *
  32. * @param id steam id of player
  33. * @return
  34. */
  35. private boolean alreadyInGraph(String id)
  36. {
  37. String query = "g.V().hasLabel('player')" +
  38. ".has('id', '" + id + "')";
  39. //System.out.println(query);
  40. return (1 <= con.queryGraph(query).stream().count());
  41. }
  42. /**
  43. * Inserts a player vertex into the graph
  44. *
  45. * @param
  46. */
  47. private void insertPlayerIntoGraph(String id, String name)
  48. {
  49. try
  50. {
  51. if(!this.alreadyInGraph(id))
  52. {
  53. String queryInsertPlayer = "g.addV('player')" +
  54. ".property('name', '" + name + "')" +
  55. ".property('crawled', '0')" +
  56. ".property('id', '" + id + "')";
  57. System.out.println("inserting " + name + " into graph");
  58. this.con.queryGraph(queryInsertPlayer);
  59. }
  60. }
  61. catch (Exception e)
  62. {
  63. e.printStackTrace();
  64. }
  65. }
  66. /**
  67. * Checks if a friend-friend edge is already in the
  68. * graph
  69. *
  70. * @param p1
  71. * @param p2
  72. * @return
  73. */
  74. private boolean edgeAlreadyInGraph(String p1, String p2)
  75. {
  76. try
  77. {
  78. String query = "g.V().hasLabel('player')" +
  79. ".has('id', '" + p1 + "')" +
  80. ".both()" +
  81. ".has('id', '" + p2 + "')";
  82. //System.out.println(query);
  83. return (1 <= con.queryGraph(query).stream().count());
  84. }
  85. catch(Exception e)
  86. {
  87. return false;
  88. }
  89. }
  90. /**
  91. * Inserts a edge between two players into the graph
  92. *
  93. * @param p1
  94. * @param p2
  95. */
  96. private void insertEdgeIntoGraph(String p1, String p2)
  97. {
  98. try
  99. {
  100. if(!this.edgeAlreadyInGraph(p1, p2))
  101. {
  102. String query = "g.V().hasLabel('player')" +
  103. ".has('id', '" + p1 + "')" +
  104. ".as('p1')" +
  105. "V().hasLabel('player')" +
  106. ".has('id', '" + p2 + "')" +
  107. ".as('p2')" +
  108. ".addE('friends')" +
  109. ".from('p1').to('p2')";
  110. //System.out.println(query);
  111. this.con.queryGraph(query);
  112. }
  113. }
  114. catch (Exception e)
  115. {
  116. e.printStackTrace();
  117. }
  118. }
  119. /**
  120. * determines if a player has been indexed for friends yet
  121. *
  122. * @param id
  123. * @return
  124. */
  125. private boolean playerAlreadyIndexed(String id)
  126. {
  127. try
  128. {
  129. String query = "g.V().hasLabel('player')" +
  130. ".has('id', '" + id + "')" +
  131. ".has('crawled', '0')";
  132. return (1 != con.queryGraph(query).stream().count());
  133. }
  134. catch(Exception e)
  135. {
  136. e.printStackTrace();
  137. }
  138. return true;
  139. }
  140. private void updateCrawledStatus(String id)
  141. {
  142. try
  143. {
  144. String query = "g.V().hasLabel('player')" +
  145. ".has('id', '" + id + "')" +
  146. ".property('crawled', '1')";
  147. this.con.queryGraph(query);
  148. }
  149. catch (Exception e)
  150. {
  151. e.printStackTrace();
  152. }
  153. }
  154. /**
  155. * Fetches the name of the player from the graph database
  156. *
  157. * @param id
  158. * @return
  159. */
  160. private String getNameFromGraph(String id)
  161. {
  162. String query = "g.V().hasLabel('player')" +
  163. ".has('id', '" + id + "')" +
  164. ".values('name')";
  165. return this.con.queryGraph(query).stream()
  166. .findFirst().get().getObject().toString();
  167. }
  168. /**
  169. * Fetches a list of friends from the graph database
  170. *
  171. * @param id
  172. * @return
  173. */
  174. private List<Player> getFriendsFromGraph(String id)
  175. {
  176. List<Player> friends = new ArrayList<>();
  177. String query = "g.V().hasLabel('player')" +
  178. ".has('id', '" + id + "')" +
  179. ".both().valueMap()";
  180. try
  181. {
  182. this.con.queryGraph(query).stream().forEach(r ->
  183. friends.add(new Player(
  184. ((ArrayList) (((HashMap<String, Object>) (r.getObject()))
  185. .get("name"))).get(0).toString(),
  186. ((ArrayList) (((HashMap<String, Object>) (r.getObject()))
  187. .get("id"))).get(0).toString()))
  188. );
  189. }
  190. catch(Exception e)
  191. {
  192. e.printStackTrace();
  193. }
  194. return friends;
  195. }
  196. /**
  197. * tells api to get this dude's friends list
  198. *
  199. * @param id
  200. */
  201. private void indexPersonFriends(String id)
  202. {
  203. System.out.println("indexing " + this.getNameFromGraph(id));
  204. List<String> friendsIds = this.api.getFriends(id);
  205. //find ones not in database
  206. List<String> notInDatabase = new ArrayList<>();
  207. for(String fid : friendsIds)
  208. {
  209. if(!this.alreadyInGraph(fid))
  210. {
  211. notInDatabase.add(fid);
  212. }
  213. }
  214. Map<String, String> names = this.api.getNames(notInDatabase);
  215. for(String key: names.keySet())
  216. {
  217. this.insertPlayerIntoGraph(key, names.get(key));
  218. }
  219. friendsIds.forEach(s-> this.insertEdgeIntoGraph(id, s));
  220. this.updateCrawledStatus(id);
  221. }
  222. /**
  223. * Fetches a player from the graph with all of its friends
  224. *
  225. * @param id
  226. * @return
  227. */
  228. public Player getPlayer(String id)
  229. {
  230. Player p;
  231. if(this.alreadyInGraph(id)) // yay
  232. {
  233. p = new Player(this.getNameFromGraph(id), id);
  234. if(!this.playerAlreadyIndexed(id)) //must index the person
  235. {
  236. this.indexPersonFriends(id);
  237. }
  238. p.setFriends(this.getFriendsFromGraph(id));
  239. }
  240. else //smh, shouldn't happen frequently
  241. {
  242. System.out.println("brand spanking new request " + id);
  243. String name = this.api.getPlayerName(id);
  244. if(name == null)
  245. {
  246. return null;
  247. }
  248. else
  249. {
  250. this.insertPlayerIntoGraph(id, name);
  251. return this.getPlayer(id);
  252. }
  253. }
  254. return p;
  255. }
  256. /**
  257. *
  258. * @param args
  259. */
  260. public static void main(String[] args)
  261. {
  262. // SteamGraph graph = new SteamGraph();
  263. //
  264. // Player base = graph.getPlayer(args[0]);
  265. //
  266. // int debth = Integer.valueOf(args[1]);
  267. //
  268. // graph.insertIntoGraph(base, debth);
  269. }
  270. }