Advertisement
faubiguy

Double Post Point Calculator

May 25th, 2014
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.87 KB | None | 0 0
  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]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement