def test_sqlite_caching(): # test that we can use the SQLite cache # generate a temporary file fd, name = tempfile.mkstemp(suffix=".cache") # close the file and unlink it, we only need the temporary name os.close(fd) os.unlink(name) assert not os.path.isfile(name) with pytest.raises(BoardGameGeekError): # invalid value for the ttl parameter BoardGameGeek(cache="sqlite://{}?ttl=blabla&fast_save=0".format(name)) with pytest.raises(BoardGameGeekError): BoardGameGeek(cache="invalid://cache") bgg = BoardGameGeek(cache="sqlite://{}?ttl=1000".format(name)) user = bgg.user(TEST_VALID_USER) assert user is not None assert user.name == TEST_VALID_USER assert os.path.isfile(name) # clean up.. os.unlink(name)
def __init__(self, db): self.db = db self.bgg = BoardGameGeek() self.publishers = { "999 Games": "&include%5Bpublisherid%5D=267", "Asmodee": "&include%5Bpublisherid%5D=157", "Avalon Hill": "&include%5Bpublisherid%5D=5", "Bergsala Enigma": "&include%5Bpublisherid%5D=6784", "Cool mini or not": "&include%5Bpublisherid%5D=34793", "Czech Games Edition": "&include%5Bpublisherid%5D=7345", "Days of Wonder": "&include%5Bpublisherid%5D=1027", "Don & Co": "&include%5Bpublisherid%5D=137", "Fantasy Flight Games": "&include%5Bpublisherid%5D=17", "Fun Forge": "&include%5Bpublisherid%5D=8832", "Games Workshop": "&include%5Bpublisherid%5D=26", "Guillotine Games": "&include%5Bpublisherid%5D=21020", "Hurrican": "&include%5Bpublisherid%5D=6015", "Iello": "&include%5Bpublisherid%5D=8923", "Intrafin Games": "&include%5Bpublisherid%5D=5380", "Libellud": "&include%5Bpublisherid%5D=9051", "Ludonaute": "&include%5Bpublisherid%5D=11688", "Monolith Games": "&include%5Bpublisherid%5D=27147", "Osprey Games": "&include%5Bpublisherid%5D=29313", "Plaid Hat Games": "&include%5Bpublisherid%5D=10754", "Queen Games": "&include%5Bpublisherid%5D=47", "Repos Production": "&include%5Bpublisherid%5D=4384", "Space Cowboys": "&include%5Bpublisherid%5D=25842", "Steve Jackson Games": "&include%5Bpublisherid%5D=19", "Story Factory": "&include%5Bpublisherid%5D=17940", "Studio McVey": "&include%5Bpublisherid%5D=21608", "The Game Master": "&include%5Bpublisherid%5D=2862", "White Goblin Games": "&include%5Bpublisherid%5D=4932", "Z-Man Games": "&include%5Bpublisherid%5D=538" }
def get(self, request): bgg = BoardGameGeek(retries=10, retry_delay=2) game = bgg.game("Dominion") game_rank = game.id ctx = {'game': game_rank} return render(request, 'board/bgg.html', ctx)
def test_no_caching(): # test that we can disable caching bgg = BoardGameGeek(cache=None) user = bgg.user(TEST_VALID_USER) assert user is not None assert user.name == TEST_VALID_USER
def bgg_game(request, game_id): bgg = BoardGameGeek() # we return error if game already in DB try: game = Game.objects.get(id_bgg=game_id) except Game.DoesNotExist: # the game is not in the DB. All fine # fetch game data from BGG try: bgg_game = bgg.game(game_id=game_id) except BoardGameGeekError: pass # We try to guess the game type - for suggestion to the user if "Children's Game" in bgg_game.categories: type_genre = 'Enfants' elif 'Abstract Strategy' in bgg_game.categories: type_genre = 'Stratégie' elif 'Area Control / Area Influence' in bgg_game.mechanics or 'Tile Placement' in bgg_game.mechanics: type_genre = 'Placement' elif 'Worker Placement' in bgg_game.mechanics: type_genre = 'Gestion' elif 'Racing' in bgg_game.mechanics: type_genre = 'Parcours' elif 'Auction/Bidding' in bgg_game.mechanics: type_genre = 'Enchères' elif 'Co-operative Play' in bgg_game.mechanics: type_genre = 'Coopératif' elif 'Party Game' in bgg_game.categories: type_genre = 'Ambiance' else: type_genre = None data = { 'id_bgg': bgg_game.id, 'name': bgg_game.name, 'type_genre': type_genre, 'min_player': bgg_game.min_players, 'max_player': bgg_game.max_players, 'min_age': bgg_game.min_age, 'duration': bgg_game.playing_time, 'description': bgg_game.description, 'thumbnail': bgg_game.thumbnail, 'image': bgg_game.image } return JsonResponse(data) else: # Game is already in DB - return 400 return JsonResponse( {"__errors__": [ { 'field': 'ID BGG', 'errors': ['Ce jeu existe deja. Nom du jeu: %s (ID BGG: %s)' % (game.name, game_id)] } ]}, status=400)
def test_rate_limiting_for_requests(): # create two threads, give each a list of games to fetch, disable cache and time the amount needed to # fetch the data. requests should be serialized, even if made from two different threads test_set_1 = [ 5, # acquire 31260, # agricola 72125 ] # "eclipse" test_set_2 = [ 18602, #caylus 28720, # brass 53953 ] # thunderstone] def _worker_thread(games): bgg = BoardGameGeek(cache=None, requests_per_minute=20) for g in games: bgg.game(game_id=g) t1 = threading.Thread(target=_worker_thread, args=(test_set_1, )) t2 = threading.Thread(target=_worker_thread, args=(test_set_2, )) start_time = time.time() t1.start() t2.start() t1.join(timeout=10000) t2.join(timeout=10000) end_time = time.time() # 20 requests per minute => a request every 3 seconds x 6 games => should take around 18 seconds assert 15 < end_time - start_time < 21 # +/- a few seconds... # second test, use caching and confirm it's working when combined with the rate limiting algorithm # do cached requests for the test set, then do them again. should take only half of the time bgg = BoardGameGeek(requests_per_minute=20) start_time = time.time() for g in test_set_1: bgg.game(game_id=g) end_time = time.time() assert 7 < end_time - start_time < 11 # 3 games should take ~9 seconds # repeat requests, should be served from cache for g in test_set_1: bgg.game(game_id=g) assert 0 < time.time() - end_time < 2
def get(self, request, game_id): form = Game.objects.get(pk=game_id) title_en = form.title_en try: bgg = BoardGameGeek(retries=10, retry_delay=2) game = bgg.game(title_en) game_rank = game.ranks game_rank_dict = game_rank[0] rank = game_rank_dict['value'] ctx = {'form': form, 'game_rank': rank} return render(request, 'board/game.html', ctx) except AttributeError: rank = "n/a" ctx = {'form': form, 'game_rank': rank} return render(request, 'board/game.html', ctx)
def _worker_thread(games): bgg = BoardGameGeek(cache=None, requests_per_minute=20) for g in games: bgg.game(game_id=g)
def bgg(): return BoardGameGeek(cache=None, retries=0, retry_delay=0) # disable retrying for testing
from boardgamegeek import BoardGameGeek from boardgamegeek import BoardGameGeekAPIError import pandas as pd bgg = BoardGameGeek() gameframe = pd.DataFrame({ "Name": [], "Year": [], "ID": [], "BGGRank": [], "Mechanics": [], "Playtime": [], "Min_Age": [], "Median_Rating": [], "Bays_Rating": [] }) for i in range(1, 12): try: g = bgg.game(game_id=i) gamedat = pd.DataFrame({ "Name": [g.name], "ID": [g.id], "Year": [g.year], "BGGRank": [g.boardgame_rank], "Mechanics": [g.mechanics], "Playtime": [g.playing_time], "Min_Age": [g.min_age], "Median_Rating": [g.rating_median], "Bays_Rating": [g.rating_bayes_average] }) gameframe = pd.concat([gameframe, gamedat])
def boardgamegeek(self) -> BoardGameGeek: return BoardGameGeek()
def trending_games(): bgg = BoardGameGeek() hot_items_dict = dict() for item in bgg.hot_items("boardgame"): hot_items_dict[item.id] = item.name return render_template('page.html', hot_items_dict=hot_items_dict)
import csv import time from boardgamegeek import BoardGameGeek import json import diskcache as dc import progressbar cache = dc.Cache('tmp') name = { 'Ludimus': 'Ludimus', } bgg = BoardGameGeek(retries=10) def create_line(pair): id, owners = pair if cache.get(id, default=False): return json.loads(cache[id]) try: game = bgg.game(game_id=id) except: time.sleep(1) try: game = bgg.game(game_id=id) except: return None if game.expansion: