參考這套代碼,辯論賽也能搬到線上

你熟悉辯論么?如果不熟悉,“奇葩說”總是看過的吧?我們這次想聊聊辯論賽的“未來”。

說是“未來”,或許現在也同樣適用。在疫情還未解除的情況下,很多線下活動都無法進行,辯論就是其中之一。不過已經有人將這個場景從線下搬到了線上。

我們 2019 年 由聲網 Agora 主辦的 RTC 創新編程挑戰賽的三強之一,“辯之竹”團隊實現了一套功能完整的辯論系統,能計時、在線辯論、裁判視頻點評,還能統計票數等。而且,它已經應用于很多辯論比賽中。于是我們讓“辯之竹”撰寫分享了一下作品的初衷,還有核心功能的實現。

同時,今年由聲網 Agora 舉辦的 RTC 創新編程挑戰賽已經開賽了!春季賽有兩個賽題:你可以選擇基于大賽提供的 Demo,為多人視頻通話實現一個好看的 UI;也可以基于 Agora SDK,為自己的應用增加音視頻互動能力,就像本文這個獲獎作品一樣。大賽還準備了豐厚的大獎,拉上小伙伴一起,點擊這里報名參賽吧!

項目介紹

為解決傳統辯論賽UI丑、各系統相互割裂、線下舉辦各類成本等問題,特開發此系統。該套系統完全體包括:

  • 可定制的賽事計時器
  • 賽程、評委和辯手 管理后臺
  • 賽程查看和無紙化提交分數的小程序
  • 賽后即時點對點反饋個人表現的辯力提升系統
  • 遠程裁決的視頻會議部分

項目初心

作為一個大學生,我們經常在大學舉辦各類辯論賽,但是在當前的辯論賽事中,長期存在著五大問題,即如圖:
image.png

  • 日程查看不直觀
  • 計時器簡陋不美觀
  • 統計票數麻煩且不環保
  • 復盤數據獲取困難
  • 優質裁判資源稀少

除了以上問題,其實我們也發現現在的辯論賽非常受限于場地的局限,就算同一學校的兩支辯論隊也要解決申請教室、邀請評委、宣傳吸引觀眾等問題,更別說如果是兩所學校,兩個城市,甚至兩個國家的辯論隊之間要舉辦比賽了。所以也想著能否把辯論賽整體搬遷到線上進行,正好接觸到聲網Agora 的黑客松大賽,了解到 SDK 每個月有 10000 分鐘的免費額度,也看下了他支撐的語言框架和 SDK 集成文檔很豐富,于是就想著參賽做個作品,能幫助解決相關問題的同時,提升鍛煉自己的技術水平。

解決日程觀看不直觀

日程展示一直是個問題。傳統賽事中,日程展示通常都是以發送 PDF 的形式呈現,當參賽人員和觀賽人員想要查看日程時,往往需要[打開QQ->進入賽事群->點開群文件->打開PDF->人工尋找對應日期的日程]。

就算完成了上述步驟,日程文件往往也是一個字號小、信息繁復、不直觀的 PDF 文件。尋找一個日程很麻煩且不適。為了讓參賽人員和觀賽人員更直觀的看到日程,特在小程序內設置此頁面。

數據儲存使用了微信的云開發,并設計了 Web 端的后臺頁面,利用微信提供的API進行小程序端和 Web 端的數據統一來在 Web 端添加日程。

Web 端數據發送部分代碼:

//./web/admin-battle-add.php
//這里調用了我自己寫的微信云開發簡易SDK,可以在源碼中./web部分/lib/WeChat.php找到。具體信息可以在本文后部分具體介紹中找到。
else if($motion=="addBattle"){
    $title   = $_POST["title"];
    $loc     = $_POST["loc"];
    $time    = $_POST["time"];
    $teamClaimId = $_POST["teamClaimId"];
    $teamCounterClaimId = $_POST["teamCounterClaimId"];
    $res = $wx->databaseAdd("db.collection(\"battle\").add({data:{env:\"{$GLOBALS["env"]}\",title:\"{$title}\",status:\"0\",loc:\"{$loc}\",time:\"{$time}\",data:{teamClaim:{Id:\"{$teamClaimId}\",point:\"\"},teamCounterClaim:{Id:\"{$teamCounterClaimId}\",point:\"\"}}}})");
    redirect("./admin-battle-query.php?id=".$res["id_list"][0]);
}

小程序部分代碼:

//./小程序部分/Bam1/client/src/pages/schedule/schedule.js
componentWillMount () {
    let {env} = this.$router.params;
    Taro.setNavigationBarTitle({title:this.$router.params.cName});
    Taro.setStorageSync("env",env);
    let p = this;
    let skpD = 0;
    Taro.cloud.database({env:"factory-1"}).collection("other").where({
        env: Taro.getStorageSync("env"),
        isSkpD : true
    }).get({
        success: res1 => {
        skpD = res1.data[0].skpD;
        Taro.cloud.database({env:"factory-1"}).collection("battle").where({env: Taro.getStorageSync("env")}).skip(skpD).limit(12).get({
            success:function (res) {
            let idL = p.state.idList;
            res.data.map((item,index)=>{
                idL.push(item._id);
            });
            p.setState({
                idList: idL
            })
...
}

備注:

  • 小程序部分,./Wechat Mini Program/Bam1/client/src/pages/schedule/schedule.js這部分代碼主要是調用微信云開發的相關函數獲取比賽 ID 列表。

  • 在這個文件外,./Wechat Mini Program/Bam1/client/src/components/battle/battle.js 是每一個日程 card 的組件。通過 schedule 文件向內傳入 ID 參數,在 battle component 內獲取數據。

  • 這里存在一個并不合理的獲取數據方式。我后來思考,在主界面一次性獲取所有數據后,將數據交由 battle component 渲染應該可以得到更高的性能。但是當時時間有限,就沒有修改。

解決計時器簡陋不美觀

其次,計時器的不美觀問題,傳統計時器如圖:

顯然,這種計時器與任何現代的設計思維都背道而馳,完全無美感可言。我找朋友為我設計了計時器的頁面,并利用 HTML + JavaScript 實現其功能。計時器展示如圖:

JS 的主要實現部分在./web/admin-battle-add.php

該計時器主要實現了如下功能:

  • 辯手姓名、圖片展示
  • 鍵盤操控
  • 自定義環節
    由于使用 HTML 開發,它有相比 exe 的更高跨平臺能力。

解決統計票數問題

同時,響應無紙化潮流,我還設計了無紙化提交分數的裁判系統。它的另一個好處是避免了人工計算分數,防止人為誤差的出現 + 計算分數的等待。
文件在:./Wechat Mini Program/Bam1/client/src/pages/user/judge.js

裁判界面的環節是與計時器同步的。

這里為了防止數據丟失,還使用Taro.setStorageSync(),在每一次寫完數據后,將數據存入臨時數據。同樣,當全部寫入完畢,再使用微信云開發提交到服務器。

$obj = $wx->databaseQuery("db.collection(\"battle-judge-point-conclude\").where({env:\"{$GLOBALS["env"]}\",battleId:\"{$bid}\",judgeId:\"{$r["judgeId"]}\"}).get()");

復盤數據獲取更容易

個人辯力提升系統也是本系統的另一個亮點。在傳統賽事中,辯手對自己的表現只能以輸贏來衡量,很難量化出一個標準,往往會拖慢對個人的提升。

但是在最普遍的三輪投票制中,有一輪即分數票,評委會根據選手的表現給出對應的分數。在傳統賽事里,因為統計麻煩,所以往往不會將這個分數反饋給辯手。這浪費了一個很重要的資源。所以此系統利用評委在云上的分數,將每個辯手的分數落實到每個辯手身上,這樣可以直觀量化出辯手的水平,為辯手的進一步提升提供幫助。

裁判遠程視頻

最后,目前在辯論賽上普遍存在一個問題:缺少優質裁判資源。倒不是說優質裁判特別特別少,而是請優質裁判所需要的高昂的食宿、交通費用往往給辯論組委會帶來很大的經濟困難。故利用Agora聲網公司提供的視頻會議SDK開發了遠程視頻裁決系統。

在前期開發中,其實并沒有非常多的實際視頻通話使用需求,聲網提供的開發者免費時長(每月10000分鐘免費),為我作為一個大學生的開發提供了很大便利。同時,聲網便利的SDK及其文檔介紹使我很快就將服務接入了已有系統,整體開發體驗非常好。得益于聲網的優質服務,在幾次測試中,視頻會議的穩定性非常之高,完全滿足了使用需求。

文字直播:

        $("#send").click(function () {
            if(channel === null) {
                showOnP("未加入頻道,請登錄。")
                return;
            }
            channel.sendMessage({ text: $("#text").val() }).then(() => {
                showOnP("直播發送:"+$("#text").val());
            /* 頻道消息發送成功的處理邏輯 */
          }).catch(error => {
                showOnP("直播發送失敗:"+$("#text").val());
                showOnP(error)
            /* 頻道消息發送失敗的處理邏輯 */
          });
        })
        client.on('ChannelMessage', ({ text }, senderId) => { // text 為收到的頻道消息文本,senderId 為發送方的 User ID
            console.log(text);
            /* 收到頻道消息的處理邏輯 */
            showOnP("直播服務器收到信息:"+text+",直播員:"+senderId);
        });

接入RTC視頻Channel:

  rtc.client.init(option.appID, function () {
        console.log("init success");
        rtc.client.join(option.token ? option.token : null, option.channel, option.uid ? +option.uid : null, function (uid) {
          Toast.notice("join channel: " + option.channel + " success, uid: " + uid);
          console.log("join channel: " + option.channel + " success, uid: " + uid);
          rtc.joined = true;
          rtc.params.uid = uid;
          // create local stream
          rtc.localStream = AgoraRTC.createStream({
            streamID: rtc.params.uid,
            audio: true,
            video: true,
            screen: false,
            microphoneId: option.microphoneId,
            cameraId: option.cameraId
          })
          // init local stream
          rtc.localStream.init(function () {
          console.log("init local stream success");
          // play stream with html element id "local_stream"
          rtc.localStream.play("local_stream")
          // publish local stream
          publish(rtc);
          }, function (err)  {
            Toast.error("stream init failed, please open console see more detail")
            console.error("init local stream failed ", err);
          })
        }, function(err) {
          Toast.error("client join failed, please open console see more detail")
          console.error("client join failed", err)
        })
      }, (err) => {
        Toast.error("client init failed, please open console see more detail")
        console.error(err);
      });
    }

此外,在上述展示出來的部分外,該系統還有完備的數據錄入(指賽事信息錄入),辯手信息和裁判信息錄入系統。在這里不多展示。目前該系統已應用到實際環境多次,支撐多次辯論賽事的開展,歡迎大家使用,也歡迎大家可以一起參與到該項目的開發維護。

涉及技術

  • 小程序: Taro, 微信云開發

  • 網頁端: Material Pro(樣式), PHP, Agora SDK

開源與更多

RTC 2020 編程挑戰賽春季賽已經開啟報名了! 本次大賽從 3月10日 ~ 4月21日 進行報名、組隊與開發,4 月 22 日至 4 月 24 日提交作品,4 月 25 日評獎,全程在線上進行。本次大賽準備了豐厚的大獎,獲獎者更有機會進入聲網 Agora 應聘快速通道快拉上小伙伴報名吧!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容