This commit is contained in:
robertem 2015-10-03 18:41:29 +00:00
parent e53b680dd2
commit c8a6f6c209
2 changed files with 1298 additions and 1198 deletions

5
db.py
View File

@ -92,15 +92,16 @@ class Transaction(Base):
user = relationship(User, backref=backref('transactions', order_by=time))
def __init__(self, user, amount=0, description=None, purchase=None):
def __init__(self, user, amount=0, description=None, purchase=None, penalty_ratio=1):
self.user = user
self.amount = amount
self.description = description
self.purchase = purchase
self.penalty_ratio = penalty_ratio
def perform_transaction(self):
self.time = datetime.datetime.now()
self.user.credit -= self.amount
self.user.credit -= self.amount * self.penalty_ratio
if self.purchase:
for entry in self.purchase.entries:
entry.product.stock -= entry.amount

View File

@ -5,9 +5,11 @@ import sqlalchemy
from sqlalchemy.sql import func
from sqlalchemy import desc
import re, sys, os, traceback, signal, readline
from select import select
from helpers import *
import random
from statistikkHelpers import statisticsTextOnly
from math import ceil
random.seed()
exit_commands = ['exit', 'abort', 'quit', 'bye', 'eat flaming death', 'q']
@ -93,7 +95,9 @@ class Menu():
return self.items[i]
def input_str(self, prompt=None, regex=None, length_range=(None,None),
empty_string_is_none=False):
empty_string_is_none=False, timeout=0):
if prompt == None:
prompt = self.prompt
if regex != None:
while True:
result = self.input_str(prompt, length_range=length_range,
@ -119,8 +123,14 @@ class Menu():
print 'Value must have length at most %d' % length_range[1]
else:
return result
if prompt == None:
prompt = self.prompt
if timeout != 0:
print prompt,
rlist, _, _ = select([sys.stdin], [], [], timeout)
if rlist:
s = sys.stdin.readline()
return s
else:
return ''
while True:
try:
result = unicode(raw_input(safe_str(prompt)),
@ -274,7 +284,6 @@ class Menu():
return (result,num)
def search_for_thing(self, search_str, permitted_things=('user','product'),
add_nonexisting=()):
search_fun = {'user': search_user,
@ -369,8 +378,8 @@ class Menu():
def confirm(self, prompt, default=None):
return ConfirmMenu(prompt, default).execute()
def confirm(self, prompt, default=None, timeout=0):
return ConfirmMenu(prompt, default, timeout).execute()
def print_header(self):
print
@ -465,15 +474,16 @@ class Selector(Menu):
class ConfirmMenu(Menu):
def __init__(self, prompt='confirm?', default=None):
def __init__(self, prompt='confirm?', default=None, timeout=0):
Menu.__init__(self, 'question', prompt=prompt,
exit_disallowed_msg='Please answer yes or no')
self.default=default
self.timeout=0
def _execute(self):
options = {True: '[y]/n', False: 'y/[n]', None: 'y/n'}[self.default]
while True:
result = self.input_str('%s (%s) ' % (self.prompt, options))
result = self.input_str('%s (%s) ' % (self.prompt, options), timeout=self.timeout)
result = result.lower()
if result in ['y','yes']:
return True
@ -857,6 +867,47 @@ addition, and you can type 'what' at any time to redisplay it.
When finished, write an empty line to confirm the purchase.
'''
def credit_check(self, user):
"""
:param user:
:type user: User
:rtype: boolean
"""
assert isinstance(user, User)
return user.credit > low_credit_warning_limit
def low_credit_warning(self, user, timeout=False):
assert isinstance(user, User)
print "***********************************************************************"
print "***********************************************************************"
print
print "$$\ $$\ $$$$$$\ $$$$$$$\ $$\ $$\ $$$$$$\ $$\ $$\ $$$$$$\\"
print "$$ | $\ $$ |$$ __$$\ $$ __$$\ $$$\ $$ |\_$$ _|$$$\ $$ |$$ __$$\\"
print "$$ |$$$\ $$ |$$ / $$ |$$ | $$ |$$$$\ $$ | $$ | $$$$\ $$ |$$ / \__|"
print "$$ $$ $$\$$ |$$$$$$$$ |$$$$$$$ |$$ $$\$$ | $$ | $$ $$\$$ |$$ |$$$$\\"
print "$$$$ _$$$$ |$$ __$$ |$$ __$$< $$ \$$$$ | $$ | $$ \$$$$ |$$ |\_$$ |"
print "$$$ / \$$$ |$$ | $$ |$$ | $$ |$$ |\$$$ | $$ | $$ |\$$$ |$$ | $$ |"
print "$$ / \$$ |$$ | $$ |$$ | $$ |$$ | \$$ |$$$$$$\ $$ | \$$ |\$$$$$$ |"
print "\__/ \__|\__| \__|\__| \__|\__| \__|\______|\__| \__| \______/"
print
print "***********************************************************************"
print "***********************************************************************"
print
print "USER %s HAS LOWER CREDIT THAN %d." % (user.name, low_credit_warning_limit)
print "THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH."
print "CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS."
print
print "Do you want to continue with this purchase?"
if timeout:
print "THIS PURCHASE WILL AUTOMATICALLY BE PERFORMED IN 3 MINUTES!"
return self.confirm(prompt=">", default=True, timeout=180)
else:
return self.confirm(prompt=">")
def add_thing_to_purchase(self, thing):
if isinstance(thing, User):
@ -865,6 +916,13 @@ When finished, write an empty line to confirm the purchase.
print 'You are now purchasing as the user anonym.'
print 'You have to put money in the anonym-jar.'
print '--------------------------------------------'
if not self.credit_check(thing):
if self.low_credit_warning(thing, self.superfast_mode ):
Transaction(thing, purchase=self.purchase, penalty_ratio=2)
else:
return False
else:
Transaction(thing, purchase=self.purchase)
elif isinstance(thing, Product):
PurchaseEntry(self.purchase, thing, 1)
@ -1006,6 +1064,46 @@ class AdjustStockMenu(Menu):
print 'The stock is now %d' % (product.stock)
class CleanupStockMenu(Menu):
def __init__(self):
Menu.__init__(self,'Stock Cleanup', uses_db=True)
def _execute(self):
self.print_header()
products = self.session.query(Product).filter(Product.stock != 0).all()
print "Every product in stock will be printed."
print "Entering no value will keep current stock or set it to 0 if it is negative."
print "Entering a value will set current stock to that value."
print "Press enter to begin."
self.pause()
changed_products = []
for product in products:
oldstock = product.stock
product.stock = self.input_int(product.name, (0,10000), default=max(0, oldstock))
self.session.add(product)
if oldstock != product.stock:
changed_products.append((product, oldstock))
try:
self.session.commit()
print 'New stocks are now stored.'
self.pause()
except sqlalchemy.exc.SQLAlchemyError, e:
print 'Could not store stock: %s' % (e)
self.pause()
return
for p in changed_products:
print p[0].name, ".", p[1], "->", p[0].stock
class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one
def __init__(self):
Menu.__init__(self, 'Adjust credit', uses_db=True)
@ -1298,7 +1396,8 @@ main = MainMenu('Dibbler main menu',
EditUserMenu(),
AddProductMenu(),
EditProductMenu(),
AdjustStockMenu(),]),
AdjustStockMenu(),
CleanupStockMenu(),]),
ProductSearchMenu(),
Menu('Statistics',
items=[ProductPopularityMenu(),