TAG SPACE SUGGESTION ALGORITHM
================================

Overview
--------
When a user opens the "Discover" tab for Spaces, the API returns up to 20
public spaces ranked by a composite score. Spaces the user already joined
or created are excluded.


Final Score Formula
-------------------
  final_score = (connection_score + activity_boost + interest_boost)
                * location_boost


1. Connection Score  (who you know inside the space)
-----------------------------------------------------
Each of the following signals adds points to the connection score:

  +4.0  for each contact (saved in your tag-book) who is currently
        active inside the space
  +2.0  for each person you follow who is currently active inside
        the space
  +3.0  if the space was created by one of your contacts
  +2.5  if the space was created by someone you follow

A space where 3 of your contacts are active scores +12.0 from this
component alone before any other boost is applied.


2. Activity Boost  (how lively the space has been in the last 48 hours)
------------------------------------------------------------------------
  +1.5  per post published in the space within the last 48 hours
  +2.0  per new member who joined the space within the last 48 hours

This keeps recently active spaces ranked above stale ones, even if they
have fewer social-graph connections.


3. Interest Boost  (how well the space matches your interests)
--------------------------------------------------------------
Each space can be tagged with content categories. The viewer's profile
stores a list of personal interests, each with a weight reflecting how
strong that interest is.

  +weight * 2.0  for every space category tag that matches one of
                 the viewer's interests

A space tagged with two categories that both match strong viewer interests
will score significantly higher than an untagged space.


4. Location Multiplier  (proximity of the space)
-------------------------------------------------
The connection + activity + interest sum is multiplied by a factor based
on the straight-line distance between the viewer's GPS coordinates and the
space's registered location:

  x4.0  space is within  2 km of the viewer
  x2.5  space is within 10 km of the viewer
  x1.5  space is within 50 km of the viewer
  x1.1  space is beyond 50 km
  x1.0  space has no location set, or viewer location is unavailable

If the viewer does not share their location, all spaces use the x1.0
multiplier and location plays no role in ranking.


Eligibility Filters  (spaces that never appear in suggestions)
--------------------------------------------------------------
A space is excluded from suggestions if any of the following is true:

  - It is not public or not currently active
  - The viewer is the creator of the space
  - The viewer already has an active session (membership) in the space
  - The space has a member limit and that limit has been reached


Tie-breaking
------------
When two spaces have the same final score, the newer space (by creation
date) appears first.


Example
-------
Suppose a viewer is 1 km from a space, has 2 contacts active in it, and
the space published 4 posts in the last 48 hours:

  connection_score  = 2 contacts * 4.0          =  8.0
  activity_boost    = 4 posts   * 1.5            =  6.0
  interest_boost    = (no matching tags)         =  0.0
  subtotal                                       = 14.0

  location_boost    = within 2 km               x  4.0
  final_score                                    = 56.0

The same space 60 km away with no matching interests would score:
  final_score = 14.0 * 1.1 = 15.4
