SHARE
TWEET

Double Post Point Calculator

faubiguy May 25th, 2014 314 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Calculates player scores for the Double Post thread at the Forum Games section fo the xkcd fora.
  2. # Usage: python doublepostpoints.py [flags]
  3. # Use flag -l to include a log of all post authors, timestamps, and how many points each post scored.
  4. # Use flag -t to only count posts up to the supplied number
  5. # Use flag -i to specify a topic id (to use a different thread)
  6.  
  7. import urllib.request, sys, re, datetime, getopt, time as mtime
  8.  
  9. postPattern = re.compile('<p class="author"><a[^>]*><img[^>]*></a>by <strong><a[^>]*>([^>]*)</a></strong> &raquo; ([^>]*)</p>')
  10. datetimePattern = re.compile('... (...) ([0-9]{2}), ([0-9]{4}) ([0-9]{1,2}):([0-9]{2}) ([ap]m) UTC')
  11. pageNumberPattern = re.compile('Page <strong>([0-9]+)</strong> of <strong>([0-9]+)</strong>')
  12. months = {'Jan':1, 'Feb':2, 'Mar':3, 'Apr':4, 'May':5, 'Jun':6, 'Jul':7, 'Aug':8, 'Sep':9, 'Oct':10, 'Nov':11, 'Dec':12}
  13.  
  14. doneLastPage = False
  15. pagesDone = 0
  16. postsDone = 0
  17. lastPoster = None
  18. lastTime = None
  19. playerPoints = {}
  20.  
  21. log, upto, topicId = False, None, '108854'
  22. flags, _ = getopt.getopt(sys.argv[1:], 'lt:i:')
  23. for flag, value in flags:
  24.         if flag == '-t':
  25.                 upto = int(value)
  26.         elif flag == '-l':
  27.                 log = True
  28.         elif flag == '-i':
  29.                 topicId = (value == 'count' or value == 'million') and '109251' or value
  30.  
  31. log and print('==== Log ====')
  32. try:
  33.         while not doneLastPage:
  34.                 response=None
  35.                 attempts=0
  36.                 while response==None and attempts < 3:
  37.                         try:
  38.                                 response = urllib.request.urlopen('http://forums.xkcd.com/viewtopic.php?t=' + topicId + '&start=' + str(40*pagesDone), timeout=15)
  39.                         except urllib.error.URLError:
  40.                                 pass
  41.                         attempts += 1
  42.                 if not response:
  43.                         sys.exit("Unable to load page " + str(pagesDone+1) + " after 3 attempts")
  44.                 pageHTML = str(response.read())
  45.                 response.close()
  46.                 log and print('Page ' + str(pagesDone+1) + ':')
  47.                 for (poster, time) in re.findall(postPattern, pageHTML):
  48.                         log and print('\t' + poster + ': ' + time)
  49.                         timeParts = re.search(datetimePattern, time).groups()
  50.                         time = datetime.datetime(int(timeParts[2]), months[timeParts[0]], int(timeParts[1]), int(timeParts[3]) % 12 + (timeParts[5] == 'pm' and 12 or 0), int(timeParts[4]))
  51.                         if poster == lastPoster:
  52.                                 points = int(((time - lastTime).total_seconds()/60)**2)
  53.                                 playerPoints[poster] = (poster in playerPoints and playerPoints[poster] or 0) + points
  54.                                 log and print('\t\tScored: ' + str(points))
  55.                         postsDone += 1
  56.                         if upto and postsDone == upto:
  57.                                 raise Exception
  58.                         lastPoster, lastTime = poster, time
  59.                 (currentPage, lastPage) = re.search(pageNumberPattern, pageHTML).group(1, 2)
  60.                 pagesDone += 1
  61.                 doneLastPage = currentPage == lastPage
  62.                 mtime.sleep(1) #Pause to prevent spamming the server with requests.
  63. except Exception:
  64.         pass          
  65.  
  66. log and print('')
  67. print('==== Points ====')
  68. for name in sorted(playerPoints, key=playerPoints.get, reverse=True):
  69.         print(name + ': ' + str(playerPoints[name]))
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top