【Python】湯婆婆の業務を効率化しよう

はじめに

みなさんは、ジブリの大ヒット映画「千と千尋の神隠し」を知っていますか?
中でも特に有名なシーンは、油屋にやって来た千尋に、湯婆婆が新たに名前をつける場面でしょう。

千尋というのかい?贅沢な名だね。今からお前の名前は千だ。いいかい、千だよ。分かったら返事をするんだ、千!」と言い、千尋から名前を奪って新しく名前をつける湯婆婆

このようにして、湯婆婆は各従業員に名前をつけることが知られています。しかしながら、大規模な営業を行う油屋において、一人ひとりに湯婆婆自身が名前をつけていては、大変なはずです。過酷を極める湯婆婆の業務の一助になりたいと思い、ここに至りました。

イデア

最近 Python というプログラミング言語を勉強し始めたので、これを用いて効率化を図れないかと考えました。従業員一人ひとりを短い名前で管理できるような方法があればさらに良いですね。そこで、以下のように考えました。

  • pandas の DataFrame を用いて、従業員名の管理を行う。
  • 各従業員名が一意に定まり、さらに短い表記を用いたいため、16 進の 0 以上の整数を割り当てる。

挙動

爆速で名前を奪っては与える湯婆婆

このように、PC からの操作によって、湯婆婆の業務を効率化します。また、元の名前と与えた名前は自動で作成された CSV ファイルに格納され、この CSV ファイルは Excel などで開くことができます。

DataFrame には 10 進数で保存しています

実装

以下のように行いました。AutomatedBase16Yubaba (自動化 16 進湯婆婆) クラスを作成して、処理を行っています。
github.com

import os
import time
from math import isnan
import csv
import pandas as pd

class AutomatedBase16Yubaba:
    def __init__(self, input_file_name="aburaya_data.csv") -> None:
        self.columns = ["old_name", "new_name"]
        if not os.path.isfile(input_file_name):
            with open(input_file_name, 'w') as f:
                writer = csv.writer(f)
                writer.writerow(self.columns)
        self._aburaya_data = pd.read_csv(input_file_name, encoding="cp932")

    def explain_operation(self) -> None:
        print("\n湯婆婆: お前の名前をターミナルから標準入力でお入れ。入れ終わったら Enter をお押し\n")

    def get_next_name(self) -> int:
        if isnan(self._aburaya_data["new_name"].max()):
            return 0
        return self._aburaya_data["new_name"].max() + 1
    
    def point_out_extravagant_name(self, new_name, old_name) -> None:
        print("湯婆婆: {0}というのかい?贅沢な名だね。\n湯婆婆: 今からお前の名は{1}だ。いいかい、{1}だよ。\n湯婆婆: 分かったら返事をするんだ、{1}!".format(old_name, hex(new_name)))

    def is_old_name_valid(self, old_name) -> bool:
        space_deleted_name = old_name.replace(" ", "").replace(" ", "").replace("\t", "")
        if not space_deleted_name:
            print("ちゃんと名前をお入れ!")
            return False
        return True
    
    def rename(self, old_name, input_file_name="aburaya_data.csv") -> None:
        new_name = self.get_next_name()
        self.point_out_extravagant_name(new_name, old_name)
        new_clerk = pd.DataFrame({
            "old_name": [old_name],
            "new_name": [new_name],
        })
        self._aburaya_data = pd.concat([self._aburaya_data, new_clerk], ignore_index=True)
        self._aburaya_data.to_csv(input_file_name, index=False, encoding="cp932")
        print("\n湯婆婆: 次の方~")

def main() -> None:
    yubaba = AutomatedBase16Yubaba()
    yubaba.explain_operation()
    while True:
        old_name = input("あなた: ")
        if not yubaba.is_old_name_valid(old_name):
            continue
        yubaba.rename(old_name)
        time.sleep(0.2)

if __name__ == "__main__":
    main()

反省点

本来であれば、Esc キーを押したときなどに、DataFrame をまとめて CSV ファイルに書き込むようにしたかったのですが、Esc などを感知するキー入力と日本語標準入力の相性が悪く、挫折してしまいました (今のところ、とても効率の悪いコードです……)。blessedなどのモジュールを使えば可能なのかもしれませんが、ご存じの方いらっしゃれば、教えて頂けると幸いです。