+def is_blank_game(players):\r
+ """Determine if this is a blank game or not. A blank game is either:\r
+\r
+ 1) a match that ended in the warmup stage, where accuracy events are not\r
+ present\r
+\r
+ 2) a match in which no player made a positive or negative score AND was\r
+ on the scoreboard\r
+ """\r
+ r = re.compile(r'acc-.*-cnt-fired')\r
+ flg_nonzero_score = False\r
+ flg_acc_events = False\r
+\r
+ for events in players:\r
+ if is_real_player(events):\r
+ for (key,value) in events.items():\r
+ if key == 'scoreboard-score' and value != '0':\r
+ flg_nonzero_score = True\r
+ if r.search(key):\r
+ flg_acc_events = True\r
+\r
+ return not (flg_nonzero_score and flg_acc_events)\r
+\r
+def get_remote_addr(request):\r
+ """Get the Xonotic server's IP address"""\r
+ if 'X-Forwarded-For' in request.headers:\r
+ return request.headers['X-Forwarded-For']\r
+ else:\r
+ return request.remote_addr\r
+\r
+\r
+def is_supported_gametype(gametype):\r
+ """Whether a gametype is supported or not"""\r
+ flg_supported = True\r
+\r
+ if gametype == 'cts' or gametype == 'lms':\r
+ flg_supported = False\r
+\r
+ return flg_supported\r
+\r
+\r
+def verify_request(request):\r
+ try:\r
+ (idfp, status) = d0_blind_id_verify(\r
+ sig=request.headers['X-D0-Blind-Id-Detached-Signature'],\r
+ querystring='',\r
+ postdata=request.body)\r
+\r
+ log.debug('\nidfp: {0}\nstatus: {1}'.format(idfp, status))\r
+ except: \r
+ idfp = None\r
+ status = None\r
+\r
+ return (idfp, status)\r
+\r
+\r
+def num_real_players(player_events, count_bots=False):\r
+ """\r
+ Returns the number of real players (those who played \r
+ and are on the scoreboard).\r
+ """\r
+ real_players = 0\r
+\r
+ for events in player_events:\r
+ if is_real_player(events, count_bots):\r
+ real_players += 1\r
+\r
+ return real_players\r
+\r
+\r
+def has_minimum_real_players(settings, player_events):\r