def test_get_coins_with_invalid_time_span(self): profile = Profile.get_or_none(Profile.username == 'theusername') GameProfile.create(game=1, profile=profile, cash=10000) res = self.client.get( '/game/1/coins?timeSpan=6&sortBy=0&numPerPage=10&pageNum=1', headers={'Authorization': 'Bearer ' + self.token}) self.assertEqual(int(HTTPStatus.BAD_REQUEST), res._status_code)
def register(username: str, password: str): profile = Profile.get_or_none(Profile.username == username) if profile is not None: raise BadRequest('A user with this username already exists') hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode() profile = Profile.create( username=username, hashed_password=hashed, ) global_game = Game.get_or_none(Game.name == 'Global Indefinite') GameProfile.create(game=global_game, profile=profile, cash=global_game.starting_cash) global_game = Game.get_or_none(Game.name == 'Global Timed') GameProfile.create(game=global_game, profile=profile, cash=global_game.starting_cash) send_notification(profile, 'Welcome to Fortune!') send_notification( profile, 'Click the Play button in the menubar on top to create a new game.') send_notification( profile, 'To adjust account options, see achiements, and add friends, click on your username on the top and select Profile' ) return create_auth_token(profile)
def test_user_automatically_joins_new_global_time_game(self): # register user res = self.client.post('/auth/register', data=json.dumps({ 'username': '******', 'password': '******', 'password': '******', }), headers={'Content-Type': 'application/json'}) self.assertEqual(200, res._status_code) game_before_check = Game.get(Game.name == 'Global Timed') game_before_check.ends_at = datetime.utcnow() game_before_check.save() # assert deletes old GameProfile profile = Profile.get_by_id(1) qry = GameProfile.select().join(Game).where( (GameProfile.profile == profile) & (Game.name == 'Global Timed')) self.assertEqual(2, len(profile.game_profiles) ) # should have 2: global timed and indefinite self.assertEqual(1, qry.count()) # just to make sure gp_old = qry.get() check_global_timed_game() # assert creates new GameProfile qry = GameProfile.select().join(Game).where( (GameProfile.profile == profile) & (Game.name == 'Global Timed')) self.assertEqual(1, qry.count()) gp_new = qry.get() # but the ids should not be the same self.assertNotEqual(gp_old.id, gp_new.id)
def add_to_game(profile_id, game): game_profile = GameProfile.select().where(GameProfile.profile == profile_id, GameProfile.game == game.id) if game_profile.count() == 0: GameProfile.create( game=game.id, profile=profile_id, cash=game.starting_cash )
def up(db): with db.atomic(): migrator = PostgresqlMigrator(db) db.bind(MODELS, bind_refs=False, bind_backrefs=False) db.create_tables(MODELS) if Coin.get_or_none(Coin.id == 1) is None: Coin.create(name='Bitcoin', symbol='BTC') Coin.create(name='Ethereum', symbol='ETH') Coin.create(name='Litecoin', symbol='LTC') Coin.create(name='Coin 3', symbol='CO3') Coin.create(name='Coin 4', symbol='CO4') Coin.create(name='Coin 5', symbol='CO5') global_indef = Game.create(name='Global Indefinite', starting_cash=10000.00, shareable_link='INDEF', shareable_code='INDEF', ends_at=None) # insert achievements into database Achievement.create( name="Win", description="Finish in first place in a private game") Achievement.create( name="Double net worth", description="Achieved by doubling your net worth in a game") Achievement.create(name="Identity Crisis", description="Change your username") # insert goals into database Goal.create(name="Entrepreneur", description="Create a private game") all_coins = Coin.select() for coin in all_coins: GameCoin.create(game=global_indef, coin=coin) global_timed = Game.create(name='Global Timed', starting_cash=10000.00, shareable_link='TIMED', shareable_code='TIMED', ends_at=datetime.utcnow() + timedelta(minutes=1)) # CHANGEME for devel purposes, making it 1 min for now GameCoin.create(game=global_timed, coin=Coin.get()) # from auth.services import register hashed = bcrypt.hashpw("admin".encode(), bcrypt.gensalt()).decode() admin = Profile.create(username="******", hashed_password=hashed, is_admin=True) # Required so that admin can still view graphs in the landing page GameProfile.create(profile=admin, game=global_indef, cash=0.0)
def test_buy_coin_without_cash(self): profile = Profile.get_or_none(Profile.username == 'theusername') GameProfile.create(game=1, profile=profile, cash=0) GameCoin.create(game=1, coin=1) Ticker.create(coin=1, price=10, price_change_day_pct=1.1) res = self.client.post( '/game/1/coin', data=json.dumps({ 'coinId': '1', 'coinAmount': '1', }), content_type='application/json', headers={'Authorization': 'Bearer ' + self.token}) self.assertEqual(int(HTTPStatus.BAD_REQUEST), res._status_code)
def sell_coin(coin_id, coin_amount, game_profile): gameProfileCoin = GameProfileCoin.get_or_none( GameProfileCoin.game_profile == game_profile.id, GameProfileCoin.coin == coin_id) if gameProfileCoin is None or gameProfileCoin.coin_amount < coin_amount: raise BadRequest('Not enough of these coins to sell') ticker = Ticker.select().where(Ticker.coin == coin_id).order_by( Ticker.captured_at.desc()) if ticker.count() == 0: raise BadRequest('Coin has no prices') ticker = ticker.get() new_cash = game_profile.cash + (ticker.price * coin_amount) new_coin_amount = gameProfileCoin.coin_amount - coin_amount GameProfileCoin.update(coin_amount=new_coin_amount).where( GameProfileCoin.id == gameProfileCoin.id).execute() GameProfile.update(cash=new_cash).where( GameProfile.id == game_profile.id).execute() return new_coin_amount
def test_get_coins_success(self): profile = Profile.get_or_none(Profile.username == 'theusername') GameProfile.create(game=1, profile=profile, cash=10000) GameCoin.create( game=1, coin=1, ) for coin in Coin.select(): Ticker.create( coin=coin, price=30.0, captured_at=(datetime.utcnow()).isoformat(), price_change_day_pct=1.1, ) res = self.client.get( '/game/1/coins?timeSpan=1&sortBy=0&numPerPage=10&pageNum=1', headers={'Authorization': 'Bearer ' + self.token}) self.assertEqual(int(HTTPStatus.OK), res._status_code)
def create_game(name, starting_cash, shareable_link, shareable_code, ends_at, active_coins, profile): # bounds check, validate if ends_at < datetime.utcnow().replace(tzinfo=pytz.utc): raise BadRequest('Invalid game ending date') if starting_cash <= Decimal(0): raise BadRequest('Starting cash must be positive') game = Game.create( name=name, starting_cash=starting_cash, shareable_link=shareable_link, shareable_code=shareable_code, ends_at=ends_at, ) create_gamecoins_for_game(game, active_coins) GameProfile.create( game=game, profile=profile, cash=game.starting_cash, ) return game
def setUp(self): super().setUp() with db.atomic() as txn: self.game = Game.create( name='Game', starting_cash=10000.00, shareable_link='aaaabbbbccccdddd', shareable_code='aaaa', ends_at=(datetime.utcnow().replace(tzinfo=pytz.utc) + timedelta(days=7)).isoformat()) profile = Profile.create(username='******', hashed_password='******') GameProfile.create(game=self.game, profile=profile, cash=-1.0) Message.create( game=self.game.id, profile=profile.id, content="first message", # use default value for created_on ) self.token = AuthToken.create(profile=profile, token='thevalidtoken').token
def check_global_timed_game(): game = Game.get(Game.shareable_link == 'TIMED') if game.ends_at < datetime.utcnow(): # end global timed game, and start another profiles = [] for game_profile in GameProfile.select().where(GameProfile.game == game): profiles.append(game_profile.profile) send_notification(game_profile.profile, 'The global timed game has expired') game_profile.delete_instance(recursive=True) game.delete_instance(recursive=True) global_timed = Game.create(name='Global Timed', starting_cash=10000.00, shareable_link='TIMED', shareable_code='TIMED', ends_at=datetime.utcnow() + timedelta(minutes=1)) # CHANGEME for devel purposes, making it 1 min for now GameCoin.create(game=global_timed, coin=Coin.get()) for profile in profiles: GameProfile.create( game=global_timed, profile=profile, cash=global_timed.starting_cash )
def buy_coin(coin_id, coin_amount, game_profile): ticker = Ticker.select().where(Ticker.coin == coin_id).order_by( Ticker.captured_at.desc()) if ticker.count() == 0: raise BadRequest('Coin has no prices') ticker = ticker.get() new_cash = game_profile.cash - (ticker.price * coin_amount) if new_cash < 0: raise BadRequest('Not enough cash to buy this coin amount') game_coin = GameCoin.get_or_none(GameCoin.game == game_profile.game, GameCoin.coin == coin_id) if game_coin is None: raise BadRequest('Coin does not exist in this game') gameProfileCoin = GameProfileCoin.get_or_none( GameProfileCoin.game_profile == game_profile.id, GameProfileCoin.coin == coin_id) if gameProfileCoin is None: GameProfileCoin.create(game_profile=game_profile.id, coin=coin_id, coin_amount=coin_amount) rows = GameProfile.update(cash=new_cash).where( GameProfile == game_profile).execute() if rows == 0: raise BadRequest('Money could not be removed from your account') return coin_amount else: new_coin_amount = gameProfileCoin.coin_amount + coin_amount rows = GameProfile.update(cash=new_cash).where( GameProfile == game_profile).execute() if rows == 0: raise BadRequest('Money could not be removed from your account') GameProfileCoin.update(coin_amount=new_coin_amount).where( GameProfileCoin.id == gameProfileCoin.id).execute() return new_coin_amount
def test_liquefy_success(self): profile = Profile.get_or_none(Profile.username == 'theusername') game_profile = GameProfile.create(game=1, profile=profile, cash=0) GameCoin.create(game=1, coin=1) GameProfileCoin.create(game_profile=game_profile, coin=1, coin_amount=2) Ticker.create( coin=1, price=10, captured_at=(datetime.utcnow()).isoformat(), price_change_day_pct=1.1, ) res = self.client.delete( '/game/1/coins', headers={'Authorization': 'Bearer ' + self.token}) self.assertEqual(int(HTTPStatus.OK), res._status_code)
def get_net_worth_by_game_profile_id(game_profile_id): gameProfile = GameProfile.get_or_none(GameProfile.id == game_profile_id) if not gameProfile: raise BadRequest('User not in game') netWorth = gameProfile.cash gameProfileCoins = get_game_profile_coins_by_game_profile_id( game_profile_id) for gameProfileCoin in gameProfileCoins: ticker = Ticker.select().where( Ticker.coin == gameProfileCoin.coin).order_by( Ticker.captured_at.desc()) if ticker.count() == 0: raise BadRequest('One coin did not have prices') ticker = ticker.get() if not ticker: raise BadRequest('One coin did not exist') netWorth += ticker.price * gameProfileCoin.coin_amount return netWorth
def test_sell_coin_success(self): profile = Profile.get_or_none(Profile.username == 'theusername') game_profile = GameProfile.create(game=1, profile=profile, cash=0) GameCoin.create(game=1, coin=1) GameProfileCoin.create(game_profile=game_profile, coin=1, coin_amount=2) Ticker.create( coin=1, price=10, captured_at=(datetime.utcnow()).isoformat(), price_change_day_pct=1.1, ) res = self.client.post( '/game/1/coin', data=json.dumps({ 'coinId': '1', 'coinAmount': '-1', }), content_type='application/json', headers={'Authorization': 'Bearer ' + self.token}) self.assertEqual(int(HTTPStatus.OK), res._status_code)
def get_players_in_a_game(game_id: int): game_profiles = GameProfile.select( GameProfile, Profile).join(Profile).where(GameProfile.game == game_id).execute() return [gp.profile for gp in game_profiles]
def get_game_profile_by_game_id(game_id): return GameProfile.selcet(profile).where(GameProfile.game == game_id)
def get_game_profile_by_profile_id_and_game_id(profile_id, game_id): game_profile = GameProfile.get_or_none(GameProfile.game == game_id, GameProfile.profile == profile_id) if not game_profile: raise BadRequest('User not in game') return game_profile
def test_joining_game_more_than_once_is_idempotent(self): game = Game.get(Game.name == 'Global Timed') before = GameProfile.select().count() self.client.get(f'/join?code={game.shareable_code}') after = GameProfile.select().count() self.assertEqual(before, after)