I am trying to build a Quiz-Game for an event which should work the following way.
I have a Collection with Games, which have multiple questions. Those again have different types, answers and a countdown.
The admin has to start a game, the game starts the first question and sets the countdown.
After the countdown runs out, the form input should be disabled and I want to collect the data from all the clients connected to the game.
Is there a way to trigger a method on server side after the countdown ran out to pull data from all clients on server side without a submit on client side?
I have used something similar in a project, maybe this is a solution to your problem.
Server Side Counter and Template Level Subscription
Let your clients subscribe to a quiz collection, where each document represents a current quiz logic.
The document contains information about wether it has been started, the countdown length and (important!) the current time left. The countdown is updated on the server, and thus the document is updated.
A minimal example would be:
Why? Because you will update your countdown on the server and write the time left into the doc. This removes the problem, that clients could manipulate their countdown (and thus maybe the overall time left) and they sync their time left with the server instead of the server with them.
Also triggering the start/pause to whatever by an admin can be checked on the server, regarding userId/roles. This makes it impossible for other clients to start/end the quiz.
Once the time is up, you write a flag (e.g. timeUp) into the document, that time is up. This again can reactively trigger in the clients a template event which makes each client call a server method and send it's result to the server.
An example using template level subscription would be:
Template.quiz.onCreated(function() {
const instance = this;
instance.state = new ReactiveDict();
instance.state.set('timeLeft', -1);
instance.state.set('started', false);
const quizId = /* ... params to load your quiz document */
instance.autorun(function () {
const subscription = instance.subscribe("quizpublication");
if (subscription.ready()) {
instance.state.set("loadComplete", true);
}
const quizDoc = Quiz.findOne({})
if (!quizDoc) return; //skips until subscriptions are ready
if (quizDoc.started && !intance.state.get("started") {
Meteor.call("startQuiz", {_id:quizDoc._id}); // trigger the counter start on the server
instance.state.set('started', quizDoc.started);
}
instance.state.set('timeLeft', quizDoc.timeLeft); //updated on the server, updated here
if (quizDoc.timeUp) {
Meteor.call("sendMyQuizresults", {/* your results from the form input*/}, function(err, res){
//...
});
}
});
});