客服分配算法(加入文件讀寫保護,更新2019/9/30)

class serverController extends Controller
{
    private $onlineList = []; //客服id數組
    private $distributeList = []; // 已分配用戶數
    private $onlineUser = [];
    private $flagValue = 1; // 閾值

    private function initList($id)
    {
        // init List
        array_push($this->onlineList, $id);
        for ($i = 0; $i < count($this->onlineList); $i++) {
            array_push($this->distributeList, 0);
        }

        if (!$this->getAttributes()) {
            $this->setAttributes();
        }
    }

    // when server login and websocket established
    public function serverLogin(Request $request)
    {
        $id = $request->get('id');

        $type = $this->gettype($id);

        if ($type != null && (int)$type != 0 && is_numeric((int)$type)) {
            if ($this->getAttributes()) {
                array_push($this->onlineList, (int)$id);
                array_push($this->distributeList, 0);
                $this->setAttributes();
            } else {
                $this->initList((int)$id);
            }
        } else {
            $this->getAttributes();
            array_push($this->onlineUser, (int)$id);
            $this->setAttributes();
        }
    }

    // when server logout
    public function Logout(Request $request)
    {
        $id = $request->get('id');

        $tmp = null;
        $this->getAttributes();
        $type = $this->gettype($id);

        if ($type != null && (int)$type != 0 && is_numeric((int)$type)) {
            foreach ($this->onlineList as $key => $item) {
                if ($item == (int)$id) {
                    $tmp = $key;
                }
            }
            unset($this->onlineList[$tmp]);
            unset($this->distributeList[$tmp]);
            if (count($this->onlineList) > 0) {
                $this->flagValue = ceil(count($this->onlineUser) / count($this->onlineList));
            } else {
                $this->flagValue = 1;
            }
            $this->setAttributes();
        } else {
            foreach ($this->onlineUser as $key => $item) {
                if ($item == (int)$id) {
                    $tmp = $key;
                }
            }
            unset($this->onlineUser[$tmp]);
            $this->setAttributes();
        }
    }


    // distribute server id
    public function getServerId()
    {
        $this->getAttributes();
        if (count($this->onlineList) > 0) {
            $serverID = array_rand($this->onlineList, 1);
            if ($this->distributeList[$serverID] < $this->flagValue) {
                ++$this->distributeList[$serverID];
                $this->setAttributes();
                return $this->onlineList[$serverID];
            } else {
                return $this->addFlagValue();
            }
        }
        // not online

    }

    private function addFlagValue()
    {
        foreach ($this->distributeList as $key => $item) {
            if ($item >= $this->flagValue) {
                continue;
            } else {
                ++$this->distributeList[$key];
                $this->setAttributes();
                return $this->onlineList[$key];
            }
        }
        $this->flagValue++;
        $this->setAttributes();
        return $this->onlineList[0];
    }

    private function getContents($path)
    {
        $fp = fopen($path, 'r');
        flock($fp, LOCK_SH);
        $buffer = '';
        while (!feof($fp)) {
            $buffer .= fread($fp, 1024);
        }
        flock($fp, LOCK_UN);
        fclose($fp);
        return $buffer;
    }

    // read file
    private function getAttributes()
    {

        if (Storage::disk('local')->exists('/app/onlineList.txt')
            && Storage::disk('local')->exists('/app/distribute.txt')
            && Storage::disk('local')->exists('/app/flagValue.txt')
            && Storage::disk('local')->exists('/app/onlineUser.txt')) {
            $this->onlineList = json_decode($this->getContents(storage_path('/app/onlineList.txt')), true);
            $this->distributeList = json_decode($this->getContents(storage_path('/app/distribute.txt')), true);
            $this->onlineUser = json_decode($this->getContents(storage_path('/app/onlineUser.txt')), true);
            $this->flagValue = (int)$this->getContents(storage_path('/app/flagValue.txt'));

            return true;
        }
        return false;
    }

    private function setAttributes()
    {
        return $this->setContents(storage_path('/app/distribute.txt'), json_encode($this->distributeList))
            && $this->setContents(storage_path('/app/onlineList.txt'), json_encode($this->onlineList))
            && $this->setContents(storage_path('/app/flagValue.txt'), $this->flagValue)
            && $this->setContents(storage_path('/app/onlineUser.txt'), json_encode($this->onlineUser));
    }

    private function setContents($path, $data)
    {
        $fp = fopen($path, 'w');
        do {
            $isLock = flocK($fp, LOCK_EX);
        } while (!$isLock);
        fwrite($fp, $data);
        flock($fp, LOCK_UN);
        fclose($fp);
        return true;
    }

    // padding isServer
    private function gettype($id)
    {
        return DB::table('user')->where('id', $id)->value('type');
    }
}

這個算法還有許多不足之處,如果大家發現,希望大家指出錯誤,及時改正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章