Php USSD(状态机)应用的算法

Php USSD(状态机)应用的算法,php,algorithm,state-machine,ussd,Php,Algorithm,State Machine,Ussd,我已经用PHP创建了一个USSD应用程序,因为USSD请求是唯一的(每个选择都有新的请求),所以我需要一种方法来跟踪它们,在我需要一种方法来存储应用程序的流,在我的USSD应用程序中有静态菜单和动态菜单(从数据库检索),我的问题是,我用很多if、else和switch语句创建了这个应用程序,更新菜单项真的很困难。有人能给我推荐一个好的算法来创建这个USSD应用程序吗?我的意思是解决这个问题的一种有效方法,我需要一种能够根据客户的请求添加和删除菜单的方法,当我这样做时,我的代码不应该中断。有人能帮

我已经用PHP创建了一个USSD应用程序,因为USSD请求是唯一的(每个选择都有新的请求),所以我需要一种方法来跟踪它们,在我需要一种方法来存储应用程序的流,在我的USSD应用程序中有静态菜单和动态菜单(从数据库检索),我的问题是,我用很多if、else和switch语句创建了这个应用程序,更新菜单项真的很困难。有人能给我推荐一个好的算法来创建这个USSD应用程序吗?我的意思是解决这个问题的一种有效方法,我需要一种能够根据客户的请求添加和删除菜单的方法,当我这样做时,我的代码不应该中断。有人能帮我吗

-谢谢和问候


附言:我读过,但它并没有真正回答我的问题

根据我从OP的问题中得到的信息,这里有一些提示:

此问题与树遍历有关。菜单的每个状态将存储在树的一个节点上

如果您不了解后缀树/trie。想法很简单,因为用户输入的选项有限:0,1,2,3,4,5,6…9,#,*,我们可以在一棵树中表示所有状态

树的每个节点都类似于:

Node{        
    Node [] next = new Node[12];//All options from 0 to *
    Menu menu;
}
因此,我们不必使用if和switch,而是可以通过从根到叶遍历树来轻松定位和存储所有状态。要引用所有状态,我们只需要存储一个变量:
Node root

例如,如果我们有一系列动作#111#。(假设#在索引10处,*在索引11处)我们将始终从
根开始
->转到索引10处的节点->转到索引1处的节点。。。最后,返回菜单

伪代码:

Menu traverse(String input){
    Node cur = root;
    for(int index in input){
        cur = cur.next[index];
    }
    return cur.menu;
}
对于删除一个状态/分支,只需从根遍历到该叶,然后用
null
替换父
next
数组中的叶节点


注意:如果将所有菜单存储在一个数组
menu[]menu
中,并且对于每个节点,而不是返回菜单,则可以更轻松地管理菜单列表,您将返回一个整数,表示数组
菜单中所需菜单的索引

使用
USSD
的最佳方法是将每个
命令
作为一个单独的类。通过这种方式,您可以工作、调试和维护大型
USSD
应用程序

示例

$ussd = new USSDMessage(); // USSD Class 

$main = new Command("menu"); // Starting Command 

// Register multiple command 
$main->register(new Command("help"));
$main->register(new Command("account"));
$main->register(new Command("transfer"));
$main->register( new Recharge("reacharge"));

$main->run($ussd); // Run Request 
// Class To receve message from USSD
class USSDMessage {
    function next();
    function saveSession();
}

// Basic Command  Class 
class Command {
    private $name;
    private $cmd = array();

    function __construct($name) {
        $this->name = $name;
    }

    function register(Command $menu) {
        $this->cmd[$menu->getName] = $menu;
    }

    function run(USSDMessage $ussd) {
        $key = $ussd->next(); // get next inpur from ussd

        if (isset($this->cmd[$key])){
            $ussd->run($ussd);
        }
    }
}

// Recharge Command Example 
class Recharge extends Command {

    function run(USSDMessage $ussd) {
        $key = $ussd->next();

        switch ($key){
            case "1":
                // Proccess card recharge
                // Do Somthing 
                $ussd->saveSession(); // End Session 
                break;
            case "2":
                // Process direct deposit
                // Do Somthing
                $ussd->saveSession(); // End Session
                break;
            default:
                // Format Not supported
                // Do Somthing
                $ussd->saveSession(); // End Session
                break;
        }
    }
}
基本班级结构

$ussd = new USSDMessage(); // USSD Class 

$main = new Command("menu"); // Starting Command 

// Register multiple command 
$main->register(new Command("help"));
$main->register(new Command("account"));
$main->register(new Command("transfer"));
$main->register( new Recharge("reacharge"));

$main->run($ussd); // Run Request 
// Class To receve message from USSD
class USSDMessage {
    function next();
    function saveSession();
}

// Basic Command  Class 
class Command {
    private $name;
    private $cmd = array();

    function __construct($name) {
        $this->name = $name;
    }

    function register(Command $menu) {
        $this->cmd[$menu->getName] = $menu;
    }

    function run(USSDMessage $ussd) {
        $key = $ussd->next(); // get next inpur from ussd

        if (isset($this->cmd[$key])){
            $ussd->run($ussd);
        }
    }
}

// Recharge Command Example 
class Recharge extends Command {

    function run(USSDMessage $ussd) {
        $key = $ussd->next();

        switch ($key){
            case "1":
                // Proccess card recharge
                // Do Somthing 
                $ussd->saveSession(); // End Session 
                break;
            case "2":
                // Process direct deposit
                // Do Somthing
                $ussd->saveSession(); // End Session
                break;
            default:
                // Format Not supported
                // Do Somthing
                $ussd->saveSession(); // End Session
                break;
        }
    }
}

您应该尝试使用DB查询来维护应用程序的状态,使用DB查询将帮助您跟踪用户的进度,并将其升级到较高级别,然后将其降级到较低级别,这样您可以更轻松地维护代码。请看下面的代码片段,以帮助您了解使用AfricaStacking平台的基于会话的USSD进度

if($userResponse==""){
        // this is when you receive nothing from the user. serve them the registration menu
        switch ($level) {
            case 0:
                //. Graduate the user to the next level, so you dont serve them the same menu
                 $sql1 = "INSERT INTO `some_seesion_name`(`session_id`, `yourIdentifier`,`level`) VALUES('".$sessionId."','".$yourIdentifier."', 1)";
                 $db->query($sql1);

                 // Insert the Identifier, since it comes with the first POST
                 $sql1a = "INSERT INTO YourDB(`yourIdentifier`) VALUES ('".$yourIdentifier."')";
                 $db->query($sql1a);

                 // Serve the menu request for name
                 $response = "CON Please enter your name";

                // Print the response onto the page so that our gateway can read it
                header('Content-type: text/plain');
                echo $response; 
                break;

     // continue the flow of the app ...... 

你能澄清什么是“USSD”以及你的问题是什么吗?在何处添加和删除菜单?到目前为止,您的代码是什么?它在哪里/如何工作?@pekka(USSD)非结构化补充业务数据是GSM移动电话用于与服务提供商的计算机通信的协议,例如,当我们在手机上执行类似于#111#的操作时,您的菜单是否正确?您可以在其中导航到更多菜单。你明白了吗?这让那部分更清楚了。但是你能澄清你的问题是什么吗?可能会显示一些代码?你可以很容易地将其制作成一个数据库驱动的应用程序,而不是切换。你基本上运行一个查询,如果返回一行,你可以做一些事情,如果不是,你不应该编辑你的问题,以包含系统间交互的示例。初始条件是什么,端点之间传递的消息是什么,最终条件是什么。很明显,尽管您非常熟悉USSD及其细节,但其他人并不多。此外,您的pastebin已过期。。。