Skip to content

Commit

Permalink
commited rdennis's syle refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
rrenaud committed Apr 30, 2011
1 parent b2dbe3f commit 147eda7
Show file tree
Hide file tree
Showing 26 changed files with 502 additions and 473 deletions.
1 change: 1 addition & 0 deletions INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mongodb - http://www.mongodb.org/downloads
pymongo - http://api.mongodb.org/python/1.9%2B/index.html
webpy - http://webpy.org/
argparse - http://code.google.com/p/argparse/ - included in Python 2.7/3.2
simplejson - http://pypi.python.org/pypi/simplejson/

mkdir db
Run an instance of mongodb with mongod --dbpath=db
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The code depends on:
- pymongo (http://api.mongodb.org/python/1.9%2B/index.html)
- web.py (http://webpy.org)
- argparse (included in Python 2.7/3.2)
- simplejson (http://pypi.python.org/pypi/simplejson/)

See INSTALL for instructions on how to set up the database.

41 changes: 20 additions & 21 deletions analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class CardStatistic(PrimitiveConversion):
number of a given card. Card advantages are rounded relative
to the average number gained/bought by other players through the
game.
"""
"""
def __init__(self):
self.available = 0
self.win_any_accum = MeanVarStat()
Expand All @@ -53,16 +53,15 @@ def analyze_game(self, game):
"""
self.num_games += 1
seen_cards_players = set()
self.max_game_id = max(self.max_game_id, game.Id())
for card in game.Supply() + card_info.EVERY_SET_CARDS:
self.card_stats[card].available += len(game.PlayerDecks())

accumed_by_player = collections.defaultdict(
lambda : collections.defaultdict(int))
for turn in game.Turns():
deck = turn.Player()
turnno = turn.TurnNo()
for card in turn.PlayerAccumulates():
self.max_game_id = max(self.max_game_id, game.get_id())
for card in game.get_supply() + card_info.EVERY_SET_CARDS:
self.card_stats[card].available += len(game.get_player_decks())

accumed_by_player = collections.defaultdict(lambda : collections.defaultdict(int))
for turn in game.get_turns():
deck = turn.get_player()
turnno = turn.get_turn_no()
for card in turn.player_accumulates():
per_card_stat = self.card_stats[card]
if (deck, card) not in seen_cards_players:
seen_cards_players.add((deck, card))
Expand All @@ -80,7 +79,7 @@ def analyze_game(self, game):
odeck_count += 1
for card in other_accum:
total_other_decks[card] += other_accum[card]
assert odeck_count != 0, game.IsotropicUrl()
assert odeck_count != 0, game.isotropic_url()
for card in set(card_accum_dict.keys() + total_other_decks.keys()):
per_card_stat = self.card_stats[card]
other_avg_freq = total_other_decks[card] / odeck_count
Expand Down Expand Up @@ -110,16 +109,16 @@ def main():
if args.incremental:
utils.read_object_from_db(game_analysis, output_collection, '')
else:
scanner.Reset()
scanner.reset()

output_file_name = 'static/output/all_games_card_stats.js'

if not os.path.exists('static/output'):
os.makedirs('static/output')

print scanner.StatusMsg()
print scanner.status_msg()

for idx, raw_game in enumerate(scanner.Scan(games, {})):
for idx, raw_game in enumerate(scanner.scan(games, {})):
try:
if idx % 1000 == 0:
print idx
Expand All @@ -128,21 +127,21 @@ def main():
if idx == args.max_games:
break
except int, exception:
print Game(raw_game).IsotropicUrl()
print Game(raw_game).isotropic_url()
print exception
print raw_game
raise

game_analysis.max_game_id = scanner.MaxGameId()
game_analysis.num_games = scanner.NumGames()
game_analysis.max_game_id = scanner.get_max_game_id()
game_analysis.num_games = scanner.get_num_games()
utils.write_object_to_db(game_analysis, output_collection, '')

output_file = open(output_file_name, 'w')
output_file.write('var all_card_data = ')

json.dump(game_analysis.ToPrimitiveObject(), output_file)
print scanner.StatusMsg()
scanner.Save()
json.dump(game_analysis.to_primitive_object(), output_file)
print scanner.status_msg()
scanner.save()

if __name__ == '__main__':
main()
39 changes: 20 additions & 19 deletions card_info.py → card_info/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import csv
import os

_cardlist_reader = csv.DictReader(open('card_list.csv'))
_cardlist_reader = csv.DictReader(open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'card_list.csv')))
_to_singular = {}
_to_plural = {}
_card_index = {}

_card_info_rows = {}

def _Init():
#the way this file is being used, it seems like a good candidate for some sort
#of Card class with properties, etc
def _init():
for idx, cardlist_row in enumerate(_cardlist_reader):
single, plural = cardlist_row['Singular'], cardlist_row['Plural']
_to_singular[single] = single
Expand All @@ -19,44 +20,44 @@ def _Init():
_card_index[single] = idx
_card_info_rows[single] = cardlist_row

_Init()
_init()

def SingularOf(card_name):
def singular_of(card_name):
return _to_singular[card_name]

def PluralOf(card_name):
def plural_of(card_name):
return _to_plural[card_name]

def Pluralize(card, freq):
return SingularOf(card) if freq == 1 else PluralOf(card)
def pluralize(card, freq):
return singular_of(card) if freq == 1 else plural_of(card)

def VPPerCard(singular_card_name):
def vp_per_card(singular_card_name):
try:
return int(_card_info_rows[singular_card_name]['VP'])
except ValueError:
return 0

def IsTreasure(singular_card_name):
def is_treasure(singular_card_name):
return _card_info_rows[singular_card_name]['Treasure'] == '1'

def Cost(singular_card_name):
def cost(singular_card_name):
return _card_info_rows[singular_card_name]['Cost']

# Returns value of card name if the value is unambigous.
def MoneyValue(card_name):
# Returns value of card name if the value is unambiguous.
def money_value(card_name):
try:
return int(_card_info_rows[card_name]['Coins'])
except ValueError, e:
return 0

def IsVictory(singular_card_name):
def is_victory(singular_card_name):
return _card_info_rows[singular_card_name]['Victory'] == '1'

def IsAction(singular_card_name):
def is_action(singular_card_name):
return _card_info_rows[singular_card_name]['Action'] == '1'

def NumCopiesPerGame(card_name, num_players):
if IsVictory(card_name):
def num_copies_per_game(card_name, num_players):
if is_victory(card_name):
if num_players >= 3:
return 12
return 8
Expand All @@ -76,8 +77,8 @@ def NumCopiesPerGame(card_name, num_players):
'Copper', 'Silver', 'Gold', 'Curse']

OPENING_CARDS = [card for card in _card_info_rows
if Cost(card) in ('0', '2', '3', '4', '5')]
if cost(card) in ('0', '2', '3', '4', '5')]
OPENING_CARDS.sort()

def CardIndex(singular):
def card_index(singular):
return _card_index[singular]
File renamed without changes.
41 changes: 21 additions & 20 deletions count_buys.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@ def accum_buy_stats(games_stream, accum_stats,
"""
for idx, game_val in enumerate(games_stream):
counted_game_len = False
supply_cards = set(game_val.Supply()).union(card_info.EVERY_SET_CARDS)
every_set_cards = card_info.EVERY_SET_CARDS
supply_cards = set(game_val.get_supply()).union(every_set_cards)

for changes in game_val.DeckChangesPerPlayer():
for changes in game_val.deck_changes_per_player():
if not acceptable_deck_filter(game_val, changes.name):
continue
any_gained = set()
win_points = game_val.GetPlayerDeck(changes.name).WinPoints()
win_points = game_val.get_player_deck(changes.name).WinPoints()

for category in game.PlayerDeckChange.CATEGORIES:
for card in getattr(changes, category):
Expand All @@ -97,11 +98,11 @@ def accum_buy_stats(games_stream, accum_stats,

if not counted_game_len: # don't double count this
counted_game_len = True
game_len = game_val.Turns()[-1].TurnNo()
game_len = game_val.get_turns()[-1].get_turn_no()
for card in supply_cards:
stats_obj = accum_stats[card]
stats_obj.game_length.AddOutcome(game_len)
if 'Colony' in game_val.Supply():
if 'Colony' in game_val.get_supply():
stats_obj.game_length_colony.AddOutcome(game_len)

if idx + 1 == max_games:
Expand All @@ -113,20 +114,20 @@ def add_effectiveness(accum_stats, global_stats):
don't gain the card.
"""
# first, find the incremental effect of the player's skill
any_eff = accum_stats['Estate'].available.meanDiff(
any_eff = accum_stats['Estate'].available.mean_diff(
global_stats['Estate'].available)

for card in accum_stats:
# now compare games in which the player gains/skips the card to gains
# in which other players gain/skip the card
stats_obj = accum_stats[card]
global_stats_obj = global_stats[card]
card_gain_eff = stats_obj.any_gained.meanDiff(
card_gain_eff = stats_obj.any_gained.mean_diff(
global_stats_obj.any_gained)
card_skip_eff = stats_obj.none_gained.meanDiff(
card_skip_eff = stats_obj.none_gained.mean_diff(
global_stats_obj.none_gained)
stats_obj.effectiveness_gain = card_gain_eff.meanDiff(any_eff)
stats_obj.effectiveness_skip = card_skip_eff.meanDiff(any_eff)
stats_obj.effectiveness_gain = card_gain_eff.mean_diff(any_eff)
stats_obj.effectiveness_skip = card_skip_eff.mean_diff(any_eff)

def progress_meter(iterable, chunksize):
""" Prints progress through iterable at chunksize intervals."""
Expand All @@ -149,7 +150,7 @@ def do_scan(scanner, games_col, accum_stats, max_games):
accum_stats: DeckBuyStats instance to store results.
"""
def games_stream():
for raw_game in progress_meter(scanner.Scan(games_col, {}), 1000):
for raw_game in progress_meter(scanner.scan(games_col, {}), 1000):
yield game.Game(raw_game)
accum_buy_stats(games_stream(), accum_stats, max_games=max_games)

Expand All @@ -170,31 +171,31 @@ def main():

if not args.incremental:
print 'resetting scanner and db'
scanner.Reset()
scanner.reset()
buy_collection.drop()

start_size = scanner.NumGames()
print scanner.StatusMsg()
start_size = scanner.get_num_games()
print scanner.status_msg()
do_scan(scanner, games, overall_stats, args.max_games)
print scanner.StatusMsg()
end_size = scanner.NumGames()
print scanner.status_msg()
end_size = scanner.get_num_games()

if args.incremental:
existing_overall_data = DeckBuyStats()
utils.read_object_from_db(existing_overall_data, buy_collection, '')
overall_stats.Merge(existing_overall_data)
overall_stats.merge(existing_overall_data)
def deck_freq(data_set):
return data_set['Estate'].available.Frequency()
print 'existing', deck_freq(existing_overall_data), 'decks'
print 'after merge', deck_freq(overall_stats), 'decks'

utils.write_object_to_db(overall_stats, buy_collection, '')

scanner.Save()
scanner.save()
time_diff = time.time() - start
games_diff = end_size - start_size
print 'took', time_diff, 'seconds for', games_diff, 'games for a rate' \
' of', games_diff / time_diff, 'games/sec'
print ('took', time_diff, 'seconds for', games_diff, 'games for a rate of',
games_diff / time_diff, 'games/sec')

def profilemain():
""" Like main(), but print a profile report."""
Expand Down
3 changes: 2 additions & 1 deletion count_plays.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pymongo
from collections import defaultdict

#module-level things like this can break
c = pymongo.Connection()
games = c.test.games

Expand Down Expand Up @@ -146,6 +146,7 @@ def _relative_rate(combo, rates):
rates[(combo[1],)] * rates[(combo[0], combo[2])],
rates[(combo[2],)] * rates[(combo[0], combo[1])]
)
#FIXME: this falls through if not 1/2/3
return rates[combo] / expected

if __name__ == '__main__':
Expand Down
Loading

0 comments on commit 147eda7

Please sign in to comment.