計算内容本体


In [ ]:
import sys
from datetime import datetime

def calc_time_delta(start_time, end_time):
    """ 時刻間の差を計算する汎用関数 """
    t_start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    t_end_time = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")

    delta = t_end_time - t_start_time
    duration = int(delta.total_seconds())
    
    return duration

def calc_schatz_charge(start_time, end_time):
    """ 30分500円の席料を計算する。5分経過以降に次の席料が発生するとみなす """
    duration = calc_time_delta(start_time, end_time)
    duration_minutes = duration / 60
    charge_times = duration_minutes / 30
    extra_minutes = duration_minutes % 30
    
    # 5分経過後から次のチャージが発生
    if extra_minutes > 5:
        charge_times = charge_times + 1
    
    # チャージ料がマイナスの場合はエラーを出す
    if charge_times < 0:
        sys.stderr.write('[Warn] end_time is earlier than start_time.\n \
            start_time: %s end_time: %s\n' % (start_time, end_time) )
        
    charge = charge_times * 500
    return charge

In [ ]:
def calc_dishes_cost(tarif, order_list=[]):
    """ メニュー注文分の計算 """
    total_cost = 0
    for i in order_list:
        cost = tarif.get(i,0)
        if cost == 0:
            sys.stderr.write('[Warn] %s does not exist in tarif\n' % i)
        total_cost = total_cost + cost
    
    return total_cost

In [ ]:
def calc_schatz_total_cost(checkin_time='12:00:00', checkout_time=None, tarif={}, order_list=[]):
    """ 支払額計算。設定した退館時刻もしくは現時点の支払額と閉館までいた場合の支払額を返す"""
    today=datetime.now().strftime("%Y-%m-%d")
    
    if len(checkin_time.split(':')) == 2:
        checkin_time = checkin_time + ':00'
        
    start_time='%s %s' % (today, checkin_time)
    
    if checkout_time is None:
        end_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    elif len(checkout_time.split(':')) == 2:
        checkout_time = checkout_time + ':00'
        end_time='%s %s' % (today, checkout_time)
    else:
        end_time='%s %s' % (today, checkout_time)

    charge = calc_schatz_charge(start_time, end_time)
    dishes_cost = calc_dishes_cost(tarif, order_list)

    total_cost = charge + dishes_cost
    payment = total_cost * TAX_RATE
    close_at = '22:00:00'
    last_time = '%s %s' % (today, close_at)

    total_cost_max = calc_schatz_charge(start_time, last_time) + dishes_cost

    payment_max = total_cost_max * TAX_RATE

    return charge, dishes_cost, payment, payment_max

タリフ定義


In [ ]:
#  消費税率
global TAX_RATE
TAX_RATE = 1.08

# 個別注文メニューの価格を定義
tarif = {u'スープ':500,u'パンプリン':300, u'おかし':300}
sp_menu_tarif = {u'水ようかん':400,u'夏野菜カレー':800,u'レモネード':300}
tarif.update(sp_menu_tarif)

実行してみる


In [ ]:
checkin_time='12:55:00'
checkout_time='17:55:00'

order_list=[u'水ようかん', u'夏野菜カレー', u'レモネード',u'スープ',u'パンプリン']

# Default: checkin_time = '12:00:00' and checkout_time = now in '%H:%M:%S'
charge, dishes_cost, payment, payment_max = calc_schatz_total_cost()

print 'Charge: %s, Dishes: %s, Payment: %s, Max Estimate: %s\n' % (charge, dishes_cost, int(payment), int(payment_max))
charge, dishes_cost, payment, payment_max = calc_schatz_total_cost(
                                                            checkout_time=checkout_time,
                                                            tarif=tarif,
                                                            order_list=order_list)
print 'Charge: %s, Dishes: %s, Payment: %s, Max Estimate: %s\n' % (charge, dishes_cost, int(payment), int(payment_max))

画面からの入力

画面からの入力を受け付ける関数


In [ ]:
# 【参考】https://plus.google.com/115875830338788300419/posts/cJFqX2Rpvzn
import IPython.core.display

def ipynb_input(varname, prompt='', default=''):
    """Prompt user for input and assign string val to given variable name."""
    js_code = ("""
        var value = prompt("{prompt}","{default}");
        var py_code = "{varname} = '" + value + "'";
        IPython.notebook.kernel.execute(py_code);
    """).format(prompt=prompt, varname=varname, default=default)
    return IPython.core.display.Javascript(js_code)

データ入力がない場合はデフォルト値を入力


In [ ]:
if 'chekin_time' not in globals():
    checkin_time= '12:00' 
if 'order_text' not in globals():
    order_text = ''

プロンプト


In [ ]:
ipynb_input(varname='checkin_time', prompt='入館時刻を入力してください。例: 12:15', default=checkin_time)

In [ ]:
# 現在時刻を取得
checkout_time=datetime.now().strftime("%H:%M")

In [ ]:
ipynb_input(varname='checkout_time', prompt='退館時刻を入力してください。例: 21:15', default=checkout_time)

In [ ]:
ipynb_input(varname='order_text',
                        prompt='注文したものをカンマ区切りで入力してください。同じものを複数回注文した場合は、その数だけ入力してください。\\n'
                        '例:夏野菜カレー,パンプリン',
                        default=order_text
                    )

結果出力

表示用関数


In [ ]:
from collections import Counter

def print_order(order_list):
    """ オーダーしたものと個数、小計を出力 """
    counter = Counter(order_list)
    print 'オーダー:'
    for menu, cnt in counter.most_common():
        price = tarif.get(menu,0)
        print '\t%s: %s個 = %s円' % (menu.encode('utf-8'), cnt, price * cnt)

プロット用関数


In [619]:
# http://bicycle1885.hatenablog.com/entry/2014/02/14/023734
# http://matplotlib.org/gallery.html
# http://symfoware.blog68.fc2.com/blog-entry-1417.html
def calc_max_range(checkin_time, close_time='22:00'):
    today=datetime.now().strftime("%Y-%m-%d")
    
    if len(checkin_time.split(':')) == 2:
        checkin_time = checkin_time + ':00'
        
    start_time='%s %s' % (today, checkin_time)
    
    if len(close_time.split(':')) == 2:
        close_time = close_time + ':00'
        end_time='%s %s' % (today, close_time)
    else:
        end_time='%s %s' % (today, close_time)

    duration = calc_time_delta(start_time, end_time)
    range = (duration / 60 /30) + 1
    
    return range

from datetime import timedelta
def mkdate(checkin_time, i):
    if len(checkin_time.split(':')) == 2:
        checkin_time = checkin_time + ':00'
        
    start_time='%s %s' % (today, checkin_time)
    t_start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    delta = timedelta(seconds=i*60*30)
    
    t_label_time = t_start_time + delta
    label_time = datetime.strftime(t_label_time, "%H:%M:%S")
    return label_time

def plot_schatz_cost(charge, dishes_cost, payment, payment_max):
    max_range = calc_max_range(checkin_time)
    x_range = range(max_range)
    x_labels = [ mkdate(checkin_time, i) for i in x_range]
    cost_y = [ (i * 500 + dishes_cost) * TAX_RATE for i in x_range]

    plot(x_range,cost_y)
    xticks(x_range, x_labels, rotation='vertical')

    x_point = charge / 500
    from matplotlib.font_manager import FontProperties
    fp = FontProperties(fname='/System/Library/Fonts/ヒラギノ角ゴ ProN W3.otf')
    annotate(
            u'メニューオーダー分: %s円' % dishes_cost,
            xy=(0, dishes_cost), arrowprops=dict(arrowstyle='->'), xytext=(3, 500),fontproperties=fp)
    annotate(
            u'現時点のお会計: %.0f円 (in TAX)'%(payment),
            xy=(x_point, payment), arrowprops=dict(arrowstyle='->'), xytext=(5, 2000),fontproperties=fp)
    l = plt.axhline(y=payment,linewidth=1, color='r')

お会計


In [625]:
# 入力された注文をリストに変換
u_order_text = order_text.decode('utf-8')
u_order_text = u_order_text.replace(' ','')
order_list = u_order_text.split(',')

# 計算結果取得
charge, dishes_cost, payment, payment_max = calc_schatz_total_cost(checkin_time, checkout_time, tarif=tarif, order_list=order_list)
#charge, dishes_cost, payment, payment_max = calc_schatz_total_cost(checkin_time, tarif=tarif, order_list=order_list)

# 結果出力
print 'Checkin Time: %s' % checkin_time
print 'Checkout Time: %s\n' % checkout_time

print '滞在時間: %s分, 席料: %s円' % ((charge / 500)*30, charge)
print_order(order_list)

print ''
print '現時点のお会計: %.0f円 (in TAX)'%(payment)
print 'このまま閉館までいた場合のお会計: %.0f円 (in TAX)'%(payment_max)

#plot_schatz_cost(charge, dishes_cost, payment, payment_max)
with xkcd():
    plot_schatz_cost(charge, dishes_cost, payment, payment_max)


Checkin Time: 12:55:00
Checkout Time: 17:55:00

滞在時間: 300分, 席料: 5000円
オーダー:
	夏野菜カレー: 1個 = 800円
	パンプリン: 1個 = 300円

現時点のお会計: 6588円 (in TAX)
このまま閉館までいた場合のお会計: 10908円 (in TAX)

In [617]:



Out[617]:
<matplotlib.rc_context at 0x113a37c50>

In [ ]: