老師們常常都要對學生做測驗,網路上已經有很多網頁式的線上測驗,但還沒見過有人做過在Line上使用的線上測驗。今天將上週所做的google表單問卷的Line程式稍微修改一下程式碼,就可以做出在Line上的線上測驗,感覺比較像有個人在對你一問一答,學生可能也不知道是個Line機器人在和他對答,似乎比較有趣些。
這個程式如果再稍加修改,還可以成為多人異地的搶答競賽,多人異地加入某個Line聊天室,由LineBot出題讓大家搶答,最後可以記錄出誰是得分王,對學生來說應該也是個滿刺激的活動。
//以下的四列require裡的內容,請確認是否已經用npm裝進node.js
var linebot = require('linebot');
var express = require('express');
var google = require('googleapis');
var googleAuth = require('google-auth-library');
//以下的引號內請輸入申請LineBot取得的各項資料,逗號及引號都不能刪掉
var bot = linebot({
channelId: '請輸入LineBot的channelId',
channelSecret: '請輸入LineBot的channelSecret',
channelAccessToken: '請輸入LineBot的channelAccessToken'
});
//底下輸入client_secret.json檔案的內容
var myClientSecret=請將client_secret.json檔案的內容放在這裡,前後不能加引號
var auth = new googleAuth();
var oauth2Client = new auth.OAuth2(myClientSecret.installed.client_id,myClientSecret.installed.client_secret, myClientSecret.installed.redirect_uris[0]);
//底下輸入sheetsapi.json檔案的內容
oauth2Client.credentials =請將sheetsapi.json檔案的內容放在這裡,前後不能加引號
//試算表的ID,引號不能刪掉
var mySheetId='請輸入試算表的ID編號';
var title='';
var users=[];
var totalSteps=0;
var myQuestions=[];
//程式啟動後會去讀取試算表的歡迎詞工作表的內容
getTitle();
//程式啟動後會去讀取試算表的問題的工作表的內容
getQuestions();
//取得歡迎詞內容的函式
function getTitle() {
var sheets = google.sheets('v4');
sheets.spreadsheets.values.get({
auth: oauth2Client,
spreadsheetId: mySheetId,
range:encodeURI('歡迎詞'),
}, function(err, response) {
if (err) {
console.log('讀取問題檔的API產生問題:' + err);
return;
}
title= response.values[0][0];
console.log('title已下載完畢!');
});
}
//取得線上測驗問題的函式
function getQuestions() {
var sheets = google.sheets('v4');
sheets.spreadsheets.values.get({
auth: oauth2Client,
spreadsheetId: mySheetId,
range:encodeURI('問題'),
}, function(err, response) {
if (err) {
console.log('讀取問題檔的API產生問題:' + err);
return;
}
var rows = response.values;
if (rows.length == 0) {
console.log('No data found.');
} else {
myQuestions=rows;
totalSteps=myQuestions.length;
console.log('要問的問題已下載完畢!');
}
});
}
//LineBot收到user的文字訊息時的處理函式
bot.on('message', function(event) {
if (event.message.type === 'text') {
var myId=event.source.userId;
if (users[myId]==undefined){
users[myId]=[];
users[myId].userId=event.source.userId;
users[myId].step=-1;
users[myId].rightAns=0;
users[myId].replies=[];
users[myId].replies[0]='';
users[myId].replies[1]=new Date();
getDisplayName(event);
sendMessage(event,title+'本次測驗共有'+totalSteps+'題:');
setTimeout(function() {
pushStepQuestion(users[myId].userId);
}, 2000);
}
else{
if(!isNaN(event.message.text)){
checkAnswer(users[myId].userId,event.message.text);
}else{
sendMessage(event,'請用阿拉伯數字選擇答案!');
}
}
}
});
//取得user的使用者名稱
function getDisplayName(eve){
bot.getUserProfile(eve.source.userId);
eve.source.profile().then(function (profile) {
users[eve.source.userId].replies[0]=profile.displayName;
}).catch(function (error) {
// error
});
}
//這是將測驗結果儲存進試算表的函式
function appendMyRow(userId) {
var request = {
auth: oauth2Client,
spreadsheetId: mySheetId,
range:encodeURI('測驗結果'),
insertDataOption: 'INSERT_ROWS',
valueInputOption: 'RAW',
resource: {
"values": [
users[userId].replies
]
}
};
var sheets = google.sheets('v4');
sheets.spreadsheets.values.append(request, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
});
}
//檢查答案是否正確的函式
function checkAnswer(whoId,myAns){
var myStep=users[whoId].step;
if (myStep<totalSteps){
users[whoId].answers=[];
users[whoId].answers[myStep]=myAns;
users[whoId].replies[myStep*2+2]=Number(myAns);
if (myAns===myQuestions[myStep][6]){
users[whoId].replies[myStep*2+3]=1;
//以下一行為傳送貼圖程式,第一個參數是要傳送的對象,第二個為貼圖的package ID,第三個參數為貼圖ID
sendSticker(whoId,1,13);
users[whoId].rightAns++;
}else{
users[whoId].replies[myStep*2+3]=0;
//以下一行為傳送貼圖程式,第一個參數是要傳送的對象,第二個為貼圖的package ID,第三個參數為貼圖ID
sendSticker(whoId,1,3);
bot.push(whoId,myQuestions[myStep][5]);
}
myStep++;
if (myStep>=totalSteps){
users[whoId].replies[myStep*2+2]=users[whoId].rightAns;
appendMyRow(whoId);
setTimeout(function() {
bot.push(whoId,'測驗完畢!'+totalSteps+'題共答對'+users[whoId].rightAns+'題!');
delete users[whoId];
},700);
}else{
setTimeout(function() {
pushStepQuestion(whoId);
}, 1000);
}
}
}
//送出貼圖的函式
function sendSticker(to,pkg_id,stk_id){
var messageData = {
type: 'sticker',
packageId: pkg_id,
stickerId: stk_id
};
bot.push(to,messageData);
}
//發問問題的函式
function pushStepQuestion(to){
users[to].step++;
var myStep=users[to].step;
var myMsg='第'+(myStep+1)+'題:\n';
myMsg+=(myQuestions[myStep][0]+'\n');
for (var i=1;i<5;i++){
myMsg+=('('+i+')'+myQuestions[myStep][i]+' ');
}
bot.push(to,myMsg);
}
//傳送訊息的函式
function sendMessage(eve,msg){
eve.reply(msg).then(function(data) {
// success
return true;
}).catch(function(error) {
// error
return false;
});
}
const app = express();
const linebotParser = bot.parser();
app.post('/', linebotParser);
//因為 express 預設走 port 3000,而 heroku 上預設卻不是,要透過下列程式轉換
var server = app.listen(process.env.PORT || 8080, function() {
var port = server.address().port;
console.log("App now running on port", port);
});
以上的程式有使用到傳送貼圖的部份,LinbBot可以讓我們使用公用的貼圖,可以參考以下的文件選擇貼圖。