<commit_before>mongodb = require('../node-mongodb-native/lib/mongodb')
fs = require('fs')
card_info = require('../server/card_info')
deckdata = require('../server/deckdata')
vowpal = require('../server/vowpal')

server = new mongodb.Server("new-caledonia.media.mit.edu", 27017, {})

useCollection = (collection, output) ->
  console.log("finding")
  counter = 0
  # Given a collection, generate deck states from all the games in it.
  collection.find({}, {}).each (err, doc) ->
    throw err if err
    return if not doc?
    counter += 1
    console.log(counter) if (counter % 1000 == 0)
    nPlayers = doc.players.length
    playerdecks = {}

    # Determine how many turns were played
    nTurns = 0
    for playerdeck in doc.decks
      nTurns = Math.max(nTurns, playerdeck.turns.length)
      playerdecks[playerdeck.name] = playerdeck
    if nTurns >= 5 and nPlayers >= 2
      # Don't learn about Possession and Outpost for now; they mess up turn
      # counting.
      if 'Possession' not in supply and 'Outpost' not in supply
        # Set up the initial supply and player states
        states = {}
        supply = {}
        for card in doc.supply
          supply[card] = card_info.numCopiesPerGame(card, nPlayers)
        for card in card_info.everySetCards
          supply[card] = card_info.numCopiesPerGame(card, nPlayers)
        for player in doc.players
          states[player] = {'Copper': 7, 'Estate': 3}
          return if not playerdecks[player]?
        
        # Iterate by turn...
        for turnNum in [0...nTurns]
          # ... then by player
          for player in doc.players
            bestopp = null
            bestscore = -200
            for opponent in doc.players
              if opponent != player and playerdecks[opponent].points > bestscore
                bestopp = opponent
            # TODO: do stuff with the player's deck and the best opponent's
            win = 0
            return if not playerdecks[player]?
            if playerdecks[player].win_points > playerdecks[bestopp].win_points
              win = 1
            else if playerdecks[player].win_points < playerdecks[bestopp].win_points
              win = -1
            if win isnt 0
              outputFeatures(states[player], states[bestopp], supply,
                doc._id+'__'+turnNum, win, output)
              turn = playerdecks[player].turns[turnNum]
              if turn?
                handleDeckChange(player, states, supply, turn)

outputFeatures = (mydeck, oppdeck, supply, id, win, out) ->
  vwStruct = {
    cards: deckdata.normalizeDeck(mydeck)
    opponent: deckdata.normalizeDeck(oppdeck)
    supply: supply
  }
  try
    fs.write(out, vowpal.featureString(id, vwStruct, win)+'\n')
  catch err
    console.log(err)
    debug = {mydeck: mydeck, oppdeck: oppdeck, vwStruct: vwStruct}
    console.log(debug)
    throw "bad feature value"<commit_msg>fix crashing bug in training, when somehow there are no valid opponents<commit_after>mongodb = require('../node-mongodb-native/lib/mongodb')
fs = require('fs')
card_info = require('../server/card_info')
deckdata = require('../server/deckdata')
vowpal = require('../server/vowpal')

server = new mongodb.Server("new-caledonia.media.mit.edu", 27017, {})

useCollection = (collection, output) ->
  console.log("finding")
  counter = 0
  # Given a collection, generate deck states from all the games in it.
  collection.find({}, {}).each (err, doc) ->
    throw err if err
    return if not doc?
    counter += 1
    console.log(counter) if (counter % 1000 == 0)
    nPlayers = doc.players.length
    playerdecks = {}

    # Determine how many turns were played
    nTurns = 0
    for playerdeck in doc.decks
      nTurns = Math.max(nTurns, playerdeck.turns.length)
      playerdecks[playerdeck.name] = playerdeck
    if nTurns >= 5 and nPlayers >= 2
      # Don't learn about Possession and Outpost for now; they mess up turn
      # counting.
      if 'Possession' not in supply and 'Outpost' not in supply
        # Set up the initial supply and player states
        states = {}
        supply = {}
        for card in doc.supply
          supply[card] = card_info.numCopiesPerGame(card, nPlayers)
        for card in card_info.everySetCards
          supply[card] = card_info.numCopiesPerGame(card, nPlayers)
        for player in doc.players
          states[player] = {'Copper': 7, 'Estate': 3}
          return if not playerdecks[player]?
        
        # Iterate by turn...
        for turnNum in [0...nTurns]
          # ... then by player
          for player in doc.players
            bestopp = null
            bestscore = -200
            for opponent in doc.players
              if opponent != player and playerdecks[opponent].points > bestscore
                bestopp = opponent
            # TODO: do stuff with the player's deck and the best opponent's
            win = 0
            return if not bestopp?
            if playerdecks[player].win_points > playerdecks[bestopp].win_points
              win = 1
            else if playerdecks[player].win_points < playerdecks[bestopp].win_points
              win = -1
            if win isnt 0
              outputFeatures(states[player], states[bestopp], supply,
                doc._id+'__'+turnNum, win, output)
              turn = playerdecks[player].turns[turnNum]
              if turn?
                handleDeckChange(player, states, supply, turn)

outputFeatures = (mydeck, oppdeck, supply, id, win, out) ->
  vwStruct = {
    cards: deckdata.normalizeDeck(mydeck)
    opponent: deckdata.normalizeDeck(oppdeck)
    supply: supply
  }
  try
    fs.write(out, vowpal.featureString(id, vwStruct, win)+'\n')
  catch err
    console.log(err)
    debug = {mydeck: mydeck, oppdeck: oppdeck, vwStruct: vwStruct}
    console.log(debug)
    throw "bad feature value"
{'fraction_non_alphanumeric': 0.10353708791208792, 'fraction_numerical': 0.008585164835164836, 'mean_word_length': 2.332379862700229, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '3276865', 'n_tokens_mistral': 1790, 'n_tokens_neox': 1722, 'n_words': 504}