35

用这套代码,奇葩说也能从线下搬到线上

 4 years ago
source link: https://mp.weixin.qq.com/s/ayS6IKQ5QVyHqODwf6O5ug
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近好像有个奇葩说相关的话题上了热搜。不过,那些话题并不是我们这次的主题,我们更想聊聊辩论赛的“未来”。

说是“未来”,或许现在也同样适用。在疫情还未解除的情况下,很多线下活动都无法进行,辩论就是其中之一。不过已经有人将这个场景从线下搬到了线上。

我们 2019 年 RTC 创新编程挑战赛的三强之一,“辩之竹”团队实现了一套功能完整的辩论系统,能计时、在线辩论、裁判视频点评,还能统计票数等。而且,它已经应用于很多辩论比赛中。于是我们让“辩之竹”撰写分享了一下作品的初衷,还有核心功能的实现:

1

项目介绍

为解决传统辩论赛UI丑、各系统相互割裂、线下举办各类成本等问题,特开发此系统。该套系统完全体包括:

  • 可定制的赛事计时器

  • 赛程、评委和辩手 管理后台

  • 赛程查看和无纸化提交分数的小程序

  • 赛后即时点对点反馈个人表现的辩力提升系统

  • 远程裁决的视频会议部分

640?wx_fmt=png

2

项目初心

作为一个大学生,我们经常在大学举办各类辩论赛,但是在当前的辩论赛事中,长期存在着五大问题,即如图:

640?wx_fmt=png

  • 日程查看不直观

  • 计时器简陋不美观

  • 统计票数麻烦且不环保

  • 复盘数据获取困难

  • 优质裁判资源稀少

除了以上问题,其实我们也发现现在的辩论赛非常受限于场地的局限,就算同一学校的两支辩论队也要解决申请教室、邀请评委、宣传吸引观众等问题,更别说如果是两所学校,两个城市,甚至两个国家的辩论队之间要举办比赛了。所以也想着能否把辩论赛整体搬迁到线上进行,正好接触到声网Agora 的黑客松大赛,了解到 SDK 每个月有 10000 分钟的免费额度,也看下了他支撑的语言框架和 SDK 集成文档很丰富,于是就想着参赛做个作品,能帮助解决相关问题的同时,提升锻炼自己的技术水平。

3

解决日程观看不直观

日程展示一直是个问题。传统赛事中,日程展示通常都是以发送 PDF 的形式呈现,当参赛人员和观赛人员想要查看日程时,往往需要 [打开QQ->进入赛事群->点开群文件->打开PDF->人工寻找对应日期的日程]

就算完成了上述步骤,日程文件往往也是一个 字号小、信息繁复、不直观 的 PDF 文件。寻找一个日程很麻烦且不适。为了让参赛人员和观赛人员更直观的看到日程,特在小程序内设置此页面。

640?wx_fmt=png

图:日程展示

数据储存使用了微信的云开发,并设计了 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 渲染应该可以得到更高的性能。但是当时时间有限,就没有修改。

4

解决计时器简陋不美观

其次,计时器的不美观问题,传统计时器如图:

640?wx_fmt=png

图:传统计时器

显然,这种计时器与任何现代的设计思维都背道而驰,完全无美感可言。我找朋友为我设计了计时器的页面,并利用 HTML + JavaScript 实现其功能。计时器展示如图:

640?wx_fmt=png

图:计时器展示

640?wx_fmt=jpeg

图:计时器图片展示

JS 的主要实现部分在 ./web/admin-battle-add.php

该计时器主要实现了如下功能:

  • 辩手姓名、图片展示

  • 键盘操控

  • 自定义环节

由于使用 HTML 开发,它有相比 exe 的更高跨平台能力。

5

解决统计票数问题

同时,响应无纸化潮流,我还设计了无纸化提交分数的裁判系统。它的另一个好处是避免了人工计算分数,防止人为误差的出现 + 计算分数的等待。

文件在: ./Wechat Mini Program/Bam1/client/src/pages/user/judge.js

640?wx_fmt=png

图: 小程序裁判入口

裁判界面的环节是与计时器同步的。

640?wx_fmt=png

图:裁判界面

这里为了防止数据丢失,还使用 Taro.setStorageSync() ,在每一次写完数据后,将数据存入临时数据。同样,当全部写入完毕,再使用微信云开发提交到服务器。

640?wx_fmt=png

图:分数实时回传

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

6

复盘数据获取更容易

个人辩力提升系统也是本系统的另一个亮点。在传统赛事中,辩手对自己的表现只能以输赢来衡量,很难量化出一个标准,往往会拖慢对个人的提升。

但是在最普遍的三轮投票制中,有一轮即分数票,评委会根据选手的表现给出对应的分数。在传统赛事里,因为统计麻烦,所以往往不会将这个分数反馈给辩手。这浪费了一个很重要的资源。所以此系统利用评委在云上的分数,将每个辩手的分数落实到每个辩手身上,这样可以直观量化出辩手的水平,为辩手的进一步提升提供帮助。

640?wx_fmt=png

图:个人辩力提升系统

7

裁判远程视频

最后,目前在辩论赛上普遍存在一个问题:缺少优质裁判资源。倒不是说优质裁判特别特别少,而是请优质裁判所需要的高昂的食宿、交通费用往往给辩论组委会带来很大的经济困难。

故利用 Agora声网公司 提供的视频会议SDK开发了远程视频裁决系统。

在前期开发中,其实并没有非常多的实际视频通话使用需求,声网提供的开发者免费时长(每月10000分钟免费),为我作为一个大学生的开发提供了很大便利。同时,声网便利的SDK及其文档介绍使我很快就将服务接入了已有系统,整体开发体验非常好。得益于声网的优质服务,在几次测试中,视频会议的稳定性非常之高,完全满足了使用需求。

640?wx_fmt=png

图:远程视频裁决系统

文字直播:

$("#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);

});

}

此外,在上述展示出来的部分外,该系统还有完备的数据录入(指赛事信息录入),辩手信息和裁判信息录入系统。在这里不多展示。目前该系统已应用到实际环境多次,支撑多次辩论赛事的开展,欢迎大家使用,也欢迎大家可以一起参与到该项目的开发维护。

8

涉及技术

  • 小程序: Taro, 微信云开发

  • 网页端: Material Pro(样式), PHP, Agora SDK

9

开源与更多

于卓浩: 重庆大学在读大一学生,喜欢学习新技术,兴致来了就写些自己喜欢的小项目。 希望能在有限的时间多学习一些有用的知识~

个人 Github: https://github.com/pkmq24

开源地址 https://github.com/AgoraIO-Community/2019-Hackathon-Works-Online-Debate

640?wx_fmt=jpeg

RTC 2020 编程挑战赛春季赛已经开启报名了! 本次大赛从  3月10日 ~ 4月21日 进行报名、组队与开发,4 月 22 日至 4 月 24 日提交作品,4 月 25 日评奖 ,全程在线上进行 本次大赛准备了 丰厚的大奖,获奖者更有机会进入声网 Agora 应聘快速通道,快拉上小伙伴报名吧!

640?wx_fmt=png

点击「阅读原文」,报名参赛!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK