Inspiration

As users of the Twitter platform, we were very interested in the way that different communities form and interact. When users cluster into these communities, content is shared between them naturally through different transmissions. Thus, visualizing this information and ultimately seeing how posts are transmitted and spread throughout the network could lead to more information on how to prevent abuse of the system and ways to prevent targeted harassment campaigns.

What It Does

The IoF allows users to have an innovative VR experience which allows them to delve through the wide-reaching space of Twitter networks. Users will be able to walk firsthand through the follower network and see as clusters form as different users follow each other.

How We Built It

  • Concurrently worked on two parts of the code via a visualization building team and a data collection team
  • Leveraged Git to merge code from the two teams
  • Utilized Tweepy (Twitter API) to gather data from Twitter and write it to a JSON file
  • Used Unity to develop the visualization code

Challenges We Ran Into

  • First experience with Twitter API to collect the data
  • Ran out of API calls during testing
  • First experience with Oculus Rift equipment for VR applications
  • Oculus Rift does not work with laptops or any of the computers in the labs
  • Developing an algorithm for optimal node placement
  • Conveying the difference between following a user and being followed by a user

Accomplishments That We're Proud Of

  • Working together as a cohesive unit
  • Completing the project and all stretch goals
  • Developing an algorithm for the optimal node placement
// Calculate the force on each vertex
float c1 = 2f;
float c2 = 1f;
float c3 = 1f;
float c4 = 0.1f;

foreach (var elem in nodes)
{
    // Calculate the force on each node
    Vector3 force = Vector3.zero;

    foreach (var other in nodes)
    {
        if (!elem.Key.Equals(other.Key))
        {
            if (connections.ContainsKey(new Pair<string, string>(elem.Key, other.Key)) || connections.ContainsKey(new Pair<string, string>(other.Key, elem.Key)))
            {
                force += (other.Value.model.transform.position - elem.Value.model.transform.position).normalized * c1 * Mathf.Log10(Vector3.Distance(elem.Value.model.transform.position, other.Value.model.transform.position) / c2);
            }
            else
            {
                force -= (other.Value.model.transform.position - elem.Value.model.transform.position).normalized * c3 / (elem.Value.model.transform.position - other.Value.model.transform.position).sqrMagnitude;
            }
        }
    }

    // move the vertex c4 * (force on vertex)
    force *= c4;
    elem.Value.model.transform.position += force;
}

// Fix edges
foreach (var edge in connections)
{
    edge.Value.GetComponent<LineRenderer>().SetPositions(new Vector3[] { nodes[edge.Key.First].model.transform.position, nodes[edge.Key.Second].model.transform.position });
}

What We Learned

  • How to effectively work with new team members of different skill levels in a collaborative environment
  • Effective management of Twitter API
  • Several optimal node placement algorithms

What's Next For Internet of Followers (IoF)

  • Simulation of the posting of a tweet to see how it is transmitted throughout the network
  • Functionality of dragging user nodes to focus on different parts of the network
  • Selecting the user focus of the graph
  • Ability to hover over users on the graph to view more data

Built With

Share this project:
×

Updates

posted an update

There has been a temporary roadblock to the progress on the Twitter data collection, which we are working to overcome. Using Tweepy has made many things simpler, but getting used to the API has been something of a challenge.

The visualization side of things has seen much more progress. My prior experience with Unity has helped a lot with getting up and running quickly, and pair programming with Heather made a breeze out of implementing an algorithm for optimal placement of graph nodes:

// Calculate the force on each vertex
float c1 = 2f;
float c2 = 1f;
float c3 = 1f;
float c4 = 0.1f;

foreach (var elem in nodes)
{
    // Calculate the force on each node
    Vector3 force = Vector3.zero;

    foreach (var other in nodes)
    {
        if (!elem.Key.Equals(other.Key))
        {
            if (connections.ContainsKey(new Pair<string, string>(elem.Key, other.Key)) || connections.ContainsKey(new Pair<string, string>(other.Key, elem.Key)))
            {
                force += (other.Value.model.transform.position - elem.Value.model.transform.position).normalized * c1 * Mathf.Log10(Vector3.Distance(elem.Value.model.transform.position, other.Value.model.transform.position) / c2);
            }
            else
            {
                force -= (other.Value.model.transform.position - elem.Value.model.transform.position).normalized * c3 / (elem.Value.model.transform.position - other.Value.model.transform.position).sqrMagnitude;
            }
        }
    }

    // move the vertex c4 * (force on vertex)
    force *= c4;
    elem.Value.model.transform.position += force;
}

// Fix edges
foreach (var edge in connections)
{
    edge.Value.GetComponent<LineRenderer>().SetPositions(new Vector3[] { nodes[edge.Key.First].model.transform.position, nodes[edge.Key.Second].model.transform.position });
}

If we can get Twitter data collection running, we can let it run through the night and simply replace the dummy data we've been using with some real data tomorrow.

Log in or sign up for Devpost to join the conversation.