GetNetworkAsync ( String tag, WhatToInclude whatToInclude, NetworkLevel networkLevel, String apiKey ) { Debug.Assert(!String.IsNullOrEmpty(tag)); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert(!String.IsNullOrEmpty(apiKey)); AssertValid(); const String MethodName = "GetNetworkAsync"; CheckIsBusy(MethodName); // Wrap the arguments in an object that can be passed to // BackgroundWorker.RunWorkerAsync(). GetNetworkAsyncArgs oGetNetworkAsyncArgs = new GetNetworkAsyncArgs(); oGetNetworkAsyncArgs.Tag = tag; oGetNetworkAsyncArgs.NetworkLevel = networkLevel; oGetNetworkAsyncArgs.WhatToInclude = whatToInclude; oGetNetworkAsyncArgs.ApiKey = apiKey; m_oBackgroundWorker.RunWorkerAsync(oGetNetworkAsyncArgs); }
/// <summary> /// Creates a new <see cref="SelectionCandidate"/> ranker. /// </summary> /// <param name="stabilityPolicy">Implementations at this stability level or higher are preferred. Lower levels are used only if there is no other choice.</param> /// <param name="networkUse">Controls how liberally network access is attempted.</param> /// <param name="languages">The preferred languages for the implementation.</param> /// <param name="isCached">Used to determine which implementations are already cached in the <see cref="IImplementationStore"/>.</param> public SelectionCandidateComparer(Stability stabilityPolicy, NetworkLevel networkUse, LanguageSet languages, Predicate <Implementation> isCached) { _stabilityPolicy = stabilityPolicy; _networkUse = networkUse; _languages = languages ?? throw new ArgumentNullException(nameof(languages)); _isCached = isCached ?? throw new ArgumentNullException(nameof(isCached)); }
GetNetworkDescription ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel ) { Debug.Assert(!String.IsNullOrEmpty(sTag)); AssertValid(); NetworkDescriber oNetworkDescriber = new NetworkDescriber(); oNetworkDescriber.AddSentence( "The graph represents the {0} network of Flickr tags related to" + " the tag \"{1}\"." , NetworkLevelToString(eNetworkLevel), sTag ); oNetworkDescriber.AddNetworkTime(NetworkSource); return(oNetworkDescriber.ConcatenateSentences()); }
GetNetworkAsync ( String userNameToAnalyze, WhatToInclude whatToInclude, NetworkLevel networkLevel, Int32 maximumPeoplePerRequest ) { Debug.Assert(!String.IsNullOrEmpty(userNameToAnalyze)); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert(maximumPeoplePerRequest > 0); AssertValid(); const String MethodName = "GetNetworkAsync"; CheckIsBusy(MethodName); // Wrap the arguments in an object that can be passed to // BackgroundWorker.RunWorkerAsync(). GetNetworkAsyncArgs oGetNetworkAsyncArgs = new GetNetworkAsyncArgs(); oGetNetworkAsyncArgs.UserNameToAnalyze = userNameToAnalyze; oGetNetworkAsyncArgs.WhatToInclude = whatToInclude; oGetNetworkAsyncArgs.NetworkLevel = networkLevel; oGetNetworkAsyncArgs.MaximumPeoplePerRequest = maximumPeoplePerRequest; m_oBackgroundWorker.RunWorkerAsync(oGetNetworkAsyncArgs); }
NetworkLevelToString ( NetworkLevel eNetworkLevel ) { AssertValid(); String sNetworkLevel = String.Empty; switch (eNetworkLevel) { case NetworkLevel.One: sNetworkLevel = "1"; break; case NetworkLevel.OnePointFive: sNetworkLevel = "1.5"; break; case NetworkLevel.Two: sNetworkLevel = "2"; break; case NetworkLevel.TwoPointFive: sNetworkLevel = "2.5"; break; case NetworkLevel.Three: sNetworkLevel = "3"; break; case NetworkLevel.ThreePointFive: sNetworkLevel = "3.5"; break; case NetworkLevel.Four: sNetworkLevel = "4"; break; case NetworkLevel.FourPointFive: sNetworkLevel = "4.5"; break; default: Debug.Assert(false); break; } return(sNetworkLevel + "-level"); }
GetUserNetworkInternal ( String sUserNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(!String.IsNullOrEmpty(sUserNameToAnalyze)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the user name and the value is the corresponding GraphML // XML node that represents the user. This is used to prevent the same // user name from being added to the XmlDocument twice. Dictionary <String, XmlNode> oUserNameDictionary = new Dictionary <String, XmlNode>(); // Include friends, subscriptions, both, or neither. Boolean [] abIncludes = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FriendVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SubscriptionVertices), }; for (Int32 i = 0; i < 2; i++) { if (abIncludes[i]) { GetUserNetworkRecursive(sUserNameToAnalyze, eWhatToInclude, (i == 0), eNetworkLevel, iMaximumPeoplePerRequest, 1, oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } } if (WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.AllStatistics)) { AppendAllStatisticGraphMLAttributeValues(oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } }
private void Update() { if (_session == null) { return; } var result = _session.Process(); switch (result.Type) { case ProcessingResult.ResultType.None: break; case ProcessingResult.ResultType.Error: Debug.LogError($"{result.SessionError} {result.ServerErrorId}"); break; case ProcessingResult.ResultType.Joined: Debug.Log("Waiting for players..."); break; case ProcessingResult.ResultType.Started: Debug.Log("Session started"); var inputSource = new KeyboardInputSource(Keyboard.current, Key.W, Key.S); var viewFactory = new LevelViewFactory(_assetLoader, new UiSystem(_assetLoader, _canvas)); _level = new NetworkLevel(inputSource, viewFactory, this, result.StartMessage); break; case ProcessingResult.ResultType.Active: if (!_level.HandleReceivedInputs(_session.ReceivedInputs)) { Debug.LogError(SessionError.ProtocolError); break; } var(inputs, optMsgFinish) = _level.Tick(); var optError = _session.SendMessages(inputs, optMsgFinish); if (optError.HasValue) { Debug.LogError(optError.Value); } break; case ProcessingResult.ResultType.Finished: var msgFinish = result.FinishMessage; var frames = string.Join(", ", msgFinish.Frames); var hashes = string.Join(", ", msgFinish.Hashes); var(frame, simulations) = _level.SimulationStats; Debug.Log($"Session finished at [{frames}] with state [{hashes}]\nSimulations: {frame} / {simulations}"); break; default: throw new ArgumentOutOfRangeException(); } }
public override void OnInspectorGUI() { DrawDefaultInspector(); NetworkLevel myScript = (NetworkLevel)target; if (GUILayout.Button("Toggle Pause")) { myScript.TogglePause(); } }
private void Awake() { if (Instance) { Destroy(this); } else { Instance = this; } paused.OnValueChanged += OnPause; ready.OnValueChanged += OnReady; }
GetNetworkDescription ( String sUserNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert(!String.IsNullOrEmpty(sUserNameToAnalyze)); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); NetworkDescriber oNetworkDescriber = new NetworkDescriber(); oNetworkDescriber.AddSentence( "The graph represents the {0} YouTube network of the user with the" + " username \"{1}\"." , NetworkLevelToString(eNetworkLevel), sUserNameToAnalyze ); oNetworkDescriber.AddNetworkTime(NetworkSource); oNetworkDescriber.StartNewParagraph(); if (WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FriendVertices)) { oNetworkDescriber.AddSentence( "There is a vertex for each friend of the user." ); } if (WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SubscriptionVertices)) { oNetworkDescriber.AddSentence( "There is a vertex for each person or channel subscribed to by" + " the user." ); } oNetworkDescriber.AddNetworkLimit(iMaximumPeoplePerRequest, "people"); return(oNetworkDescriber.ConcatenateSentences()); }
GetUserNetworkInternal ( String sScreenName, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest, String sApiKey ) { Debug.Assert(!String.IsNullOrEmpty(sScreenName)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPerRequest > 0); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.CommenterVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.UserInformation) ); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetUserNetworkInternal(sScreenName, eWhatToInclude, eNetworkLevel, iMaximumPerRequest, sApiKey, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnTerminatingException(oException); } OnNetworkObtainedWithoutTerminatingException(oGraphMLXmlDocument, oRequestStatistics); return(oGraphMLXmlDocument); }
GetUserNetworkInternal ( String sUserNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert(!String.IsNullOrEmpty(sUserNameToAnalyze)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument(WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.AllStatistics)); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetUserNetworkInternal(sUserNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnUnexpectedException(oException, oGraphMLXmlDocument, oRequestStatistics); } String sNetworkTitle = "YouTube User " + sUserNameToAnalyze; OnNetworkObtained(oGraphMLXmlDocument, oRequestStatistics, GetNetworkDescription(sUserNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest), sNetworkTitle, sNetworkTitle ); return(oGraphMLXmlDocument); }
GetNeedToAppendVertices ( NetworkLevel eNetworkLevel, Int32 iRecursionLevel ) { Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); AssertValid(); return( (eNetworkLevel != NetworkLevel.OnePointFive || iRecursionLevel == 1) ); }
GetRelatedTagsInternal ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey ) { Debug.Assert(!String.IsNullOrEmpty(sTag)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SampleThumbnails)); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetRelatedTagsInternal(sTag, eWhatToInclude, eNetworkLevel, sApiKey, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnUnexpectedException(oException, oGraphMLXmlDocument, oRequestStatistics); } String sNetworkTitle = "Flickr Tag " + sTag; OnNetworkObtained(oGraphMLXmlDocument, oRequestStatistics, GetNetworkDescription(sTag, eWhatToInclude, eNetworkLevel), sNetworkTitle, sNetworkTitle ); return(oGraphMLXmlDocument); }
GetUserNetworkInternal ( String sScreenNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert(!String.IsNullOrEmpty(sScreenNameToAnalyze)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); BeforeGetNetwork(); Boolean bIncludeLatestStatus = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.LatestStatuses); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument(true, bIncludeLatestStatus); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetUserNetworkInternal(sScreenNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnTerminatingException(oException); } OnNetworkObtainedWithoutTerminatingException(oGraphMLXmlDocument, oRequestStatistics); return(oGraphMLXmlDocument); }
GetNeedToRecurse ( NetworkLevel eNetworkLevel, Int32 iRecursionLevel ) { Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); AssertValid(); return( iRecursionLevel == 1 && (eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two) ); }
GetNetwork ( String screenNameToAnalyze, WhatToInclude whatToInclude, NetworkLevel networkLevel, Int32 maximumPeoplePerRequest ) { Debug.Assert(!String.IsNullOrEmpty(screenNameToAnalyze)); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert(maximumPeoplePerRequest > 0); AssertValid(); return(GetUserNetworkInternal(screenNameToAnalyze, whatToInclude, networkLevel, maximumPeoplePerRequest)); }
GetTwitterUserNetworkConfiguration ( out String screenNameToAnalyze, out TwitterUserNetworkAnalyzer.WhatToInclude whatToInclude, out NetworkLevel networkLevel, out Int32 maximumPeoplePerRequest, out String networkFileFolderPath, out NetworkFileFormats networkFileFormats, out Boolean automateNodeXLWorkbook ) { AssertValid(); Debug.Assert(m_oNetworkConfigurationXmlDocument != null); Debug.Assert(GetNetworkType() == NetworkType.TwitterUser); networkFileFolderPath = null; XmlNode oTwitterUserNetworkConfigurationNode = XmlUtil2.SelectRequiredSingleNode( m_oNetworkConfigurationXmlDocument, "/NetworkConfiguration/TwitterUserNetworkConfiguration", null); screenNameToAnalyze = XmlUtil2.SelectRequiredSingleNodeAsString( oTwitterUserNetworkConfigurationNode, "ScreenNameToAnalyze/text()", null); whatToInclude = GetRequiredEnumValue <TwitterUserNetworkAnalyzer.WhatToInclude>( oTwitterUserNetworkConfigurationNode, "WhatToInclude/text()", "WhatToInclude"); networkLevel = GetRequiredEnumValue <NetworkLevel>( oTwitterUserNetworkConfigurationNode, "NetworkLevel/text()", "NetworkLevel"); GetTwitterCommonConfiguration(oTwitterUserNetworkConfigurationNode, out maximumPeoplePerRequest, out networkFileFolderPath, out networkFileFormats, out automateNodeXLWorkbook); }
GetRelatedTagsInternal ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey ) { Debug.Assert(!String.IsNullOrEmpty(sTag)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SampleThumbnails)); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetRelatedTagsInternal(sTag, eWhatToInclude, eNetworkLevel, sApiKey, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnTerminatingException(oException); } OnNetworkObtainedWithoutTerminatingException(oGraphMLXmlDocument, oRequestStatistics); return(oGraphMLXmlDocument); }
GetRelatedTagsInternal ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(!String.IsNullOrEmpty(sTag)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the tag name and the value is the corresponding GraphML // XML node that represents the tag. This is used to prevent the same // tag from being added to the XmlDocument twice. Dictionary <String, XmlNode> oTagDictionary = new Dictionary <String, XmlNode>(); GetRelatedTagsRecursive(sTag, eWhatToInclude, eNetworkLevel, sApiKey, 1, oGraphMLXmlDocument, oTagDictionary, oRequestStatistics); if (WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SampleThumbnails)) { AppendSampleThumbnails(oTagDictionary, oGraphMLXmlDocument, sApiKey, oRequestStatistics); } }
/// <summary> /// Creates a new <see cref="SelectionCandidate"/> ranker. /// </summary> /// <param name="config">Used to retrieve global configuration.</param> /// <param name="isCached">Used to determine which implementations are already cached in the <see cref="IStore"/>.</param> /// <param name="stabilityPolicy">Implementations at this stability level or higher are preferred. Lower levels are used only if there is no other choice. Must not be <see cref="Stability.Unset"/>!</param> /// <param name="culture">The user's culture, used to determine preferred languages.</param> public SelectionCandidateComparer([NotNull] Config config, [NotNull] Predicate <Implementation> isCached, Stability stabilityPolicy, [NotNull] CultureInfo culture) { #region Sanity check if (config == null) { throw new ArgumentNullException("config"); } if (isCached == null) { throw new ArgumentNullException("isCached"); } if (culture == null) { throw new ArgumentNullException("culture"); } #endregion _networkUse = config.NetworkUse; _isCached = isCached; _stabilityPolicy = (stabilityPolicy == Stability.Unset) ? (config.HelpWithTesting ? Stability.Testing : Stability.Stable) : stabilityPolicy; _culture = culture; }
/// <summary> /// Creates a new <see cref="SelectionCandidate"/> ranker. /// </summary> /// <param name="config">Used to retrieve global configuration.</param> /// <param name="isCached">Used to determine which implementations are already cached in the <see cref="IStore"/>.</param> /// <param name="stabilityPolicy">Implementations at this stability level or higher are preferred. Lower levels are used only if there is no other choice. Must not be <see cref="Stability.Unset"/>!</param> /// <param name="languages">The preferred languages for the implementation.</param> public SelectionCandidateComparer([NotNull] Config config, [NotNull] Predicate <Implementation> isCached, Stability stabilityPolicy, [NotNull] LanguageSet languages) { #region Sanity check if (config == null) { throw new ArgumentNullException(nameof(config)); } if (isCached == null) { throw new ArgumentNullException(nameof(isCached)); } if (languages == null) { throw new ArgumentNullException(nameof(languages)); } #endregion _networkUse = config.NetworkUse; _isCached = isCached; _stabilityPolicy = (stabilityPolicy == Stability.Unset) ? (config.HelpWithTesting ? Stability.Testing : Stability.Stable) : stabilityPolicy; _languages = languages; }
GetNetworkDescription ( String sScreenNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert( !String.IsNullOrEmpty(sScreenNameToAnalyze) ); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); NetworkDescriber oNetworkDescriber = new NetworkDescriber(); oNetworkDescriber.AddSentence( "The graph represents the {0} Twitter network of the user with the" + " username \"{1}\"." , NetworkLevelToString(eNetworkLevel), sScreenNameToAnalyze ); oNetworkDescriber.AddNetworkTime(NetworkSource); oNetworkDescriber.StartNewParagraph(); Boolean bFollowedVertices = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedVertices); Boolean bFollowerVertices = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowerVertices); if (bFollowedVertices) { oNetworkDescriber.AddSentence( "There is a vertex for each person followed by the user." ); } if (bFollowerVertices) { oNetworkDescriber.AddSentence( "There is a vertex for each person following the user." ); } oNetworkDescriber.AddNetworkLimit(iMaximumPeoplePerRequest, "people"); if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedFollowerEdges | WhatToInclude.RepliesToEdges | WhatToInclude.MentionsEdges ) ) { oNetworkDescriber.StartNewParagraph(); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedFollowerEdges) ) { if (bFollowedVertices) { oNetworkDescriber.AddSentence( "There is an edge for each followed relationship." ); } if (bFollowerVertices) { oNetworkDescriber.AddSentence( "There is an edge for each following relationship." ); } } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.RepliesToEdges) ) { oNetworkDescriber.AddSentence( "There is an edge for each \"replies-to\" relationship in the" + " user's latest tweet." ); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.MentionsEdges) ) { oNetworkDescriber.AddSentence( "There is an edge for each \"mentions\" relationship in the" + " user's latest tweet." ); } return ( oNetworkDescriber.ConcatenateSentences() ); }
//************************************************************************* // Method: DoDataExchange() // /// <summary> /// Transfers data between the dialog's fields and its controls. /// </summary> /// /// <param name="bFromControls"> /// true to transfer data from the dialog's controls to its fields, false /// for the other direction. /// </param> /// /// <returns> /// true if the transfer was successful. /// </returns> //************************************************************************* protected override Boolean DoDataExchange( Boolean bFromControls ) { if (bFromControls) { // Validate the controls. if ( !ValidateRequiredTextBox(txbScreenNameToAnalyze, "Enter the screen name of a Twitter user.", out m_sScreenNameToAnalyze) ) { return (false); } m_bIncludeFollowedVertices = m_bIncludeFollowerVertices = false; if (radIncludeFollowedVertices.Checked) { m_bIncludeFollowedVertices = true; } else if (radIncludeFollowerVertices.Checked) { m_bIncludeFollowerVertices = true; } else { m_bIncludeFollowedVertices = m_bIncludeFollowerVertices = true; } m_bIncludeFollowedFollowerEdges = chkIncludeFollowedFollowerEdges.Checked; m_bIncludeRepliesToEdges = chkIncludeRepliesToEdges.Checked; m_bIncludeMentionsEdges = chkIncludeMentionsEdges.Checked; m_eNetworkLevel = usrNetworkLevel.Level; m_bIncludeLatestStatuses = chkIncludeLatestStatuses.Checked; m_iMaximumPeoplePerRequest = usrLimitToN.N; } else { txbScreenNameToAnalyze.Text = m_sScreenNameToAnalyze; if (m_bIncludeFollowedVertices) { if (m_bIncludeFollowerVertices) { radIncludeFollowedAndFollower.Checked = true; } else { radIncludeFollowedVertices.Checked = true; } } else { radIncludeFollowerVertices.Checked = true; } chkIncludeFollowedFollowerEdges.Checked = m_bIncludeFollowedFollowerEdges; chkIncludeRepliesToEdges.Checked = m_bIncludeRepliesToEdges; chkIncludeMentionsEdges.Checked = m_bIncludeMentionsEdges; usrNetworkLevel.Level = m_eNetworkLevel; chkIncludeLatestStatuses.Checked = m_bIncludeLatestStatuses; usrLimitToN.N = m_iMaximumPeoplePerRequest; EnableControls(); } return (true); }
GetNetworkInternal ( String sScreenNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sScreenNameToAnalyze) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); sScreenNameToAnalyze = sScreenNameToAnalyze.ToLower(); // The unique screen names of the people in the network. HashSet<String> oUniqueScreenNames = new HashSet<String>(); // The key is the Twitter user ID and the value is the corresponding // TwitterUser. This is used by AppendOnePointFiveDegreeNetwork() to // determine which Twitter users are in the 1-degree network. Dictionary<String, TwitterUser> oUserIDDictionary = new Dictionary<String, TwitterUser>(); // The screen names of people followed by (or following) sScreenName. HashSet<String> oOneDegreeOtherScreenNames = new HashSet<String>(); // Include followed, followers, both, or neither. Boolean [] abFollowedFollowerFlags = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowerVertices), }; for (Int32 i = 0; i < 2; i++) { if ( abFollowedFollowerFlags[i] ) { // Always start with a 1-degree network. AppendOneDegreeNetwork(sScreenNameToAnalyze, eWhatToInclude, (i == 0), iMaximumPeoplePerRequest, oGraphMLXmlDocument, oUniqueScreenNames, oUserIDDictionary, oOneDegreeOtherScreenNames, oRequestStatistics); } } for (Int32 i = 0; i < 2; i++) { if ( abFollowedFollowerFlags[i] ) { if (eNetworkLevel == NetworkLevel.OnePointFive) { // Append edges to make it a 1.5-degree network. AppendOnePointFiveDegreeNetwork(sScreenNameToAnalyze, eWhatToInclude, (i == 0), iMaximumPeoplePerRequest, oGraphMLXmlDocument, oUserIDDictionary, oOneDegreeOtherScreenNames, oRequestStatistics); } else if (eNetworkLevel == NetworkLevel.Two) { // Append vertices and edges to make it a 2-degree network. AppendTwoDegreeNetwork(sScreenNameToAnalyze, eWhatToInclude, (i == 0), iMaximumPeoplePerRequest, oGraphMLXmlDocument, oUniqueScreenNames, oUserIDDictionary, oOneDegreeOtherScreenNames, oRequestStatistics); } } } AppendRepliesToAndMentionsEdgeXmlNodes(oGraphMLXmlDocument, oUserIDDictionary.Values, oUniqueScreenNames, WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.RepliesToEdges), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.MentionsEdges), false, false ); }
GetRelatedTagsRecursive ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary <String, XmlNode> oTagDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sTag)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oTagDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* * Here is what this method should do, based on the eNetworkLevel and * iRecursionLevel parameters. * * eNetworkLevel * |One | OnePointFive | Two * ---|------------------| ------------------| ----------------- * i 1 |Add all vertices. | Add all vertices. | Add all vertices. * R | | | * e |Add all edges. | Add all edges. | Add all edges. * c | | | * u |Do not recurse. | Recurse. | Recurse. * r | | | * s ---|------------------|-------------------|------------------ * i 2 |Impossible. | Do not add | Add all vertices. * o | | vertices. | * n | | | * L | | Add edges only if | Add all edges. * e | | vertices are | * v | | already included. | * e | | | * l | | Do not recurse. | Do not recurse. | | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); ReportProgress("Getting tags related to \"" + sTag + "\"."); String sUrl = GetFlickrMethodUrl("flickr.tags.getRelated", sApiKey, "&tag=" + UrlUtil.EncodeUrlParameter(sTag)); XmlDocument oXmlDocument; try { oXmlDocument = GetXmlDocument(sUrl, oRequestStatistics); } catch (Exception oException) { // If the exception is not a WebException or XmlException, or if // none of the network has been obtained yet, throw the exception. if (!HttpSocialNetworkUtil.ExceptionIsWebOrXml(oException) || !oGraphMLXmlDocument.HasVertexXmlNode) { throw oException; } return; } // The document consists of a single "tags" node with zero or more // "tag" child nodes. String sOtherTag = null; XmlNodeList oTagNodes = oXmlDocument.DocumentElement.SelectNodes( "tags/tag"); if (oTagNodes.Count > 0) { AppendVertexXmlNode(sTag, oGraphMLXmlDocument, oTagDictionary); } foreach (XmlNode oTagNode in oTagNodes) { sOtherTag = XmlUtil2.SelectRequiredSingleNodeAsString(oTagNode, "text()", null); if (bNeedToAppendVertices) { AppendVertexXmlNode(sOtherTag, oGraphMLXmlDocument, oTagDictionary); } if (bNeedToAppendVertices || oTagDictionary.ContainsKey(sOtherTag)) { oGraphMLXmlDocument.AppendEdgeXmlNode(sTag, sOtherTag); } } if (bNeedToRecurse) { foreach (XmlNode oTagNode in oTagNodes) { sOtherTag = XmlUtil2.SelectRequiredSingleNodeAsString(oTagNode, "text()", null); GetRelatedTagsRecursive(sOtherTag, eWhatToInclude, eNetworkLevel, sApiKey, 2, oGraphMLXmlDocument, oTagDictionary, oRequestStatistics); } } }
GetTwitterUserNetwork ( DateTime oStartTime, String sNetworkConfigurationFilePath, NetworkConfigurationFileParser oNetworkConfigurationFileParser, out XmlDocument oXmlDocument, out String sNetworkFileFolderPath, out NetworkFileFormats eNetworkFileFormats, out Boolean bAutomateNodeXLWorkbook ) { Debug.Assert(!String.IsNullOrEmpty(sNetworkConfigurationFilePath)); Debug.Assert(oNetworkConfigurationFileParser != null); oXmlDocument = null; sNetworkFileFolderPath = null; eNetworkFileFormats = NetworkFileFormats.None; bAutomateNodeXLWorkbook = false; String sScreenNameToAnalyze = null; TwitterUserNetworkAnalyzer.WhatToInclude eWhatToInclude = TwitterUserNetworkAnalyzer.WhatToInclude.None; NetworkLevel eNetworkLevel = NetworkLevel.One; Int32 iMaximumPeoplePerRequest = Int32.MaxValue; try { oNetworkConfigurationFileParser.GetTwitterUserNetworkConfiguration( out sScreenNameToAnalyze, out eWhatToInclude, out eNetworkLevel, out iMaximumPeoplePerRequest, out sNetworkFileFolderPath, out eNetworkFileFormats, out bAutomateNodeXLWorkbook); } catch (XmlException oXmlException) { // (This call exits the program.) OnNetworkConfigurationFileException(oXmlException); } TwitterUserNetworkAnalyzer oTwitterUserNetworkAnalyzer = new TwitterUserNetworkAnalyzer(); oTwitterUserNetworkAnalyzer.ProgressChanged += new ProgressChangedEventHandler( HttpNetworkAnalyzer_ProgressChanged); Console.WriteLine( "Getting the Twitter User network specified in \"{0}\". The" + " screen name is \"{1}\"." , sNetworkConfigurationFilePath, sScreenNameToAnalyze ); try { oXmlDocument = oTwitterUserNetworkAnalyzer.GetNetwork( sScreenNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest); } catch (PartialNetworkException oPartialNetworkException) { oXmlDocument = OnGetNetworkPartialNetworkException(oStartTime, oPartialNetworkException, sNetworkConfigurationFilePath, sNetworkFileFolderPath, oTwitterUserNetworkAnalyzer); } catch (Exception oException) { // (This call exits the program.) OnGetNetworkOtherException(oStartTime, oException, sNetworkConfigurationFilePath, sNetworkFileFolderPath, oTwitterUserNetworkAnalyzer); } }
NetworkLevelToString ( NetworkLevel eNetworkLevel ) { AssertValid(); String sNetworkLevel = String.Empty; switch (eNetworkLevel) { case NetworkLevel.One: sNetworkLevel = "1"; break; case NetworkLevel.OnePointFive: sNetworkLevel = "1.5"; break; case NetworkLevel.Two: sNetworkLevel = "2"; break; case NetworkLevel.TwoPointFive: sNetworkLevel = "2.5"; break; case NetworkLevel.Three: sNetworkLevel = "3"; break; case NetworkLevel.ThreePointFive: sNetworkLevel = "3.5"; break; case NetworkLevel.Four: sNetworkLevel = "4"; break; case NetworkLevel.FourPointFive: sNetworkLevel = "4.5"; break; default: Debug.Assert(false); break; } return (sNetworkLevel + "-level"); }
//************************************************************************* // Method: GetNeedToAppendVertices() // /// <summary> /// Determines whether a method getting a recursive network needs to /// add vertices for a specified network and recursion level. /// </summary> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iRecursionLevel"> /// Recursion level for the current call. Must be 1 or 2. /// </param> /// /// <returns> /// true if the caller needs to add vertices for the specified network and /// recursion levels. /// </returns> /// /// <remarks> /// This is meant for network analyzers that analyze a recursive network. /// Call this from the method that uses recursion to get the different /// network levels, and use the return value to determine whether to add /// vertices for the current network and recursion levels. /// </remarks> //************************************************************************* protected Boolean GetNeedToAppendVertices( NetworkLevel eNetworkLevel, Int32 iRecursionLevel ) { Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); AssertValid(); return ( (eNetworkLevel != NetworkLevel.OnePointFive || iRecursionLevel == 1) ); }
GetNetworkAsync ( String screenName, WhatToInclude whatToInclude, NetworkLevel networkLevel, Int32 maximumPerRequest, String apiKey ) { Debug.Assert( !String.IsNullOrEmpty(screenName) ); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert(maximumPerRequest > 0); Debug.Assert( !String.IsNullOrEmpty(apiKey) ); AssertValid(); const String MethodName = "GetNetworkAsync"; CheckIsBusy(MethodName); // Wrap the arguments in an object that can be passed to // BackgroundWorker.RunWorkerAsync(). GetNetworkAsyncArgs oGetNetworkAsyncArgs = new GetNetworkAsyncArgs(); oGetNetworkAsyncArgs.ScreenName = screenName; oGetNetworkAsyncArgs.WhatToInclude = whatToInclude; oGetNetworkAsyncArgs.NetworkLevel = networkLevel; oGetNetworkAsyncArgs.MaximumPerRequest = maximumPerRequest; oGetNetworkAsyncArgs.ApiKey = apiKey; m_oBackgroundWorker.RunWorkerAsync(oGetNetworkAsyncArgs); }
//************************************************************************* // Method: GetUserNetworkRecursive() // /// <summary> /// Recursively gets a network of Twitter users. /// </summary> /// /// <param name="sScreenName"> /// The screen name to use in this call. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="bIncludeFollowedThisCall"> /// true to include the people followed by the user, false to include the /// people following the user. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iMaximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <param name="iRecursionLevel"> /// Recursion level for this call. Must be 1 or 2. Gets incremented when /// recursing. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oScreenNameDictionary"> /// The key is the screen name in lower case and the value is the /// corresponding TwitterVertex. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> //************************************************************************* protected void GetUserNetworkRecursive( String sScreenName, WhatToInclude eWhatToInclude, Boolean bIncludeFollowedThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, TwitterVertex> oScreenNameDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oScreenNameDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* Here is what this method should do, based on the eNetworkLevel and iRecursionLevel parameters. It's assumed that eWhatToInclude.FollowedFollowerEdge is set. eNetworkLevel |One | OnePointFive | Two ---|------------------| ------------------| ----------------- i 1 |Add all vertices. | Add all vertices. | Add all vertices. R | | | e |Add all edges. | Add all edges. | Add all edges. c | | | u |Do not recurse. | Recurse. | Recurse. r | | | s ---|------------------|-------------------|------------------ i 2 |Impossible. | Do not add | Add all vertices. o | | vertices. | n | | | L | | Add edges only if | Add all edges. e | | vertices are | v | | already included. | e | | | l | | Do not recurse. | Do not recurse. | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); List<String> oScreenNamesToRecurse = new List<String>(); Boolean bIncludeLatestStatuses = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.LatestStatuses); ReportProgressForFollowedOrFollowing(sScreenName, bIncludeFollowedThisCall); Boolean bThisUserAppended = false; // If the GraphMLXmlDocument already contains at least one vertex node, // then this is the second time that this method has been called, a // partial network has already been obtained, and most errors should // now be skipped. However, if none of the network has been obtained // yet, errors on page 1 should throw an immediate exception. Boolean bSkipMostPage1Errors = oGraphMLXmlDocument.HasVertexXmlNode; // The document consists of a single "users" node with zero or more // "user" child nodes. foreach ( XmlNode oUserXmlNode in EnumerateXmlNodes( GetFollowedOrFollowingUrl(sScreenName, bIncludeFollowedThisCall), "users_list/users/user", null, null, Int32.MaxValue, iMaximumPeoplePerRequest, false, bSkipMostPage1Errors, oRequestStatistics) ) { String sOtherScreenName; if ( !TryGetScreenName(oUserXmlNode, out sOtherScreenName) ) { // Nothing can be done without a screen name. continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a Twitter error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sScreenName, null, oGraphMLXmlDocument, oScreenNameDictionary, true, bIncludeLatestStatuses); bThisUserAppended = true; } Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherScreenName, oUserXmlNode, oGraphMLXmlDocument, oScreenNameDictionary, true, bIncludeLatestStatuses) && bNeedToRecurse ) { oScreenNamesToRecurse.Add(sOtherScreenName); } } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedFollowerEdges) ) { if ( bNeedToAppendVertices || oScreenNameDictionary.ContainsKey(sOtherScreenName) ) { XmlNode oEdgeXmlNode; if (bIncludeFollowedThisCall) { oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument, sScreenName, sOtherScreenName, "Followed"); } else { oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument, sOtherScreenName, sScreenName, "Follower"); } AppendRelationshipDateUtcGraphMLAttributeValue( oGraphMLXmlDocument, oEdgeXmlNode, oRequestStatistics); } } } if (bNeedToRecurse) { foreach (String sScreenNameToRecurse in oScreenNamesToRecurse) { GetUserNetworkRecursive(sScreenNameToRecurse, eWhatToInclude, bIncludeFollowedThisCall, eNetworkLevel, iMaximumPeoplePerRequest, 2, oGraphMLXmlDocument, oScreenNameDictionary, oRequestStatistics); } } }
GetUserNetworkInternal ( String sScreenName, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest, String sApiKey, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPerRequest > 0); Debug.Assert( !String.IsNullOrEmpty(sApiKey) ); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); String sUserID; // Get the user's ID and the correct case of the screen name. FlickrScreenNameToUserID(sScreenName, sApiKey, oRequestStatistics, out sUserID, out sScreenName); // The key is the user ID name and the value is the corresponding // GraphML XML node that represents the user. This is used to prevent // the same user ID from being added to the XmlDocument twice. Dictionary<String, XmlNode> oUserIDDictionary = new Dictionary<String, XmlNode>(); // Include contacts, commenters, both, or neither. Boolean [] abIncludes = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.ContactVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.CommenterVertices), }; for (Int32 i = 0; i < 2; i++) { if ( abIncludes[i] ) { GetUserNetworkRecursive(sUserID, sScreenName, eWhatToInclude, (i == 0), eNetworkLevel, iMaximumPerRequest, sApiKey, 1, oGraphMLXmlDocument, oUserIDDictionary, oRequestStatistics); } } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.UserInformation) ) { AppendUserInformationGraphMLAttributeValues(oGraphMLXmlDocument, oUserIDDictionary, sApiKey, oRequestStatistics); } }
//************************************************************************* // Method: GetUserNetworkInternal() // /// <summary> /// Gets a network of Twitter users, given a GraphMLXmlDocument. /// </summary> /// /// <param name="sScreenNameToAnalyze"> /// The screen name of the Twitter user whose network should be analyzed. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iMaximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// The GraphMLXmlDocument to populate with the requested network. /// </param> //************************************************************************* protected void GetUserNetworkInternal( String sScreenNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sScreenNameToAnalyze) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the screen name and the value is the corresponding // TwitterVertex. This is used to prevent the same screen name from // being added to the XmlDocument twice. Dictionary<String, TwitterVertex> oScreenNameDictionary = new Dictionary<String, TwitterVertex>(); // Include followed, followers, both, or neither. Boolean [] abIncludes = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowerVertices), }; for (Int32 i = 0; i < 2; i++) { if ( abIncludes[i] ) { GetUserNetworkRecursive(sScreenNameToAnalyze, eWhatToInclude, (i == 0), eNetworkLevel, iMaximumPeoplePerRequest, 1, oGraphMLXmlDocument, oScreenNameDictionary, oRequestStatistics); } } Boolean bIncludeLatestStatus = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.LatestStatuses); AppendMissingGraphMLAttributeValues(oGraphMLXmlDocument, oScreenNameDictionary, true, bIncludeLatestStatus, oRequestStatistics); AppendRepliesToAndMentionsXmlNodes(oGraphMLXmlDocument, oScreenNameDictionary, WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.RepliesToEdges), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.MentionsEdges) ); }
//************************************************************************* // Method: GetNetwork() // /// <summary> /// Synchronously gets a directed network of Twitter users. /// </summary> /// /// <param name="screenNameToAnalyze"> /// The screen name of the Twitter user whose network should be analyzed. /// </param> /// /// <param name="whatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="networkLevel"> /// Network level to include. /// </param> /// /// <param name="maximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <returns> /// An XmlDocument containing the network as GraphML. /// </returns> //************************************************************************* public XmlDocument GetNetwork( String screenNameToAnalyze, WhatToInclude whatToInclude, NetworkLevel networkLevel, Int32 maximumPeoplePerRequest ) { Debug.Assert( !String.IsNullOrEmpty(screenNameToAnalyze) ); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert(maximumPeoplePerRequest > 0); AssertValid(); return ( GetUserNetworkInternal(screenNameToAnalyze, whatToInclude, networkLevel, maximumPeoplePerRequest) ); }
GetNetworkInternal ( String sScreenNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert( !String.IsNullOrEmpty(sScreenNameToAnalyze) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); BeforeGetNetwork(); Boolean bIncludeLatestStatus = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.LatestStatuses); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument(bIncludeLatestStatus); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetNetworkInternal(sScreenNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnUnexpectedException(oException, oGraphMLXmlDocument, oRequestStatistics); } OnNetworkObtained(oGraphMLXmlDocument, oRequestStatistics, GetNetworkDescription(sScreenNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest), "Twitter User " + sScreenNameToAnalyze ); return (oGraphMLXmlDocument); }
GetUserNetworkRecursive ( String sUserName, WhatToInclude eWhatToInclude, Boolean bIncludeFriendsThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary <String, XmlNode> oUserNameDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sUserName)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserNameDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* * Here is what this method should do, based on the eNetworkLevel and * iRecursionLevel parameters. * * eNetworkLevel * |One | OnePointFive | Two * ---|------------------| ------------------| ----------------- * i 1 |Add all vertices. | Add all vertices. | Add all vertices. * R | | | * e |Add all edges. | Add all edges. | Add all edges. * c | | | * u |Do not recurse. | Recurse. | Recurse. * r | | | * s ---|------------------|-------------------|------------------ * i 2 |Impossible. | Do not add | Add all vertices. * o | | vertices. | * n | | | * L | | Add edges only if | Add all edges. * e | | vertices are | * v | | already included. | * e | | | * l | | Do not recurse. | Do not recurse. | | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); List <String> oUserNamesToRecurse = new List <String>(); ReportProgressForFriendsOrSubscriptions(sUserName, bIncludeFriendsThisCall); Boolean bThisUserAppended = false; // If the GraphMLXmlDocument already contains at least one vertex node, // then this is the second time that this method has been called, a // partial network has already been obtained, and most errors should // now be skipped. However, if none of the network has been obtained // yet, errors on page 1 should throw an immediate exception. Boolean bSkipMostPage1Errors = oGraphMLXmlDocument.HasVertexXmlNode; // The document consists of a single "feed" node with zero or more // "entry" child nodes. foreach (XmlNode oEntryXmlNode in EnumerateXmlNodes( GetFriendsOrSubscriptionsUrl(sUserName, bIncludeFriendsThisCall), "a:feed/a:entry", iMaximumPeoplePerRequest, bSkipMostPage1Errors, oRequestStatistics)) { XmlNamespaceManager oXmlNamespaceManager = CreateXmlNamespaceManager(oEntryXmlNode.OwnerDocument); String sOtherUserName; if (!XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "yt:username/text()", oXmlNamespaceManager, out sOtherUserName)) { continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a YouTube error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sUserName, null, oGraphMLXmlDocument, oUserNameDictionary); bThisUserAppended = true; } Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherUserName, oEntryXmlNode, oGraphMLXmlDocument, oUserNameDictionary) && bNeedToRecurse ) { oUserNamesToRecurse.Add(sOtherUserName); } } if (bNeedToAppendVertices || oUserNameDictionary.ContainsKey(sOtherUserName)) { String sRelationship; if (bIncludeFriendsThisCall) { sRelationship = "Friend of"; } else { sRelationship = "Subscribes to"; String sSubscriptionType = null; if (XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "a:category[@scheme='http://gdata.youtube.com/schemas/" + "2007/subscriptiontypes.cat']/@term", oXmlNamespaceManager, out sSubscriptionType)) { sRelationship += " " + sSubscriptionType; } } NodeXLGraphMLUtil.AppendEdgeXmlNode(oGraphMLXmlDocument, sUserName, sOtherUserName, sRelationship); } } if (bNeedToRecurse) { foreach (String sUserNameToRecurse in oUserNamesToRecurse) { GetUserNetworkRecursive(sUserNameToRecurse, eWhatToInclude, bIncludeFriendsThisCall, eNetworkLevel, iMaximumPeoplePerRequest, 2, oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } } }
//************************************************************************* // Method: GetNeedToRecurse() // /// <summary> /// Determines whether a method getting a recursive network needs to /// recurse. /// </summary> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iRecursionLevel"> /// Recursion level for the current call. Must be 1 or 2. /// </param> /// /// <returns> /// true if the caller needs to recurse. /// </returns> /// /// <remarks> /// This is meant for network analyzers that analyze a recursive network. /// Call this from the method that uses recursion to get the different /// network levels, and use the return value to determine whether to /// recurse. /// </remarks> //************************************************************************* protected Boolean GetNeedToRecurse( NetworkLevel eNetworkLevel, Int32 iRecursionLevel ) { Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); AssertValid(); return ( iRecursionLevel == 1 && (eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two) ); }
GetNetworkDescription ( String sScreenName, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest ) { Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert(iMaximumPerRequest > 0); AssertValid(); NetworkDescriber oNetworkDescriber = new NetworkDescriber(); oNetworkDescriber.AddSentence( "The graph represents the {0} Flickr network of the user with the" + " screen name \"{1}\"." , NetworkLevelToString(eNetworkLevel), sScreenName ); oNetworkDescriber.AddNetworkTime(NetworkSource); oNetworkDescriber.StartNewParagraph(); if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.ContactVertices) ) { oNetworkDescriber.AddSentence( "There is a vertex for each contact of the user." ); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.CommenterVertices) ) { oNetworkDescriber.AddSentence( "There is a vertex for each person who commented on the user's" + " photos." ); } oNetworkDescriber.AddNetworkLimit(iMaximumPerRequest, "people"); return ( oNetworkDescriber.ConcatenateSentences() ); }
//************************************************************************* // Method: GetRelatedTagsInternal() // /// <overloads> /// Gets the Flickr tags related to a specified tag. /// </overloads> /// /// <summary> /// Gets the Flickr tags related to a specified tag. /// </summary> /// /// <param name="sTag"> /// Tag to get related tags for. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="sApiKey"> /// Flickr API key. /// </param> /// /// <returns> /// An XmlDocument containing the network as GraphML. /// </returns> //************************************************************************* protected XmlDocument GetRelatedTagsInternal( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey ) { Debug.Assert( !String.IsNullOrEmpty(sTag) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert( !String.IsNullOrEmpty(sApiKey) ); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SampleThumbnails) ); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetRelatedTagsInternal(sTag, eWhatToInclude, eNetworkLevel, sApiKey, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnTerminatingException(oException); } OnNetworkObtainedWithoutTerminatingException(oGraphMLXmlDocument, oRequestStatistics); return (oGraphMLXmlDocument); }
//************************************************************************* // Method: DoDataExchange() // /// <summary> /// Transfers data between the dialog's fields and its controls. /// </summary> /// /// <param name="bFromControls"> /// true to transfer data from the dialog's controls to its fields, false /// for the other direction. /// </param> /// /// <returns> /// true if the transfer was successful. /// </returns> //************************************************************************* protected override Boolean DoDataExchange( Boolean bFromControls ) { if (bFromControls) { // Validate the controls. if ( !ValidateRequiredTextBox(txbScreenName, "Enter the screen name of a Flickr user.", out m_sScreenName) || !usrFlickrApiKey.Validate() ) { return (false); } m_bIncludeContactVertices = m_bIncludeCommenterVertices = false; if (radIncludeContactVertices.Checked) { m_bIncludeContactVertices = true; } else if (radIncludeCommenterVertices.Checked) { m_bIncludeCommenterVertices = true; } else { m_bIncludeContactVertices = m_bIncludeCommenterVertices = true; } m_bIncludeUserInformation = chkIncludeUserInformation.Checked; m_eNetworkLevel = usrNetworkLevel.Level; m_iMaximumPeoplePerRequest = usrLimitToN.N; m_sApiKey = usrFlickrApiKey.ApiKey; } else { txbScreenName.Text = m_sScreenName; if (m_bIncludeContactVertices) { if (m_bIncludeCommenterVertices) { radIncludeContactsAndCommenters.Checked = true; } else { radIncludeContactVertices.Checked = true; } } else { radIncludeCommenterVertices.Checked = true; } chkIncludeUserInformation.Checked = m_bIncludeUserInformation; usrNetworkLevel.Level = m_eNetworkLevel; usrLimitToN.N = m_iMaximumPeoplePerRequest; usrFlickrApiKey.ApiKey = m_sApiKey; EnableControls(); } return (true); }
//************************************************************************* // Method: GetRelatedTagsRecursive() // /// <summary> /// Recursively gets a tag's related tags. /// </summary> /// /// <param name="sTag"> /// Tag to get related tags for. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="sApiKey"> /// Flickr API key. /// </param> /// /// <param name="iRecursionLevel"> /// Recursion level for this call. Must be 1 or 2. Gets incremented when /// recursing. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oTagDictionary"> /// The key is the tag name and the value is the corresponding GraphML XML /// node that represents the tag. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> //************************************************************************* protected void GetRelatedTagsRecursive( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, XmlNode> oTagDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert( !String.IsNullOrEmpty(sTag) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert( !String.IsNullOrEmpty(sApiKey) ); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oTagDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* Here is what this method should do, based on the eNetworkLevel and iRecursionLevel parameters. eNetworkLevel |One | OnePointFive | Two ---|------------------| ------------------| ----------------- i 1 |Add all vertices. | Add all vertices. | Add all vertices. R | | | e |Add all edges. | Add all edges. | Add all edges. c | | | u |Do not recurse. | Recurse. | Recurse. r | | | s ---|------------------|-------------------|------------------ i 2 |Impossible. | Do not add | Add all vertices. o | | vertices. | n | | | L | | Add edges only if | Add all edges. e | | vertices are | v | | already included. | e | | | l | | Do not recurse. | Do not recurse. | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); ReportProgress("Getting tags related to \"" + sTag + "\"."); String sUrl = GetFlickrMethodUrl( "flickr.tags.getRelated", sApiKey, "&tag=" + UrlUtil.EncodeUrlParameter(sTag) ); XmlDocument oXmlDocument; try { oXmlDocument = GetXmlDocument(sUrl, oRequestStatistics); } catch (Exception oException) { // If the exception is not a WebException or XmlException, or if // none of the network has been obtained yet, throw the exception. if (!ExceptionIsWebOrXml(oException) || !oGraphMLXmlDocument.HasVertexXmlNode) { throw oException; } return; } // The document consists of a single "tags" node with zero or more // "tag" child nodes. String sOtherTag = null; XmlNodeList oTagNodes = oXmlDocument.DocumentElement.SelectNodes( "tags/tag"); if (oTagNodes.Count > 0) { AppendVertexXmlNode(sTag, oGraphMLXmlDocument, oTagDictionary); } foreach (XmlNode oTagNode in oTagNodes) { sOtherTag = XmlUtil2.SelectRequiredSingleNodeAsString(oTagNode, "text()", null); if (bNeedToAppendVertices) { AppendVertexXmlNode(sOtherTag, oGraphMLXmlDocument, oTagDictionary); } if ( bNeedToAppendVertices || oTagDictionary.ContainsKey(sOtherTag) ) { oGraphMLXmlDocument.AppendEdgeXmlNode(sTag, sOtherTag); } } if (bNeedToRecurse) { foreach (XmlNode oTagNode in oTagNodes) { sOtherTag = XmlUtil2.SelectRequiredSingleNodeAsString(oTagNode, "text()", null); GetRelatedTagsRecursive(sOtherTag, eWhatToInclude, eNetworkLevel, sApiKey, 2, oGraphMLXmlDocument, oTagDictionary, oRequestStatistics); } } }
//************************************************************************* // Method: GetNetworkAsync() // /// <summary> /// Asynchronously gets an undirected network of Flickr tags related to a /// specified tag. /// </summary> /// /// <param name="tag"> /// Tag to get related tags for. /// </param> /// /// <param name="whatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="networkLevel"> /// Network level to include. /// </param> /// /// <param name="apiKey"> /// Flickr API key. /// </param> /// /// <remarks> /// When the analysis completes, the <see /// cref="HttpNetworkAnalyzerBase.AnalysisCompleted" /> event fires. The /// <see cref="RunWorkerCompletedEventArgs.Result" /> property will return /// an XmlDocument containing the network as GraphML. /// /// <para> /// To cancel the analysis, call <see /// cref="HttpNetworkAnalyzerBase.CancelAsync" />. /// </para> /// /// </remarks> //************************************************************************* public void GetNetworkAsync( String tag, WhatToInclude whatToInclude, NetworkLevel networkLevel, String apiKey ) { Debug.Assert( !String.IsNullOrEmpty(tag) ); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert( !String.IsNullOrEmpty(apiKey) ); AssertValid(); const String MethodName = "GetNetworkAsync"; CheckIsBusy(MethodName); // Wrap the arguments in an object that can be passed to // BackgroundWorker.RunWorkerAsync(). GetNetworkAsyncArgs oGetNetworkAsyncArgs = new GetNetworkAsyncArgs(); oGetNetworkAsyncArgs.Tag = tag; oGetNetworkAsyncArgs.NetworkLevel = networkLevel; oGetNetworkAsyncArgs.WhatToInclude = whatToInclude; oGetNetworkAsyncArgs.ApiKey = apiKey; m_oBackgroundWorker.RunWorkerAsync(oGetNetworkAsyncArgs); }
GetNetworkDescription ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel ) { Debug.Assert( !String.IsNullOrEmpty(sTag) ); AssertValid(); NetworkDescriber oNetworkDescriber = new NetworkDescriber(); oNetworkDescriber.AddSentence( "The graph represents the {0} network of Flickr tags related to" + " the tag \"{1}\"." , NetworkLevelToString(eNetworkLevel), sTag ); oNetworkDescriber.AddNetworkTime(NetworkSource); return ( oNetworkDescriber.ConcatenateSentences() ); }
//************************************************************************* // Method: GetRelatedTagsInternal() // /// <summary> /// Gets the Flickr tags related to a specified tag, given a /// GraphXMLXmlDocument. /// </summary> /// /// <param name="sTag"> /// Tag to get related tags for. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="sApiKey"> /// Flickr API key. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// The GraphMLXmlDocument to populate with the requested network. /// </param> //************************************************************************* protected void GetRelatedTagsInternal( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sTag) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert( !String.IsNullOrEmpty(sApiKey) ); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the tag name and the value is the corresponding GraphML // XML node that represents the tag. This is used to prevent the same // tag from being added to the XmlDocument twice. Dictionary<String, XmlNode> oTagDictionary = new Dictionary<String, XmlNode>(); GetRelatedTagsRecursive(sTag, eWhatToInclude, eNetworkLevel, sApiKey, 1, oGraphMLXmlDocument, oTagDictionary, oRequestStatistics); if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SampleThumbnails) ) { AppendSampleThumbnails(oTagDictionary, oGraphMLXmlDocument, sApiKey, oRequestStatistics); } }
GetUserNetworkInternal ( String sScreenName, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest, String sApiKey ) { Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPerRequest > 0); Debug.Assert( !String.IsNullOrEmpty(sApiKey) ); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.CommenterVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.UserInformation) ); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetUserNetworkInternal(sScreenName, eWhatToInclude, eNetworkLevel, iMaximumPerRequest, sApiKey, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnUnexpectedException(oException, oGraphMLXmlDocument, oRequestStatistics); } OnNetworkObtained(oGraphMLXmlDocument, oRequestStatistics, GetNetworkDescription(sScreenName, eWhatToInclude, eNetworkLevel, iMaximumPerRequest), "Flickr User " + sScreenName ); return (oGraphMLXmlDocument); }
//************************************************************************* // Method: DoDataExchange() // /// <summary> /// Transfers data between the dialog's fields and its controls. /// </summary> /// /// <param name="bFromControls"> /// true to transfer data from the dialog's controls to its fields, false /// for the other direction. /// </param> /// /// <returns> /// true if the transfer was successful. /// </returns> //************************************************************************* protected override Boolean DoDataExchange( Boolean bFromControls ) { if (bFromControls) { // Validate the controls. String sTag; if ( !ValidateRequiredTextBox(txbTag, "Enter a Flickr tag.", out sTag) || !usrFlickrApiKey.Validate() ) { return (false); } m_sTag = sTag; m_eNetworkLevel = usrNetworkLevel.Level; m_bIncludeSampleThumbnails = chkIncludeSampleThumbnails.Checked; m_sApiKey = usrFlickrApiKey.ApiKey; } else { txbTag.Text = m_sTag; usrNetworkLevel.Level = m_eNetworkLevel; chkIncludeSampleThumbnails.Checked = m_bIncludeSampleThumbnails; usrFlickrApiKey.ApiKey = m_sApiKey; EnableControls(); } return (true); }
GetNetworkDescription ( String sUserNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert( !String.IsNullOrEmpty(sUserNameToAnalyze) ); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); NetworkDescriber oNetworkDescriber = new NetworkDescriber(); oNetworkDescriber.AddSentence( "The graph represents the {0} YouTube network of the user with the" + " username \"{1}\"." , NetworkLevelToString(eNetworkLevel), sUserNameToAnalyze ); oNetworkDescriber.AddNetworkTime(NetworkSource); oNetworkDescriber.StartNewParagraph(); if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FriendVertices) ) { oNetworkDescriber.AddSentence( "There is a vertex for each friend of the user." ); } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SubscriptionVertices) ) { oNetworkDescriber.AddSentence( "There is a vertex for each person or channel subscribed to by" + " the user." ); } oNetworkDescriber.AddNetworkLimit(iMaximumPeoplePerRequest, "people"); return ( oNetworkDescriber.ConcatenateSentences() ); }
GetUserNetworkRecursive ( String sUserID, String sScreenName, WhatToInclude eWhatToInclude, Boolean bIncludeContactsThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest, String sApiKey, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary <String, XmlNode> oUserIDDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sUserID)); Debug.Assert(!String.IsNullOrEmpty(sScreenName)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPerRequest > 0); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* * Here is what this method should do, based on the eNetworkLevel and * iRecursionLevel parameters. * * eNetworkLevel * |One | OnePointFive | Two * ---|------------------| ------------------| ----------------- * i 1 |Add all vertices. | Add all vertices. | Add all vertices. * R | | | * e |Add all edges. | Add all edges. | Add all edges. * c | | | * u |Do not recurse. | Recurse. | Recurse. * r | | | * s ---|------------------|-------------------|------------------ * i 2 |Impossible. | Do not add | Add all vertices. * o | | vertices. | * n | | | * L | | Add edges only if | Add all edges. * e | | vertices are | * v | | already included. | * e | | | * l | | Do not recurse. | Do not recurse. | | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); Boolean bNeedToAppendVertices = GetNeedToAppendVertices(eNetworkLevel, iRecursionLevel); List <String> oUserIDsToRecurse = new List <String>(); ReportProgressForContactsOrCommenters(sScreenName, bIncludeContactsThisCall); Boolean bThisUserAppended = false; foreach (XmlNode oChildXmlNode in GetContactsOrCommentersEnumerator( sUserID, bIncludeContactsThisCall, iMaximumPerRequest, oGraphMLXmlDocument, sApiKey, oRequestStatistics)) { String sOtherScreenName, sOtherUserID; if ( !XmlUtil2.TrySelectSingleNodeAsString(oChildXmlNode, bIncludeContactsThisCall ? "@username" : "@authorname", null, out sOtherScreenName) || !XmlUtil2.TrySelectSingleNodeAsString(oChildXmlNode, bIncludeContactsThisCall ? "@nsid" : "@author", null, out sOtherUserID) ) { continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a YouTube error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sUserID, sScreenName, oGraphMLXmlDocument, oUserIDDictionary); bThisUserAppended = true; } if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherUserID, sOtherScreenName, oGraphMLXmlDocument, oUserIDDictionary) && bNeedToRecurse ) { oUserIDsToRecurse.Add(sOtherUserID); } } if (bNeedToAppendVertices || oUserIDDictionary.ContainsKey(sOtherUserID)) { // Append an edge node and optional attributes. XmlNode oEdgeXmlNode; if (bIncludeContactsThisCall) { oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument, sScreenName, sOtherScreenName, "Contact"); } else { // (Note the swapping of screen names in the commenter // case.) oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument, sOtherScreenName, sScreenName, "Commenter"); UInt32 uCommentDateUtc; if (XmlUtil2.TrySelectSingleNodeAsUInt32(oChildXmlNode, "@datecreate", null, out uCommentDateUtc)) { DateTime oCommentDateUtc = DateTimeUtil2.UnixTimestampToDateTimeUtc( uCommentDateUtc); oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeXmlNode, CommentDateUtcID, ExcelDateTimeUtil.DateTimeToStringLocale1033( oCommentDateUtc, ExcelColumnFormat.DateAndTime) ); } AppendStringGraphMLAttributeValue(oChildXmlNode, "@permalink", null, oGraphMLXmlDocument, oEdgeXmlNode, CommentUrlID); } } } if (bNeedToRecurse) { foreach (String sUserIDToRecurse in oUserIDsToRecurse) { XmlNode oVertexXmlNode = oUserIDDictionary[sUserIDToRecurse]; String sScreenNameToRecurse = GetScreenNameFromVertexXmlNode( oVertexXmlNode); GetUserNetworkRecursive(sUserIDToRecurse, sScreenNameToRecurse, eWhatToInclude, bIncludeContactsThisCall, eNetworkLevel, iMaximumPerRequest, sApiKey, 2, oGraphMLXmlDocument, oUserIDDictionary, oRequestStatistics); } } }
//************************************************************************* // Method: GetNetworkAsync() // /// <summary> /// Asynchronously gets a directed network of YouTube users. /// </summary> /// /// <param name="userNameToAnalyze"> /// The user name of the YouTube user whose network should be analyzed. /// </param> /// /// <param name="whatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="networkLevel"> /// Network level to include. /// </param> /// /// <param name="maximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <remarks> /// When the analysis completes, the <see /// cref="HttpNetworkAnalyzerBase.AnalysisCompleted" /> event fires. The /// <see cref="RunWorkerCompletedEventArgs.Result" /> property will return /// an XmlDocument containing the network as GraphML. /// /// <para> /// To cancel the analysis, call <see /// cref="HttpNetworkAnalyzerBase.CancelAsync" />. /// </para> /// /// </remarks> //************************************************************************* public void GetNetworkAsync( String userNameToAnalyze, WhatToInclude whatToInclude, NetworkLevel networkLevel, Int32 maximumPeoplePerRequest ) { Debug.Assert( !String.IsNullOrEmpty(userNameToAnalyze) ); Debug.Assert(networkLevel == NetworkLevel.One || networkLevel == NetworkLevel.OnePointFive || networkLevel == NetworkLevel.Two); Debug.Assert(maximumPeoplePerRequest > 0); AssertValid(); const String MethodName = "GetNetworkAsync"; CheckIsBusy(MethodName); // Wrap the arguments in an object that can be passed to // BackgroundWorker.RunWorkerAsync(). GetNetworkAsyncArgs oGetNetworkAsyncArgs = new GetNetworkAsyncArgs(); oGetNetworkAsyncArgs.UserNameToAnalyze = userNameToAnalyze; oGetNetworkAsyncArgs.WhatToInclude = whatToInclude; oGetNetworkAsyncArgs.NetworkLevel = networkLevel; oGetNetworkAsyncArgs.MaximumPeoplePerRequest = maximumPeoplePerRequest; m_oBackgroundWorker.RunWorkerAsync(oGetNetworkAsyncArgs); }
//************************************************************************* // Method: DoDataExchange() // /// <summary> /// Transfers data between the dialog's fields and its controls. /// </summary> /// /// <param name="bFromControls"> /// true to transfer data from the dialog's controls to its fields, false /// for the other direction. /// </param> /// /// <returns> /// true if the transfer was successful. /// </returns> //************************************************************************* protected override Boolean DoDataExchange( Boolean bFromControls ) { if (bFromControls) { // Validate the controls. if ( !ValidateUserNameTextBox(txbUserName, out m_sUserName) ) { return (false); } m_bIncludeFriendVertices = m_bIncludeSubscriptionVertices = false; if (radIncludeFriendVertices.Checked) { m_bIncludeFriendVertices = true; } else if (radIncludeSubscriptionVertices.Checked) { m_bIncludeSubscriptionVertices = true; } else { m_bIncludeFriendVertices = m_bIncludeSubscriptionVertices = true; } m_eNetworkLevel = usrNetworkLevel.Level; m_bIncludeAllStatistics = chkIncludeAllStatistics.Checked; m_iMaximumPeoplePerRequest = usrLimitToN.N; } else { txbUserName.Text = m_sUserName; if (m_bIncludeFriendVertices) { if (m_bIncludeSubscriptionVertices) { radIncludeFollowedAndFollower.Checked = true; } else { radIncludeFriendVertices.Checked = true; } } else { radIncludeSubscriptionVertices.Checked = true; } usrNetworkLevel.Level = m_eNetworkLevel; chkIncludeAllStatistics.Checked = m_bIncludeAllStatistics; usrLimitToN.N = m_iMaximumPeoplePerRequest; EnableControls(); } return (true); }
//************************************************************************* // Method: GetUserNetworkInternal() // /// <overloads> /// Gets a network of YouTube users. /// </overloads> /// /// <summary> /// Gets a network of YouTube users. /// </summary> /// /// <param name="sUserNameToAnalyze"> /// The user name of the YouTube user whose network should be analyzed. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iMaximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <returns> /// An XmlDocument containing the network as GraphML. /// </returns> //************************************************************************* protected XmlDocument GetUserNetworkInternal( String sUserNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest ) { Debug.Assert( !String.IsNullOrEmpty(sUserNameToAnalyze) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); AssertValid(); GraphMLXmlDocument oGraphMLXmlDocument = CreateGraphMLXmlDocument( WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.AllStatistics) ); RequestStatistics oRequestStatistics = new RequestStatistics(); try { GetUserNetworkInternal(sUserNameToAnalyze, eWhatToInclude, eNetworkLevel, iMaximumPeoplePerRequest, oRequestStatistics, oGraphMLXmlDocument); } catch (Exception oException) { OnTerminatingException(oException); } OnNetworkObtainedWithoutTerminatingException(oGraphMLXmlDocument, oRequestStatistics); return (oGraphMLXmlDocument); }
GetUserNetworkRecursive ( String sScreenName, WhatToInclude eWhatToInclude, Boolean bIncludeFollowedThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary <String, TwitterVertex> oScreenNameDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sScreenName)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oScreenNameDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* * Here is what this method should do, based on the eNetworkLevel and * iRecursionLevel parameters. It's assumed that * eWhatToInclude.FollowedFollowerEdge is set. * * eNetworkLevel * |One | OnePointFive | Two * ---|------------------| ------------------| ----------------- * i 1 |Add all vertices. | Add all vertices. | Add all vertices. * R | | | * e |Add all edges. | Add all edges. | Add all edges. * c | | | * u |Do not recurse. | Recurse. | Recurse. * r | | | * s ---|------------------|-------------------|------------------ * i 2 |Impossible. | Do not add | Add all vertices. * o | | vertices. | * n | | | * L | | Add edges only if | Add all edges. * e | | vertices are | * v | | already included. | * e | | | * l | | Do not recurse. | Do not recurse. | | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); List <String> oScreenNamesToRecurse = new List <String>(); Boolean bIncludeLatestStatuses = WhatToIncludeFlagIsSet( eWhatToInclude, WhatToInclude.LatestStatuses); ReportProgressForFollowedOrFollowing(sScreenName, bIncludeFollowedThisCall); Boolean bThisUserAppended = false; // If the GraphMLXmlDocument already contains at least one vertex node, // then this is the second time that this method has been called, a // partial network has already been obtained, and most errors should // now be skipped. However, if none of the network has been obtained // yet, errors on page 1 should throw an immediate exception. Boolean bSkipMostPage1Errors = oGraphMLXmlDocument.HasVertexXmlNode; // The document consists of a single "users" node with zero or more // "user" child nodes. foreach (XmlNode oUserXmlNode in EnumerateXmlNodes( GetFollowedOrFollowingUrl(sScreenName, bIncludeFollowedThisCall), "users_list/users/user", null, null, Int32.MaxValue, iMaximumPeoplePerRequest, false, bSkipMostPage1Errors, oRequestStatistics)) { String sOtherScreenName; if (!TryGetScreenName(oUserXmlNode, out sOtherScreenName)) { // Nothing can be done without a screen name. continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a Twitter error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sScreenName, null, oGraphMLXmlDocument, oScreenNameDictionary, true, bIncludeLatestStatuses); bThisUserAppended = true; } Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherScreenName, oUserXmlNode, oGraphMLXmlDocument, oScreenNameDictionary, true, bIncludeLatestStatuses) && bNeedToRecurse ) { oScreenNamesToRecurse.Add(sOtherScreenName); } } if (WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedFollowerEdges)) { if (bNeedToAppendVertices || oScreenNameDictionary.ContainsKey(sOtherScreenName)) { XmlNode oEdgeXmlNode; if (bIncludeFollowedThisCall) { oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument, sScreenName, sOtherScreenName, "Followed"); } else { oEdgeXmlNode = AppendEdgeXmlNode(oGraphMLXmlDocument, sOtherScreenName, sScreenName, "Follower"); } AppendRelationshipDateUtcGraphMLAttributeValue( oGraphMLXmlDocument, oEdgeXmlNode, oRequestStatistics); } } } if (bNeedToRecurse) { foreach (String sScreenNameToRecurse in oScreenNamesToRecurse) { GetUserNetworkRecursive(sScreenNameToRecurse, eWhatToInclude, bIncludeFollowedThisCall, eNetworkLevel, iMaximumPeoplePerRequest, 2, oGraphMLXmlDocument, oScreenNameDictionary, oRequestStatistics); } } }
//************************************************************************* // Method: GetUserNetworkInternal() // /// <summary> /// Gets a network of YouTube users, given a GraphMLXmlDocument. /// </summary> /// /// <param name="sUserNameToAnalyze"> /// The user name of the YouTube user whose network should be analyzed. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iMaximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// The GraphMLXmlDocument to populate with the requested network. /// </param> //************************************************************************* protected void GetUserNetworkInternal( String sUserNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert( !String.IsNullOrEmpty(sUserNameToAnalyze) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the user name and the value is the corresponding GraphML // XML node that represents the user. This is used to prevent the same // user name from being added to the XmlDocument twice. Dictionary<String, XmlNode> oUserNameDictionary = new Dictionary<String, XmlNode>(); // Include friends, subscriptions, both, or neither. Boolean [] abIncludes = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FriendVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.SubscriptionVertices), }; for (Int32 i = 0; i < 2; i++) { if ( abIncludes[i] ) { GetUserNetworkRecursive(sUserNameToAnalyze, eWhatToInclude, (i == 0), eNetworkLevel, iMaximumPeoplePerRequest, 1, oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } } if ( WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.AllStatistics) ) { AppendAllStatisticGraphMLAttributeValues(oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } }
GetUserNetworkInternal ( String sScreenNameToAnalyze, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(!String.IsNullOrEmpty(sScreenNameToAnalyze)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); // The key is the screen name and the value is the corresponding // TwitterVertex. This is used to prevent the same screen name from // being added to the XmlDocument twice. Dictionary <String, TwitterVertex> oScreenNameDictionary = new Dictionary <String, TwitterVertex>(); // Include followed, followers, both, or neither. Boolean [] abIncludes = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowedVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.FollowerVertices), }; for (Int32 i = 0; i < 2; i++) { if (abIncludes[i]) { GetUserNetworkRecursive(sScreenNameToAnalyze, eWhatToInclude, (i == 0), eNetworkLevel, iMaximumPeoplePerRequest, 1, oGraphMLXmlDocument, oScreenNameDictionary, oRequestStatistics); } } Boolean bIncludeLatestStatus = WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.LatestStatuses); AppendMissingGraphMLAttributeValues(oGraphMLXmlDocument, oScreenNameDictionary, true, bIncludeLatestStatus, oRequestStatistics); AppendRepliesToAndMentionsXmlNodes(oGraphMLXmlDocument, oScreenNameDictionary, WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.RepliesToEdges), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.MentionsEdges) ); }
//************************************************************************* // Method: GetUserNetworkRecursive() // /// <summary> /// Recursively gets a network of YouTube users. /// </summary> /// /// <param name="sUserName"> /// The user name to use in this call. /// </param> /// /// <param name="eWhatToInclude"> /// Specifies what should be included in the network. /// </param> /// /// <param name="bIncludeFriendsThisCall"> /// true to include the user's friends, false to include the people /// subscribed to by the user. /// </param> /// /// <param name="eNetworkLevel"> /// Network level to include. Must be NetworkLevel.One, OnePointFive, or /// Two. /// </param> /// /// <param name="iMaximumPeoplePerRequest"> /// Maximum number of people to request for each query, or Int32.MaxValue /// for no limit. /// </param> /// /// <param name="iRecursionLevel"> /// Recursion level for this call. Must be 1 or 2. Gets incremented when /// recursing. /// </param> /// /// <param name="oGraphMLXmlDocument"> /// GraphMLXmlDocument being populated. /// </param> /// /// <param name="oUserNameDictionary"> /// The key is the user name and the value is the corresponding GraphML XML /// node that represents the user. /// </param> /// /// <param name="oRequestStatistics"> /// A <see cref="RequestStatistics" /> object that is keeping track of /// requests made while getting the network. /// </param> //************************************************************************* protected void GetUserNetworkRecursive( String sUserName, WhatToInclude eWhatToInclude, Boolean bIncludeFriendsThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPeoplePerRequest, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, XmlNode> oUserNameDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert( !String.IsNullOrEmpty(sUserName) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPeoplePerRequest > 0); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserNameDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* Here is what this method should do, based on the eNetworkLevel and iRecursionLevel parameters. eNetworkLevel |One | OnePointFive | Two ---|------------------| ------------------| ----------------- i 1 |Add all vertices. | Add all vertices. | Add all vertices. R | | | e |Add all edges. | Add all edges. | Add all edges. c | | | u |Do not recurse. | Recurse. | Recurse. r | | | s ---|------------------|-------------------|------------------ i 2 |Impossible. | Do not add | Add all vertices. o | | vertices. | n | | | L | | Add edges only if | Add all edges. e | | vertices are | v | | already included. | e | | | l | | Do not recurse. | Do not recurse. | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); List<String> oUserNamesToRecurse = new List<String>(); ReportProgressForFriendsOrSubscriptions(sUserName, bIncludeFriendsThisCall); Boolean bThisUserAppended = false; // If the GraphMLXmlDocument already contains at least one vertex node, // then this is the second time that this method has been called, a // partial network has already been obtained, and most errors should // now be skipped. However, if none of the network has been obtained // yet, errors on page 1 should throw an immediate exception. Boolean bSkipMostPage1Errors = oGraphMLXmlDocument.HasVertexXmlNode; // The document consists of a single "feed" node with zero or more // "entry" child nodes. foreach ( XmlNode oEntryXmlNode in EnumerateXmlNodes( GetFriendsOrSubscriptionsUrl(sUserName, bIncludeFriendsThisCall), "a:feed/a:entry", iMaximumPeoplePerRequest, bSkipMostPage1Errors, oRequestStatistics) ) { XmlNamespaceManager oXmlNamespaceManager = CreateXmlNamespaceManager(oEntryXmlNode.OwnerDocument); String sOtherUserName; if ( !XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "yt:username/text()", oXmlNamespaceManager, out sOtherUserName) ) { continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a YouTube error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sUserName, null, oGraphMLXmlDocument, oUserNameDictionary); bThisUserAppended = true; } Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherUserName, oEntryXmlNode, oGraphMLXmlDocument, oUserNameDictionary) && bNeedToRecurse ) { oUserNamesToRecurse.Add(sOtherUserName); } } if ( bNeedToAppendVertices || oUserNameDictionary.ContainsKey(sOtherUserName) ) { String sRelationship; if (bIncludeFriendsThisCall) { sRelationship = "Friend of"; } else { sRelationship = "Subscribes to"; String sSubscriptionType = null; if ( XmlUtil2.TrySelectSingleNodeAsString(oEntryXmlNode, "a:category[@scheme='http://gdata.youtube.com/schemas/" + "2007/subscriptiontypes.cat']/@term", oXmlNamespaceManager, out sSubscriptionType) ) { sRelationship += " " + sSubscriptionType; } } AppendEdgeXmlNode(oGraphMLXmlDocument, sUserName, sOtherUserName, sRelationship); } } if (bNeedToRecurse) { foreach (String sUserNameToRecurse in oUserNamesToRecurse) { GetUserNetworkRecursive(sUserNameToRecurse, eWhatToInclude, bIncludeFriendsThisCall, eNetworkLevel, iMaximumPeoplePerRequest, 2, oGraphMLXmlDocument, oUserNameDictionary, oRequestStatistics); } } }
GetUserNetworkInternal ( String sScreenName, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest, String sApiKey, RequestStatistics oRequestStatistics, GraphMLXmlDocument oGraphMLXmlDocument ) { Debug.Assert(!String.IsNullOrEmpty(sScreenName)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPerRequest > 0); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); Debug.Assert(oRequestStatistics != null); Debug.Assert(oGraphMLXmlDocument != null); AssertValid(); String sUserID; // Get the user's ID and the correct case of the screen name. FlickrScreenNameToUserID(sScreenName, sApiKey, oRequestStatistics, out sUserID, out sScreenName); // The key is the user ID name and the value is the corresponding // GraphML XML node that represents the user. This is used to prevent // the same user ID from being added to the XmlDocument twice. Dictionary <String, XmlNode> oUserIDDictionary = new Dictionary <String, XmlNode>(); // Include contacts, commenters, both, or neither. Boolean [] abIncludes = new Boolean[] { WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.ContactVertices), WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.CommenterVertices), }; for (Int32 i = 0; i < 2; i++) { if (abIncludes[i]) { GetUserNetworkRecursive(sUserID, sScreenName, eWhatToInclude, (i == 0), eNetworkLevel, iMaximumPerRequest, sApiKey, 1, oGraphMLXmlDocument, oUserIDDictionary, oRequestStatistics); } } if (WhatToIncludeFlagIsSet(eWhatToInclude, WhatToInclude.UserInformation)) { AppendUserInformationGraphMLAttributeValues(oGraphMLXmlDocument, oUserIDDictionary, sApiKey, oRequestStatistics); } }
GetUserNetworkRecursive ( String sUserID, String sScreenName, WhatToInclude eWhatToInclude, Boolean bIncludeContactsThisCall, NetworkLevel eNetworkLevel, Int32 iMaximumPerRequest, String sApiKey, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary<String, XmlNode> oUserIDDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert( !String.IsNullOrEmpty(sUserID) ); Debug.Assert( !String.IsNullOrEmpty(sScreenName) ); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(iMaximumPerRequest > 0); Debug.Assert( !String.IsNullOrEmpty(sApiKey) ); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oUserIDDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* Here is what this method should do, based on the eNetworkLevel and iRecursionLevel parameters. eNetworkLevel |One | OnePointFive | Two ---|------------------| ------------------| ----------------- i 1 |Add all vertices. | Add all vertices. | Add all vertices. R | | | e |Add all edges. | Add all edges. | Add all edges. c | | | u |Do not recurse. | Recurse. | Recurse. r | | | s ---|------------------|-------------------|------------------ i 2 |Impossible. | Do not add | Add all vertices. o | | vertices. | n | | | L | | Add edges only if | Add all edges. e | | vertices are | v | | already included. | e | | | l | | Do not recurse. | Do not recurse. | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); Boolean bNeedToAppendVertices = GetNeedToAppendVertices(eNetworkLevel, iRecursionLevel); List<String> oUserIDsToRecurse = new List<String>(); ReportProgressForContactsOrCommenters(sScreenName, bIncludeContactsThisCall); Boolean bThisUserAppended = false; foreach ( XmlNode oChildXmlNode in GetContactsOrCommentersEnumerator( sUserID, bIncludeContactsThisCall, iMaximumPerRequest, oGraphMLXmlDocument, sApiKey, oRequestStatistics) ) { String sOtherScreenName, sOtherUserID; if ( !XmlUtil2.TrySelectSingleNodeAsString(oChildXmlNode, bIncludeContactsThisCall ? "@username" : "@authorname", null, out sOtherScreenName) || !XmlUtil2.TrySelectSingleNodeAsString(oChildXmlNode, bIncludeContactsThisCall ? "@nsid" : "@author", null, out sOtherUserID) ) { continue; } if (!bThisUserAppended) { // Append a vertex node for this request's user. // // This used to be done after the foreach loop, which avoided // the need for a "bThisUserAppended" flag. That caused the // following bug: If a YouTube error occurred within // EnumerateXmlNodes() after some edges had been added, and the // user decided to import the resulting partial network, the // GraphML might contain edges that referenced "this user" // without containing a vertex for "this user." That is an // illegal state for GraphML, which the ExcelTemplate project // caught and reported as an error. TryAppendVertexXmlNode(sUserID, sScreenName, oGraphMLXmlDocument, oUserIDDictionary); bThisUserAppended = true; } if (bNeedToAppendVertices) { if ( TryAppendVertexXmlNode(sOtherUserID, sOtherScreenName, oGraphMLXmlDocument, oUserIDDictionary) && bNeedToRecurse ) { oUserIDsToRecurse.Add(sOtherUserID); } } if ( bNeedToAppendVertices || oUserIDDictionary.ContainsKey(sOtherUserID) ) { // Append an edge node and optional attributes. XmlNode oEdgeXmlNode; if (bIncludeContactsThisCall) { oEdgeXmlNode = NodeXLGraphMLUtil.AppendEdgeXmlNode( oGraphMLXmlDocument, sScreenName, sOtherScreenName, "Contact"); } else { // (Note the swapping of screen names in the commenter // case.) oEdgeXmlNode = NodeXLGraphMLUtil.AppendEdgeXmlNode( oGraphMLXmlDocument, sOtherScreenName, sScreenName, "Commenter"); UInt32 uCommentDateUtc; if ( XmlUtil2.TrySelectSingleNodeAsUInt32(oChildXmlNode, "@datecreate", null, out uCommentDateUtc) ) { DateTime oCommentDateUtc = DateTimeUtil2.UnixTimestampToDateTimeUtc( uCommentDateUtc); oGraphMLXmlDocument.AppendGraphMLAttributeValue( oEdgeXmlNode, CommentDateUtcID, ExcelDateTimeUtil.DateTimeToStringLocale1033( oCommentDateUtc, ExcelColumnFormat.DateAndTime) ); } AppendStringGraphMLAttributeValue(oChildXmlNode, "@permalink", null, oGraphMLXmlDocument, oEdgeXmlNode, CommentUrlID); } } } if (bNeedToRecurse) { foreach (String sUserIDToRecurse in oUserIDsToRecurse) { XmlNode oVertexXmlNode = oUserIDDictionary[sUserIDToRecurse]; String sScreenNameToRecurse = GetScreenNameFromVertexXmlNode( oVertexXmlNode); GetUserNetworkRecursive(sUserIDToRecurse, sScreenNameToRecurse, eWhatToInclude, bIncludeContactsThisCall, eNetworkLevel, iMaximumPerRequest, sApiKey, 2, oGraphMLXmlDocument, oUserIDDictionary, oRequestStatistics); } } }