<commit_before>"""
This is TF2Toolbox in Flask Python!
"""

from __future__ import with_statement

from collections import defaultdict
import contextlib
import datetime
import httplib
import os
import simplejson as json
import urllib2
import xml.dom.minidom

import bpdata

from flask import *

# Configuration
DEBUG = False
SECRET_KEY = '<KEY>'

app = Flask(__name__)
app.config.from_object(__name__)
app.jinja_env.trim_blocks = True


@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
  template_info = {'nav_cell': 'Home'}
  if request.method == 'POST':
    set_user_session(template_info, request.form['steamURL'])
  return render_template('index.html', template_info=template_info, session=session)

@app.route('/about', methods=['GET', 'POST'])
def about():
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])
  return render_template('about.html', template_info={}, session=session)

@app.route('/bptext', methods=['GET', 'POST'])
def bptext():
  template_info = {'nav_cell': 'Backpack Text', 'signin_action': '/bptext'}
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])

    elif request.form['form_id'] == 'bptext':
      if 'steamID' in session:
        bp_json = get_user_backpack(template_info, session['steamID'])
        if 'error_msg' not in template_info:
          bp_parse(template_info, bp_json, request.form, session)
      return render_template('bptext_result.html', template_info=template_info, session=session)

  return render_template('bptext_form.html', template_info=template_info, session=session)

@app.route('/metal', methods=['GET', 'POST'])
def metal():
  template_info = {'nav_cell': 'Metal Maker', 'signin_action': '/metal'}
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])

    elif request.form['form_id'] == 'metal':
      if 'steamID' in session:
        bp_json = get_user_backpack(template_info, session['steamID'])
        if 'error_msg' not in template_info:
          bp_metal(template_info, bp_json, request.form, session)
      return render_template('metal_result.html', template_info=template_info, session=session)

  return render_template('metal_form.html', template_info=template_info, session=session)

@app.route('/weapons', methods=['GET', 'POST'])
def weapons():
  template_info = {'nav_cell': 'Weapon Stock', 'signin_action': '/weapons'}
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])
  if 'steamID' in session:
    bp_json = get_user_backpack(template_info, session['steamID'])
    if 'error_msg' not in template_info:
      bp_weapons(template_info, bp_json, session)
  return render_template('weapon_stock.html', template_info=template_info, session=session)

def set_user_session(template_info, steamURL):
  """
  Given a Steam Community URL, sets the following session variables for the current user:
    * username
    * avatar
    * steamID
    * num_bp_slots
    * customURL

  In the case of an error, adds an error message to template_info.

  TODO: Consider using xml.etree.ElementTree, or lxml, instead of xml.dom.minidom
  """
  session.pop('username', None)
  session.pop('avatar', None)
  session.pop('steamID', None)
  session.pop('num_bp_slots', None)
  session.pop('customURL', None)

  if not steamURL.startswith('http://steamcommunity.com/id/') and not steamURL.startswith('http://steamcommunity.com/profiles/'):
    template_info['error_msg'] = "That was not a valid Steam Community URL.\n"
    return

  steamURL += "?xml=1"

  try:
    url_file = urllib2.urlopen(steamURL)
    user_data = xml.dom.minidom.parse(url_file)
    root_children = user_data.documentElement.childNodes
    vars_set = 0
    for child in root_children:
      if child.nodeName ==  'steamID':
        session['username'] = child.firstChild.nodeValue
      elif child.nodeName == 'avatarMedium':
        session['avatar'] = child.firstChild.nodeValue
      elif child.nodeName == 'steamID64':
        session['steamID'] = child.firstChild.nodeValue
      elif child.nodeName == 'customURL':
        session['customURL'] = child.firstChild.nodeValue
  except urllib2.URLError:
    template_info['error_msg'] = "We were unable to retrieve that URL. Please try again!\n"
    return
  except xml.parsers.expat.ExpatError:
    pass

  if 'username' not in session or 'avatar' not in session or 'steamID' not in session:
    template_info['error_msg'] = "We were unable to retrieve info for that profile.\n"
    return

  bp_json = get_user_backpack(template_info, session['steamID'])
  if not bp_json:
    return
  session['num_bp_slots'] = bp_json['result']['num_backpack_slots']


def get_user_backpack(template_info, steamID):
  """
  Given an user's Steam ID, returns the backpack as a JSON object.

  In the case of an error, adds an error message to template_info.
  """
  backpack_url = "http://api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/?SteamID=" + steamID + "&key=<KEY>"
  try:
    url_file = urllib2.urlopen(backpack_url)
    bp_json = json.load(url_file)
  except urllib2.URLError:
    template_info['error_msg'] = "We were unable to retrieve that user's backpack.\n"

  status = bp_json['result']['status']
  if status == 1: #backpack validation
    return bp_json
  elif status == 15:
    template_info['error_msg'] = "Sorry, this user's backpack is private.\n"
  elif status == 8 or status == 18:
    template_info['error_msg'] = "Invalid SteamID.\n"
  return None

def pretty(json_obj):
  print json.dumps(json_obj, sort_keys=True, indent=2)



def bp_weapons(template_info, bp, session_info):
  """
  Given a JSON representation of a backpack,  and a copy of the user's session info (steamID, customURL, etc.),
  returns the following in template_info.

    * Weapon info on the backpack
    * Errors if needed.

  """

  # Result schema;
  """
  'result': {
    'Scout': {
      'essential': {'Sandman': True, 'Soda Popper': False}
      'alternative': {'Three-Rune Blade': False}
    }
    'Soldier'...
    'Multiple'
  }
  """
  schema = get_schema()
  if not schema:
    template_info['error_msg'] = "Could not retrieve the TF2 Item Schema.\n"
    return

  result = {
    'ordered_classes': ['Scout', 'Soldier', 'Pyro', 'Demoman', 'Heavy', 'Engineer', 'Medic', 'Sniper', 'Spy', 'Multiple'],
    'Special': {'alternative': {}}
  }
  for cls in result['ordered_classes']:
    result[cls] = {'essential': {}, 'alternative': {}}

  # Load the schema into an usable form, with defindexes as keys.
  s = {}
  for entry in schema['result']['items']:
    # Load the weapon list.
    if entry.get('item_slot', None) in ['primary', 'secondary', 'melee', 'pda', 'pda2'] and entry['item_class'] != 'slot_token':
      used_by = entry.get('used_by_classes', None)
      item_name = entry['item_name']

      # Categorize the weapon. Is it essential (adds new functionality to game?) or alternative (replicates existing functionality/promotional)
      # Is it used by one class or multiple?
      # Is it a stock weapon? (defindex 0-30). If so, initialize to True.
      category = 'essential'
      if item_name in bpdata.ALT_WEAPONS or item_name in bpdata.LIMITED_WEAPONS:
        category = 'alternative'

      if not used_by or len(used_by) > 1: # Special case for Saxxy - used_by = None
        cls = 'Multiple'
      else:
        cls = used_by[0]

      if item_name not in result[cls][category]:
        if entry.get('defindex') <= 30:
          result[cls][category][item_name] = [True, entry.get('image_url')]
        else:
          result[cls][category][item_name] = [False, entry.get('image_url')]
      else:
        if entry.get('defindex') <= 30:
          result[cls][category][item_name] = [True, entry.get('image_url')]



      s[entry['defindex']] = {'name': entry['item_name'],
                              'used_by': cls,
                              'category': category
                             }
<commit_msg>fixing upgradeable multiclass stock weapons, i.e. shotty pistol<commit_after>"""
This is TF2Toolbox in Flask Python!
"""

from __future__ import with_statement

from collections import defaultdict
import contextlib
import datetime
import httplib
import os
import simplejson as json
import urllib2
import xml.dom.minidom

import bpdata

from flask import *

# Configuration
DEBUG = False
SECRET_KEY = '<KEY>'

app = Flask(__name__)
app.config.from_object(__name__)
app.jinja_env.trim_blocks = True


@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
  template_info = {'nav_cell': 'Home'}
  if request.method == 'POST':
    set_user_session(template_info, request.form['steamURL'])
  return render_template('index.html', template_info=template_info, session=session)

@app.route('/about', methods=['GET', 'POST'])
def about():
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])
  return render_template('about.html', template_info={}, session=session)

@app.route('/bptext', methods=['GET', 'POST'])
def bptext():
  template_info = {'nav_cell': 'Backpack Text', 'signin_action': '/bptext'}
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])

    elif request.form['form_id'] == 'bptext':
      if 'steamID' in session:
        bp_json = get_user_backpack(template_info, session['steamID'])
        if 'error_msg' not in template_info:
          bp_parse(template_info, bp_json, request.form, session)
      return render_template('bptext_result.html', template_info=template_info, session=session)

  return render_template('bptext_form.html', template_info=template_info, session=session)

@app.route('/metal', methods=['GET', 'POST'])
def metal():
  template_info = {'nav_cell': 'Metal Maker', 'signin_action': '/metal'}
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])

    elif request.form['form_id'] == 'metal':
      if 'steamID' in session:
        bp_json = get_user_backpack(template_info, session['steamID'])
        if 'error_msg' not in template_info:
          bp_metal(template_info, bp_json, request.form, session)
      return render_template('metal_result.html', template_info=template_info, session=session)

  return render_template('metal_form.html', template_info=template_info, session=session)

@app.route('/weapons', methods=['GET', 'POST'])
def weapons():
  template_info = {'nav_cell': 'Weapon Stock', 'signin_action': '/weapons'}
  if request.method == 'POST':
    if request.form['form_id'] == 'signin':
      set_user_session(template_info, request.form['steamURL'])
  if 'steamID' in session:
    bp_json = get_user_backpack(template_info, session['steamID'])
    if 'error_msg' not in template_info:
      bp_weapons(template_info, bp_json, session)
  return render_template('weapon_stock.html', template_info=template_info, session=session)

def set_user_session(template_info, steamURL):
  """
  Given a Steam Community URL, sets the following session variables for the current user:
    * username
    * avatar
    * steamID
    * num_bp_slots
    * customURL

  In the case of an error, adds an error message to template_info.

  TODO: Consider using xml.etree.ElementTree, or lxml, instead of xml.dom.minidom
  """
  session.pop('username', None)
  session.pop('avatar', None)
  session.pop('steamID', None)
  session.pop('num_bp_slots', None)
  session.pop('customURL', None)

  if not steamURL.startswith('http://steamcommunity.com/id/') and not steamURL.startswith('http://steamcommunity.com/profiles/'):
    template_info['error_msg'] = "That was not a valid Steam Community URL.\n"
    return

  steamURL += "?xml=1"

  try:
    url_file = urllib2.urlopen(steamURL)
    user_data = xml.dom.minidom.parse(url_file)
    root_children = user_data.documentElement.childNodes
    vars_set = 0
    for child in root_children:
      if child.nodeName ==  'steamID':
        session['username'] = child.firstChild.nodeValue
      elif child.nodeName == 'avatarMedium':
        session['avatar'] = child.firstChild.nodeValue
      elif child.nodeName == 'steamID64':
        session['steamID'] = child.firstChild.nodeValue
      elif child.nodeName == 'customURL':
        session['customURL'] = child.firstChild.nodeValue
  except urllib2.URLError:
    template_info['error_msg'] = "We were unable to retrieve that URL. Please try again!\n"
    return
  except xml.parsers.expat.ExpatError:
    pass

  if 'username' not in session or 'avatar' not in session or 'steamID' not in session:
    template_info['error_msg'] = "We were unable to retrieve info for that profile.\n"
    return

  bp_json = get_user_backpack(template_info, session['steamID'])
  if not bp_json:
    return
  session['num_bp_slots'] = bp_json['result']['num_backpack_slots']


def get_user_backpack(template_info, steamID):
  """
  Given an user's Steam ID, returns the backpack as a JSON object.

  In the case of an error, adds an error message to template_info.
  """
  backpack_url = "http://api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/?SteamID=" + steamID + "&key=<KEY>"
  try:
    url_file = urllib2.urlopen(backpack_url)
    bp_json = json.load(url_file)
  except urllib2.URLError:
    template_info['error_msg'] = "We were unable to retrieve that user's backpack.\n"

  status = bp_json['result']['status']
  if status == 1: #backpack validation
    return bp_json
  elif status == 15:
    template_info['error_msg'] = "Sorry, this user's backpack is private.\n"
  elif status == 8 or status == 18:
    template_info['error_msg'] = "Invalid SteamID.\n"
  return None

def pretty(json_obj):
  print json.dumps(json_obj, sort_keys=True, indent=2)



def bp_weapons(template_info, bp, session_info):
  """
  Given a JSON representation of a backpack,  and a copy of the user's session info (steamID, customURL, etc.),
  returns the following in template_info.

    * Weapon info on the backpack
    * Errors if needed.

  """

  # Result schema;
  """
  'result': {
    'Scout': {
      'essential': {'Sandman': True, 'Soda Popper': False}
      'alternative': {'Three-Rune Blade': False}
    }
    'Soldier'...
    'Multiple'
  }
  """
  schema = get_schema()
  if not schema:
    template_info['error_msg'] = "Could not retrieve the TF2 Item Schema.\n"
    return

  result = {
    'ordered_classes': ['Scout', 'Soldier', 'Pyro', 'Demoman', 'Heavy', 'Engineer', 'Medic', 'Sniper', 'Spy', 'Multiple'],
    'Special': {'alternative': {}}
  }
  for cls in result['ordered_classes']:
    result[cls] = {'essential': {}, 'alternative': {}}

  # Load the schema into an usable form, with defindexes as keys.
  s = {}
  for entry in schema['result']['items']:
    # Load the weapon list.
    if entry.get('item_slot', None) in ['primary', 'secondary', 'melee', 'pda', 'pda2'] and entry['item_class'] != 'slot_token':

      # Skip multiclass stock upgradeables.
      if entry.get('defindex') >= 190 and entry.get('defindex') <= 212:
        continue
      used_by = entry.get('used_by_classes', None)
      item_name = entry['item_name']

      # Categorize the weapon. Is it essential (adds new functionality to game?) or alternative (replicates existing functionality/promotional)
      # Is it used by one class or multiple?
      # Is it a stock weapon? (defindex 0-30). If so, initialize to True.
      category = 'essential'
      if item_name in bpdata.ALT_WEAPONS or item_name in bpdata.LIMITED_WEAPONS:
        category = 'alternative'

      if not used_by or len(used_by) > 1: # Special case for Saxxy - used_by = None
        cls = 'Multiple'
      else:
        cls = used_by[0]

      if item_name not in result[cls][category]:
        if entry.get('defindex') <= 30:
          result[cls][category][item_name] = [True, entry.get('image_url')]
        else:
          result[cls][category][item_name] = [False, entry.get('image_url')]

      s[entry['defindex']] = {'name': entry['item_name'],
                              'used_by': cls,
                              'category': category
                             }

{'fraction_non_alphanumeric': 0.1350958040261945, 'fraction_numerical': 0.004487024011642009, 'mean_word_length': 3.8608900677866194, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5580322', 'n_tokens_mistral': 5455, 'n_tokens_neox': 5275, 'n_words': 1349}