The FOMO Map: Session B Proposal

Siman Huang
6 min readNov 17, 2017

--

Team: Jingyuan Gao, Jujie Xu, Siman Huang

FOMO

/ˈfōmō/

noun

anxiety that an exciting or interesting event may currently be happening elsewhere, often aroused by posts seen on a social media website.

eg. “I realized I was a lifelong sufferer of FOMO!”

In order to help people relieve the Fear of Missing out (or make them even more miserable), we propose the FOMO Map that guides people to make choices between the events that are happening nearby.

Conceptual Diagram
Overview

The FOMO Map collects event data from “meetup.com”, including the types of the events, the titles, organizations, locations, starting time, ending time, and the popularity. Based on locations and google direction datas, the FOMO Map can also calculate how long it takes to transit from your location to the destined events.

The FOMO Map displays all the nearby events that are reachable by public transportations. Each dot indicates one event.

The circles visualize the transit time from your location to each destination; larger radius indicates longer transit time.

The curves along the dots indicates how popular an event is.

Each color represents one type of event, such as art, music, social, etc.

As the mouse touches each dot, the call-out window shows all the information of that one specific event, including categories, names, transit times, and amount of time left before it ends.

GSAPP 18:00

From an event’s start time to the end time, the dot would become more and more transparent until it disappears in the end. It helps users to visualize how much time left before they could catch an event.

GSAPP 18:00–24:00
GSAPP 20:30

As your location changes, the map visualizes different results

Time Square:

East Village:

import spatialpixel.mapping.slippymapper as slippymapper
import spatialpixel.google.directions as directions
import csv

def keyPressed():
global currenttime
if keyPressed:
currenttime += 0.5
#print currenttime

def mouseClicked():
global currenttime
if mouseClicked:
currenttime -= 0.5
#print currenttime

def setup():
size (1920,1920)
background(0)
translate(width/2, height/2)
fill(50, 50, 50)
textSize(580)
text('YOUR', -880, -280)
text('FOMO', -880, 220)
text('MAP', -620, 720)
noFill()
strokeWeight(4)
stroke(150, 150, 150)
ellipse(0, 0, 80, 80)
strokeWeight(4)
line(0, 40, 0, -40)
line(40, 0, -40, 0)
fill(190, 190, 190)
textSize(26)
text('N', -8, -50)
text('S', -8, 68)
text('W', -68, 10)
text('E', 48, 8)
textSize(30)
noStroke()
fill(255)
text('YOU', -30, 13)
textSize(34)
fill(255)
text('24:00', -940, -900)
text('gsapp', -940, -860)


global newyork
newyork = slippymapper.SlippyMapper(40.807993,-73.963833,12,'toner',width,height)

global locations
global latitudes
latitudes=[]
global longitudes
longitudes=[]
global starttimes
starttimes = []
global endtimes
endtimes = []
global kinds
kinds = []
global popularitys
popularitys = []

global names
names = []
locations=[latitudes, longitudes, names]
global currenttime


with open('FOMO_meetup_Dec_12th.csv') as f1:
reader = csv.reader(f1)
header = reader.next()

for row in reader:
latitude = float(row[4])
latitudes.append(latitude)
longitude = float(row[5])
longitudes.append(longitude)
name = str(row[1])
names.append(name)

starttime = float(row[8])
starttimes.append(starttime)
endtime = float(row[9])
endtimes.append(endtime)
kind = str(row[0])
kinds.append(kind)
popularity = int(row[11])
popularitys.append(popularity)

apikey= 'AIzaSyCvsKej4Vqzfi8zr9BHHWBkm6N57ZHTZNY '
centre = (40.758716, -73.984643)


currenttime = 18.0

number=len(longitudes)

global duration
duration = []
for i in xrange(number):
location_n=(locations[0][i],locations[1][i]) #(latitude[i], longitude[i])
location_n_route=directions.RenderGoogleDirections(apikey)
testjson=location_n_route.request(centre,location_n,'bus')
data=location_n_route.data
duration.append(data['routes'][0]['legs'][0]['duration']['value'])
#print(duration)

global info
info = {}
global relative_info
relative_info = {}
max_duration = max(duration)
print(max_duration)
for i in range(len(names)):
info[names[i]] = [locations[0][i], locations[1][i]]
relative_info[names[i]] = [locations[0][i] - centre[0], locations[1][i] - centre[1], 450*duration[i]/max_duration]
#print(relative_info)
textSize(30)
noStroke()
fill(255)
text('YOU', -30, 13)
fill(229, 163, 163)

global longi_point
longi_point = []
global latti_point
latti_point = []
global drift
drift=[]
global r
global stroke_weight
global thita
global drift
global indexColor
indexColor = {}

for i in xrange(len(names)):
if currenttime + duration[i]/3600 < endtime:
strokeWeight(2.5)
noFill()
indexColor = {'Arts': color(153, 204, 255), 'Films': color(255, 153, 153), 'Health & Wellness': color(255, 204, 102), 'Sports & Fitness': color(225, 0, 0), 'Hobbies & Crafts': color(0, 102, 0), 'Music': color(0, 153, 204), 'Photography': color(153, 102, 255)}
left_time_degree = (((endtimes[i]-currenttime)/(endtimes[i]-starttimes[i]))*255)
stroke(indexColor[kinds[i]], left_time_degree)
ellipse(0, 0, 4*relative_info[names[i]][2], 4*relative_info[names[i]][2])
# print(relative_info[location][0], relative_info[location][1])
distance = (relative_info[names[i]][0]**2 + relative_info[names[i]][1]**2) ** 0.5
# print(distance)
longi_point.append(relative_info[names[i]][0] / distance * relative_info[names[i]][2])
latti_point.append(relative_info[names[i]][1] / distance * relative_info[names[i]][2])

r = 2 * (longi_point[-1]**2 + latti_point[-1]**2) ** 0.5
thita = atan(- longi_point[-1] / latti_point[-1]) + PI
alp = 15.0 /180.0 * PI
drift = popularitys[i] /120
#print drift
drift_ratio = 0.1
x = [r * cos(thita - alp), (r-drift_ratio * drift) * cos(thita - 0.5*alp), (r-drift) * cos(thita - 0.15*alp), (r-drift) * cos(thita + 0.15*alp), (r-drift_ratio * drift) * cos(thita + 0.5*alp), r * cos(thita + alp)]
y = [r * sin(thita - alp), (r-drift_ratio * drift) * sin(thita - 0.5*alp), (r-drift) * sin(thita - 0.15*alp), (r-drift) * sin(thita + 0.15*alp), (r-drift_ratio * drift) * sin(thita + 0.5*alp), r * sin(thita + alp)]
beginShape()
curveVertex(x[0],y[0])
curveVertex(x[0],y[0])
curveVertex(x[1],y[1])
curveVertex(x[2],y[2])
curveVertex(x[3],y[3])
curveVertex(x[4],y[4])
curveVertex(x[5],y[5])
curveVertex(x[5],y[5])
endShape()
stroke_weight = 10.0
strokeWeight(stroke_weight)
#indexColor = {'Arts': color(153, 204, 255), 'Films': color(255, 153, 153), 'Health & Wellness': color(255, 204, 102), 'Sports & Fitness': color(230, 230, 0), 'Hobbies & Crafts': color(153, 255, 102), 'Music': color(0, 153, 204), 'Photography': color(204, 204, 255)}
left_time_degree = (((endtimes[i]-currenttime)/(endtimes[i]-starttimes[i]))*255)
#print left_time_degree
stroke(indexColor[kinds[i]], left_time_degree)
ellipse((r - (drift - stroke_weight/2)) * cos(thita), (r - (drift - stroke_weight/2)) * sin(thita), 10, 10)
# print(longi_point[-1], latti_point[-1])


def draw():
translate(width/2, height/2)
noStroke()
fill(0)
rect(-960, -960, 1920, 1920)
fill(50, 50, 50)
textSize(580)
text('YOUR', -880, -280)
text('FOMO', -880, 220)
text('MAP', -620, 720)
noFill()
strokeWeight(4)
stroke(150, 150, 150)
ellipse(0, 0, 80, 80)
strokeWeight(4)
line(0, 40, 0, -40)
line(40, 0, -40, 0)
fill(190, 190, 190)
textSize(26)
text('N', -8, -50)
text('S', -8, 68)
text('W', -68, 10)
text('E', 48, 8)
textSize(30)
noStroke()
fill(255)
text('YOU', -30, 13)
textSize(34)
fill(255)
strokeWeight(2.5)
noFill()
for i in xrange(len(names)):
if currenttime + duration[i]/3600 < endtimes:
strokeWeight(2.5)
noFill()
indexColor = {'Arts': color(153, 204, 255), 'Films': color(255, 153, 153), 'Health & Wellness': color(255, 204, 102), 'Sports & Fitness': color(225, 0, 0), 'Hobbies & Crafts': color(0, 102, 0), 'Music': color(0, 153, 204), 'Photography': color(153, 102, 255)}
left_time_degree = (((endtimes[i]-currenttime)/(endtimes[i]-starttimes[i]))*255)
stroke(indexColor[kinds[i]], left_time_degree)
ellipse(0, 0, 4*relative_info[names[i]][2], 4*relative_info[names[i]][2])
# print(relative_info[location][0], relative_info[location][1])
distance = (relative_info[names[i]][0]**2 + relative_info[names[i]][1]**2) ** 0.5
# print(distance)
longi_point.append(relative_info[names[i]][0] / distance * relative_info[names[i]][2])
latti_point.append(relative_info[names[i]][1] / distance * relative_info[names[i]][2])

r = 2 * (longi_point[-1]**2 + latti_point[-1]**2) ** 0.5
thita = atan(- longi_point[-1] / latti_point[-1]) + PI
alp = 15.0 /180.0 * PI
drift = popularitys[i] /120
#print drift
drift_ratio = 0.1
x = [r * cos(thita - alp), (r-drift_ratio * drift) * cos(thita - 0.5*alp), (r-drift) * cos(thita - 0.15*alp), (r-drift) * cos(thita + 0.15*alp), (r-drift_ratio * drift) * cos(thita + 0.5*alp), r * cos(thita + alp)]
y = [r * sin(thita - alp), (r-drift_ratio * drift) * sin(thita - 0.5*alp), (r-drift) * sin(thita - 0.15*alp), (r-drift) * sin(thita + 0.15*alp), (r-drift_ratio * drift) * sin(thita + 0.5*alp), r * sin(thita + alp)]
beginShape()
curveVertex(x[0],y[0])
curveVertex(x[0],y[0])
curveVertex(x[1],y[1])
curveVertex(x[2],y[2])
curveVertex(x[3],y[3])
curveVertex(x[4],y[4])
curveVertex(x[5],y[5])
curveVertex(x[5],y[5])
endShape()
stroke_weight = 10.0
strokeWeight(stroke_weight)
#indexColor = {'Arts': color(153, 204, 255), 'Films': color(255, 153, 153), 'Health & Wellness': color(255, 204, 102), 'Sports & Fitness': color(230, 230, 0), 'Hobbies & Crafts': color(153, 255, 102), 'Music': color(0, 153, 204), 'Photography': color(204, 204, 255)}
left_time_degree = (((endtimes[i]-currenttime)/(endtimes[i]-starttimes[i]))*255)
#print left_time_degree
stroke(indexColor[kinds[i]], left_time_degree)
ellipse((r - (drift - stroke_weight/2)) * cos(thita), (r - (drift - stroke_weight/2)) * sin(thita), 10, 10)
# print(longi_point[-1], latti_point[-1])
line(mouseX-width/2, mouseY-height/2, 0, 0)
for i in xrange(len(longi_point)):

r = 2 * (longi_point[-1]**2 + latti_point[-1]**2) ** 0.5
thita = atan(- longi_point[-1] / latti_point[-1]) + PI

mouseIsOverColumn = 2 * latti_point[i] - 2 * drift < mouseX-width/2 and mouseX-width/2 < 2 * latti_point[i] + 2 * drift
mouseIsOverRow = -longi_point[i] * 2 - 2 * drift < mouseY-height/2 and mouseY-height/2 < -longi_point[i] * 2 + 2 * drift
mouseIsOverTheRectangle = mouseIsOverColumn and mouseIsOverRow
if mouseIsOverTheRectangle:
left_time_degree = (((endtimes[i]-currenttime)/(endtimes[i]-starttimes[i]))*255)
#print left_time_degree
fill(indexColor[kinds[i]], left_time_degree)
noStroke()
rect(-960, 780, 480, 250)
fill(255)
textSize(26)
text(names[i], -940, 860)
text('Transit Time: ', -940, 900)
text(duration[i]/60, -760, 900)
text('min', -730, 900)
text('Time Left: ', -940, 940)
timeLeft = int((endtimes[i]-currenttime)*60)
text((timeLeft), -780, 940)
text('min', -730, 940)
text(kinds[i], -940, 820)

--

--