Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Charge for S-tier cards #179

Merged
merged 5 commits into from
Jul 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kaori/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def _fn(d) -> str:
if k == 'text' and type(v) == str:
text.append(v)

if type(v) == dict:
if type(v) == dict or type(v) == list:
text.append(_fn(v))

return "\n".join(text)
Expand Down
37 changes: 33 additions & 4 deletions kaori/plugins/gacha/commands/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Tuple, List, Optional, Union
from uuid import uuid4

from kaori.plugins.kkreds import get_kkred_balance, KKredsTransaction

from kaori.support.slacktools.message import extract_mentions
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
Expand Down Expand Up @@ -130,7 +132,8 @@ async def handle(message: SlackMessage, bot: SlackAdapter, db: DB, file_uploader

card, replies = next_card_creation_step(card=card,
user_input=user_input,
session=session)
session=session,
kaori_user=User.get_by_slack_id(session, bot.id))

refresh_card_preview(card, bot)

Expand Down Expand Up @@ -181,15 +184,37 @@ def initialize_card(message: SlackMessage, user: User) -> Card:
return card


def charge_for_card(card: Card, session: Session, kaori_user: User) -> Tuple[bool, str]:
if card.price() == 0:
return True, 'Card is free!'

# TODO: any time we are dealing with balance we should acquire a lock. Too lazy to do that rn. too bad!
balance = get_kkred_balance(user=card.owner_user, session=session)

if balance < card.price():
return False, 'You do not have enough kkreds to pay for this card.'

transaction = KKredsTransaction(from_user=card.owner_user,
to_user=kaori_user,
amount=card.price())

session.add(transaction)
session.commit()

return True, 'Successfully paid for card!'


# This is essentially a state machine.
# Right now this is spaghetti code for prototyping purposes.
# TODO: Once the functionality is totally built out we can break this into multiple functions etc.
# BODY: Oh god break this into some functions please, this should be a dispatcher or something.
# This function is now officially out of control
# TODO: AGAIN, this is wayyyy out of control. It's got good test coverage but FFS
# TODO: This function is out of control and needs to be broken up. too bad!
def next_card_creation_step(card: Card,
session: Session,
user_input: str) -> Tuple[Card, List[Union[str, dict]]]:
user_input: str,
kaori_user: User) -> Tuple[Card, List[Union[str, dict]]]:
replies = []

if user_input == 'quit':
Expand Down Expand Up @@ -252,9 +277,13 @@ def next_card_creation_step(card: Card,
replies.append('Need to specify a rarity')
elif cursor == 'set_confirm_price':
# todo: make utility for capturing english affirmatives
if re.search(r'yes+|yep+|ye+|yeah+', user_input, re.IGNORECASE):
if re.search(r'yes+|yep+|ye+|yeah+|pay|try again', user_input, re.IGNORECASE):
replies.append(':+1:')
cursor = 'do_stats_roll'
success, reason = charge_for_card(card=card, session=session, kaori_user=kaori_user)
if success:
cursor = 'do_stats_roll'
else:
replies.append(reason + ' To attempt payment again: send `@kaori try again`')
# todo: make utility for capturing english negatives
elif re.search(r'no+|nope+|', user_input, re.IGNORECASE):
replies.append("Okay. If you change your mind:\n"
Expand Down
41 changes: 38 additions & 3 deletions kaori/plugins/gacha/commands/test_creation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from secrets import token_hex
from time import time
from unittest.mock import Mock, MagicMock
from uuid import uuid4

from slackclient import SlackClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import sessionmaker, Session

import kaori.plugins.gacha as gacha_plugin
from kaori import test_config
Expand All @@ -14,7 +15,7 @@
from kaori.plugins.users import User
from kaori.skills import DB, LocalFileUploader
from kaori.support import Kaori
from .creation import user_extract_rarity
from .creation import user_extract_rarity, charge_for_card
from ..skills import CardBattler


Expand Down Expand Up @@ -67,7 +68,7 @@ def test_card_creation_state_happy(make_fake_user, grant_kkreds):
slack_id = u.slack_id
user_id = u.id

# grant_kkreds(u, 1e10)
grant_kkreds(u, 1e10)

def handle(msg):
k.handle('slack', msg)
Expand Down Expand Up @@ -136,3 +137,37 @@ def user_message(**kwargs):
session.refresh(card)
assert card.published is True
assert card.creation_cursor == 'done'


def test_charge_for_card(make_fake_user, grant_kkreds, db_session: Session):
kaori = make_fake_user()
fake_user = make_fake_user()
db_session.add(kaori)
db_session.add(fake_user)
uniq2 = str(uuid4())
card_a = Card(name=uniq2,
slug=uniq2,
owner=fake_user.id,
published=False,
rarity=500,
primary_nature='stupid',
secondary_nature='clown',
creation_thread_channel=f'ch-{uniq2}',
creation_thread_ts=f'ts-{uniq2}')

db_session.add(card_a)
db_session.commit()

success, reason = charge_for_card(card=card_a, session=db_session, kaori_user=kaori)

assert success is False
assert 'do not have enough kkreds' in reason

db_session.expunge(fake_user)
grant_kkreds(fake_user, 1e10)
db_session.add(fake_user)

success, reason = charge_for_card(card=card_a, session=db_session, kaori_user=kaori)

assert 'paid for card' in reason
assert success is True
13 changes: 9 additions & 4 deletions kaori/plugins/gacha/models/Card.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Card(Base):

# creation related
owner = sa.Column('owner', sa.Integer, sa.ForeignKey('users.id'), nullable=False)
owner_user = sa.orm.relationship('User')
published = sa.Column('published', sa.Boolean, nullable=False, default=False)
creation_thread_channel = sa.Column('creation_thread_channel', sa.Text, nullable=False)
creation_thread_ts = sa.Column('creation_thread_ts', sa.Text, nullable=False, unique=True)
Expand Down Expand Up @@ -108,10 +109,14 @@ def sluggify_name(name: str) -> str:
def rarity_prices() -> Dict[RarityName, int]:
return {
RarityName.S: 1000,
RarityName.A: 403,
RarityName.B: 181,
RarityName.C: 81,
RarityName.F: 7,
RarityName.A: 0,
# RarityName.A: 403,
RarityName.B: 0,
# RarityName.B: 181,
RarityName.C: 0,
# RarityName.C: 81,
RarityName.F: 0,
# RarityName.F: 7,
}

def price(self) -> int:
Expand Down
13 changes: 12 additions & 1 deletion kaori/plugins/gacha/test_tui.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import re
from unittest.mock import MagicMock

from .engine import NatureName
from .tui import get_nature_examples, card_stats_blocks
from .tui import get_nature_examples, card_stats_blocks, price_blocks, create_are_you_sure_blocks


def test_nature_examples():
Expand All @@ -13,3 +14,13 @@ def test_nature_examples():
def test_stats_blocks(find_nested_text):
assert 'total of 1 card ' in find_nested_text(card_stats_blocks(card_total=1))
assert 'total of 2 cards ' in find_nested_text(card_stats_blocks(card_total=2))


def test_price(find_nested_text):
assert '*S:* 1,000 kkreds' in find_nested_text(price_blocks())
assert '*F:* _FREE_' in find_nested_text(price_blocks())
card = MagicMock()
card.price.return_value = 1000
assert 'will cost you 1,000 kkreds' in find_nested_text(create_are_you_sure_blocks(card))
card.price.return_value = 0
assert 'will cost you 0 kkreds' in find_nested_text(create_are_you_sure_blocks(card))
28 changes: 11 additions & 17 deletions kaori/plugins/gacha/tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def render_stats_blocks(card: Card) -> List[dict]:
"type": "mrkdwn",
"text": f'*{title}*\n`{text[0]:<4} {"(" + text[1] + ")":>11}`'
} for title, text in {
'HP': (eng.max_hp, f'{card.stupid} stupid'),
'HP': (eng.max_hp, f'{card.stupid} stupid'),
'EVA': (_percent(eng.evasion), f'{card.baby} baby'),
'AMR': (eng.armor, f'{card.clown} clown'),
'DMG': (eng.dmg, f'{card.horny} horny'),
Expand Down Expand Up @@ -113,8 +113,6 @@ def instructions_blocks(bot_name: str) -> List[dict]:
f"• To avoid a fiasco *I will only respond to direct mentions* and I will only respond to you.",
f"• *To quit card creation* just send `{bot_name} quit`",
f"• *To start over* just send `{bot_name} start over`",
# TODO: beta notice
"• *Beta Notice:* cards are currently free to create.",
]

return [
Expand All @@ -133,24 +131,21 @@ def instructions_blocks(bot_name: str) -> List[dict]:
"text": '\n'.join(bullets)
}
},
# TODO: beta notice
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Beta Notice:* cards are currently free to create. They might be cleared from the database "
"at some point when the beta period ends."
},
},
]


def price_string(rank, price):
if price == 0:
return f"*{rank}:* _FREE_"

return f"*{rank}:* {price:,} kkreds"


def price_blocks():
prices = [
{
"type": "mrkdwn",
# "text": f"*{rank}:* {price} kkreds",
"text": f"*{rank}:* ~{price} kkreds~ _free_",
"text": price_string(rank=rank, price=price)
} for rank, price in Card.rarity_prices().items()
]
return [
Expand Down Expand Up @@ -294,14 +289,13 @@ def battle_blocks(attacker: Card, defender: Card, battle_url: str):


def create_are_you_sure_blocks(card):
cost = f"This card will cost you {card.price():,} kkreds to create"
return [
{
"type": "section",
"text": {
"type": "mrkdwn",
# TODO beta notice
"text": f"~This card will cost {card.price()} kkreds~ "
"Cards are free to create during the beta!\n"
"text": f"{cost} "
"*Are you sure you want to create this card?*\n"
"(ex. `@kaori yes`)"
},
Expand Down