Nokiaに関係ある事ない事をつらつらと。
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
705NKでプログラミング その13
前回は、オブジェクト指向の特徴の一つであるクラスの扱い方について簡単なスクリプトを書いてみました。今回は、それを踏まえたうえで、以前作ったSoftBankのパケット計算スクリプトをオブジェクト指向で書き換えてみることにします。
と言うことで、今回書き上げたスクリプトがこんな感じです。

import appuifw
class Packet:
    def GetPacketCharge(self, packet, acc = 0):
        raise NotImplementedError

class PacketNoPlan(Packet):
    call_plan = 0
    packet_plan = unicode("パケ割引無し","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        self.charge = packet * 0.2
        return PacketNoPlan.call_plan, PacketNoPlan.packet_plan, int(self.charge)

class PacketShihoudai(Packet):
    call_plan = 0
    packet_plan = unicode("パケットし放題","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if acc == 0:
            if packet <= 12250:
                self.charge = 980
            elif packet >= 52500:
                self.charge = 4200
            else:
                self.charge = packet * 0.08
        elif acc == 1:
            if packet <= 12250:
                self.charge = 980
            elif packet >= 71250:
                self.charge = 5700
            else:
                self.charge = packet * 0.08
        elif acc == 2:
            if packet <= 12250:
                self.charge = 980
            elif packet >= 122500:
                self.charge = 9800
            else:
                self.charge = packet * 0.08
        else:
            self.charge = 980 + packet * 0.2
        return PacketShihoudai.call_plan, PacketShihoudai.packet_plan, int(self.charge)

class PacketTeigakuLight(Packet):
    call_plan = 1
    packet_plan = unicode("パケ定額ライト","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if acc == 0:
            if packet <= 12500:
                self.charge = 1000
            elif packet >= 52500:
                self.charge = 4200
            else:
                self.charge = packet * 0.08
        elif acc == 1:
            if packet <= 12500:
                self.charge = 1000
            elif packet >= 71250:
                self.charge = 5700
            else:
                self.charge = packet * 0.08
        else:
            self.charge = 980 + packet * 0.08
        return PacketTeigakuLight.call_plan, PacketTeigakuLight.packet_plan, int(self.charge)

class PacketTeigakuOrange(Packet):
    call_plan = 1
    packet_plan = unicode("パケット定額(O)","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if acc == 0:
            if packet <= 40000:
                self.charge = 2000
            elif packet >= 84000:
                self.charge = 4200
            else:
                self.charge = packet * 0.05
        elif acc == 1:
            if packet <= 40000:
                self.charge = 2000
            elif packet >= 114000:
                self.charge = 5700
            else:
                self.charge = packet * 0.05
        else:
            self.charge = 2000 + packet * 0.05
        return PacketTeigakuOrange.call_plan, PacketTeigakuOrange.packet_plan, int(self.charge)

class PacketTeigakuBlue(Packet):
    call_plan = 2
    packet_plan = unicode("パケット定額(B)","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if acc == 0:
            self.charge = 3900
        else:
            self.charge = 3900 + packet * 0.02
        return PacketTeigakuBlue.call_plan, PacketTeigakuBlue.packet_plan, int(self.charge)

class PacketTeigakuFull(Packet):
    call_plan = 2
    packet_plan = unicode("パケット定額フル","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if acc == 0 or acc == 1:
            self.charge = 5700
        else:
            self.charge = 5700+ packet * 0.02
        return PacketTeigakuFull.call_plan, PacketTeigakuFull.packet_plan, int(self.charge)

class PacketTeigakuBiz(Packet):
    call_plan = 2
    packet_plan = unicode("パケット定額Biz","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if acc == 0 or acc == 2:
            self.charge = 5700
        else:
            self.charge = 5700 + packet * 0.02
        return PacketTeigakuBiz.call_plan, PacketTeigakuBiz.packet_plan, int(self.charge)

class PacketWaribiki10(Packet):
    call_plan = 2
    packet_plan = unicode("パケット10","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if packet <= 10000:
            self.charge = 1000
        else:
            self.charge = packet * 0.1
        return PacketWaribiki10.call_plan, PacketWaribiki10.packet_plan, int(self.charge)

class PacketWaribiki30(Packet):
    call_plan = 2
    packet_plan = unicode("パケット30","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if packet <= 60000:
            self.charge = 3000
        else:
            self.charge = packet * 0.05
        return PacketWaribiki30.call_plan, PacketWaribiki30.packet_plan, int(self.charge)

class PacketWaribiki60(Packet):
    call_plan = 2
    packet_plan = unicode("パケット60","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if packet <= 300000:
            self.charge = 6000
        else:
            self.charge = packet * 0.02
        return PacketWaribiki60.call_plan, PacketWaribiki60.packet_plan, int(self.charge)

class PacketWaribiki90(Packet):
    call_plan = 2
    packet_plan = unicode("パケット90","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        if packet <= 600000:
            self.charge = 9000
        else:
            self.charge = packet * 0.015
        return PacketWaribiki90.call_plan, PacketWaribiki90.packet_plan, int(self.charge)

class PacketSelector:
    def __init__(self):
        self.noplan = PacketNoPlan()
        self.shihoudai = PacketShihoudai()
        self.teigaku_l = PacketTeigakuLight()
        self.teigaku_o = PacketTeigakuOrange()
        self.teigaku_b = PacketTeigakuBlue()
        self.teigaku_ful = PacketTeigakuFull()
        self.teigaku_biz = PacketTeigakuBiz()
        self.waribiki_10 = PacketWaribiki10()
        self.waribiki_30 = PacketWaribiki30()
        self.waribiki_60 = PacketWaribiki60()
        self.waribiki_90 = PacketWaribiki90()
        self.master = []

    def AllPacketCharge(self, packet, acc):
        self.master.append(self.noplan.GetPacketCharge(packet, acc))
        self.master.append(self.shihoudai.GetPacketCharge(packet, acc))
        self.master.append(self.teigaku_l.GetPacketCharge(packet, acc))
        self.master.append(self.teigaku_o.GetPacketCharge(packet, acc))
        self.master.append(self.teigaku_b.GetPacketCharge(packet, acc))
        self.master.append(self.teigaku_ful.GetPacketCharge(packet, acc))
        self.master.append(self.teigaku_biz.GetPacketCharge(packet, acc))
        self.master.append(self.waribiki_10.GetPacketCharge(packet, acc))
        self.master.append(self.waribiki_30.GetPacketCharge(packet, acc))
        self.master.append(self.waribiki_60.GetPacketCharge(packet, acc))
        self.master.append(self.waribiki_90.GetPacketCharge(packet, acc))
        self.master.append((0,0,0))
        return self.master

nbsp;   def BestPacketPlan(self, packet, callplan, access):
        self.master = self.AllPacketCharge(packet, access)
        self.i = 0
        self.temp = 0
        self.charge = self.master[0]
        while self.master[self.i][2]:
            if callplan == self.master[self.i][0] or self.master[self.i][0] == 0:
                self.temp = self.master[self.i]
                if self.temp[2] < self.charge[2]:
                    self.charge = self.temp
            elif callplan == 3:
                self.temp = self.master[self.i]
                if self.temp[2] < self.charge[2]:
                    self.charge = self.temp
            self.i = self.i+1
        self.cp, self.pp, self.ch = self.charge
        return self.pp, self.ch

    def ByteAndPacket(self, unit, data):
        if unit == 0:
           self.packet = data
           self.byte = data * 128 / 1024
        else:
           self.packet = data * 1024 / 128
           self.byte = data
        return self.packet, self.byte

class FormCreator:
    def __init__(self):
        self.savedata = False

        self.choice1 = [unicode('ホワイトプラン','utf-8'),
                        unicode('オレンジプラン','utf-8'),
                        unicode('ブループラン','utf-8'),
                        unicode('全てのプラン','utf-8')]

        self.choice2 = [unicode('携帯ブラウザのみ','utf-8'),
                        unicode('PCサイトブラウザ','utf-8'),
                        unicode('PCサイトダイレクト','utf-8'),
                        unicode('AI接続','utf-8')]

        self.choice3 = [unicode('パケット(pkt)','utf-8'),
                        unicode('バイト(KB)','utf-8')]

        self.field = [(unicode('通話プラン','utf-8'),'combo',(self.choice1,0)),
                      (unicode('接続形態','utf-8'),'combo',(self.choice2,0)),
                      (unicode('データ単位','utf-8'),'combo',(self.choice3,0)),
                      (unicode('送受信データ量','utf-8'),'number',0)]

    def SetInputForm(self):
        self.flags = appuifw.FFormEditModeOnly+appuifw.FFormDoubleSpaced
        self.form = appuifw.Form(self.field, self.flags)
        self.form.save_hook = self.MarkSaved
        self.form.execute()
        return self.form[0][2][1], self.form[1][2][1], self.form[2][2][1], self.form[3][2]

    def SetResultForm(self, packetplan, byte, packet, charge):
        appuifw.query(unicode("最適プラン:","utf-8") + "\n" + packetplan + "\n" + str(byte) + "KB" + "\n" + str(packet) + "pkt" + "\n" + str(charge) + unicode("円","utf-8"), "query")

    def MarkSaved(self, hook):
        self.savedata = hook
        return True

    def CheckSaveData(self):
        return self.savedata

if __name__ == "__main__":
    myForm = FormCreator()
    make = PacketSelector()

    callplan, access, unit, data = myForm.SetInputForm()
    packet, byte = make.ByteAndPacket(unit, data)
    packetplan, charge = make.BestPacketPlan(packet, callplan, access)
    if myForm.CheckSaveData():
        myForm.SetResultForm(packetplan, byte, packet, charge)


前回とは異なり、モジュールとメインプログラムをまた一緒にしてしまったので、結構長くなってしまいました。Blogで紹介するのはこのくらいが限界でしょうか…。それはさておき、スクリプトの大半がクラスの定義で、実際の実行部分は最後のほんの数行しかありません。おかげでスクリプト自体はかなりすっきりと記述できたと思います。

まずクラスですが、大きく分けると、パケット計算クラス、最適なプランを選択するクラス、Formを作成するクラスの3つに分かれます。さらにパケット計算クラスは、それぞれ各パケットプランに応じた子クラスに継承されています。行の始めの方にある

class Packet:
    def GetPacketCharge(self, packet, acc = 0):
        raise NotImplementedError


の部分が親クラスです。このPacketというクラスでは、GetPacketChargeというファンクションが定義されているものの、実装はされていません。実際GetPacketChargeにどんな処理をさせるかは、こんな感じで

class PacketNoPlan(Packet):
    call_plan = 0
    packet_plan = unicode("パケ割引無し","utf-8")
    def GetPacketCharge(self, packet, acc = 0):
        self.charge = packet * 0.2
        return PacketNoPlan.call_plan, PacketNoPlan.packet_plan, int(self.charge)


継承先の子クラスで実装させています。ちなみにPacketNoPlanと言うのがクラス名で、括弧の中にPacketと記述することで、PacketNoPlanクラスがPacketクラスの子クラスだということを明示しています。Javaとかだと、この辺りはインターフェースを利用すれば良いのでしょうが、Pythonにはその概念が無いので、クラス継承を使って擬似的に表現してみました。まぁ回りくどいって言えば回りくどいんですが、こうすることによって、Packetという親クラスを持つ子クラスは、GetPacketChargeというファンクションを必ず実装する、ということが一目で分かるので、スクリプトの見通しが良くなるんじゃないかと。

PacketSelectorクラスは最適なパケットプランを選択するクラスで、このスクリプトのキモとなる部分です。ここを見ると、パケット計算用のクラスは各パケットプラン毎にクラスを分けるのではなく、全てを一つのクラスにしてしまって計算部分はファンクションにしてしまえばスッキリしたかなぁ、と思います。と言うのも、AllPacketChargeファンクションは、各パケットプラン毎にインスタンスを作成しなければならないので、かなり力技に見えてしまいます(苦笑)。forループとか使ってやれば、もう少しスマートになるのかな?それでも、パケットプランの追加があったとしても、新たなパケットプランのクラスを記述して、ここにそのプランを追加するだけで、新たなプランにも対応することが可能となりますので、柔軟性は高いのではないかと思います。BestPacketPlanファンクションは、前回書いたスクリプトとほぼ変わっていないです。

FormCreatorクラスは表示用フォームを作成するクラスです。今まではappuifwのquery()ファンクションを使用していたのですが、Formタイプの実装方法が分かってきたので、今回はそちらを使うことにします。おかげで1枚の入力フォームで、必要な情報を全て入力することができるようになりました。

では実機で動かしてみることにします。

nokimani071124_001.jpg

入力フォームです。今までは項目ごとにフォームを開いていましたが、今回のスクリプトでは、この1枚で全ての情報を入力することができます。

nokimani071124_002.jpg

項目を選択して決定キーを押すと、選択リストが表示されます。

nokimani071124_003.jpg

今回は、「全てのプラン」「携帯ブラウザのみ」「バイト」「10MB」で最適パケット料金を比較することにします。

nokimani071124_004.jpg

オプションから「保存」を選択し、「戻る」を押すと…

nokimani071124_005.jpg

最適プランが表示されます。

まだイマイチフォームの機能を把握していません。特にフォームから別フォームに飛ぶ方法が良く分かっていないので、操作性がちょっと悪いです。ただスクリプト自体はオブジェクト指向を心がけるようになってからは、見やすくなったと思います。スクリプトの開発についても、クラスなどを使うことによってだいぶ見通しが良くなったので、手が加えやすくなりました。次回は何をやるか決めていませんが、もう少し実用的なスクリプトを製作したいです。とは言え、スクリプトのアイデアがなかなか思い浮かびませんねぇ(苦笑)。

スポンサーサイト

テーマ:Nokia - ジャンル:携帯電話・PHS

コメント
この記事へのコメント
コメントを投稿する
URL:
Comment:
Pass:
秘密: 管理者にだけ表示を許可する
 
トラックバック
この記事のトラックバックURL
この記事へのトラックバック
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。