   Choose a number, type a name, enter to skip, or q to quit.
   > """
 
+checkedTopGroups = {}
 findUserToSchool = (users) ->
   # We find the top user from the top group that we can make the most reasoned suggestions about what the school name would be.
-  [bestTarget, bestTargetSuggestions, mostReasons] = [null, [], 0]
+  [bestTarget, bestTargetSuggestions, mostReasons, bestGroup] = [null, [], 0, null]
   for field, groups of topGroups
-    for nextLargestGroup in groups
+    for nextLargestGroup in groups when not checkedTopGroups[nextLargestGroup]
       possibleTargets = userCategories[field][nextLargestGroup]
-      schoolNames = _.uniq possibleTargets, 'schoolName'
+      schoolNames = (t.schoolName for t in _.uniq possibleTargets, 'schoolName')
       # TODO: better method to avoid showing users where everyone in the suggestion already has the same school (because we have already done this group)
-      for schoolName in schoolNames
-        if _.filter(possibleTargets, schoolName: schoolName).length > 0.5 * possibleTargets.length
+      alreadyDone = false
+      for schoolName in schoolNames when schoolName?.length > 10 and /,.+,/.test schoolName  # Long enough school name with location info (two commas)
+        sharedCount = _.filter(possibleTargets, schoolName: schoolName).length
+        if sharedCount > 0.5 * possibleTargets.length
+          console.log 'Already done', schoolName, sharedCount, possibleTargets.length, 'for', field, nextLargestGroup
           alreadyDone = true
       continue if alreadyDone
       nSamples = Math.min 15, Math.max(4, Math.floor possibleTargets.length / 20)
-      console.log 'Checking', nSamples, 'samples of', possibleTargets.length, 'players in the biggest', field, 'group:', nextLargestGroup
+      if debugging then console.log 'Checking', nSamples, 'samples of', possibleTargets.length, 'players in the biggest', field, 'group:', nextLargestGroup
       for i in [0 ... nSamples]
         target = possibleTargets[Math.floor i * possibleTargets.length / (nSamples + 1)]
         suggestions = findSuggestions target

                when 'Name' then 30
                when 'Referrer' then 20
                when 'Domain' then (if getDomain(target) is 'cps.edu' then 1 else 10)
                when 'Clans' then 0.1
          sum
        ), 0
        if reasons > mostReasons
          bestTarget = target
          bestTargetSuggestions = suggestions
          mostReasons = reasons
      break
  return [bestTarget, bestTargetSuggestions]

findSuggestions = (target) ->
  # Look for other users with the same IP, course instances, clans, or similar school names or non-common shared email domains.
  suggestions = []
  t0 = new Date()
  console.log '  Checking suggestions for', target.emailLower, target.schoolName, (new Date()) - t0
  if target.lastIP
    for otherUser in (userCategories.lastIP[target.lastIP] ? []) when otherUser isnt target
      suggestions.push schoolName: otherUser.schoolName, reasons: ['IP'], user: otherUser
  for leagueType in ['courseInstances', 'clans']
    console.log '    Now checking', leagueType, (new Date()) - t0
    if target[leagueType]?.length
      for league in target[leagueType]
        for otherUser in (userCategories[leagueType][league] ? []) when otherUser isnt target

  "virgin.net", "wanadoo.co.uk", "bt.com",

  # Domains used in Asia
  "sina.com", "qq.com", "naver.com", "hanmail.net", "daum.net", "nate.com", "yahoo.co.jp", "yahoo.co.kr", "yahoo.co.id", "yahoo.co.in", "yahoo.com.sg", "yahoo.com.ph", "yahoo.com.tw"

  # French ISP domains
  "hotmail.fr", "live.fr", "laposte.net", "yahoo.fr", "wanadoo.fr", "orange.fr", "gmx.fr", "sfr.fr", "neuf.fr", "free.fr",
