Add average mark to progress page & fix loader
This commit is contained in:
@@ -222,5 +222,9 @@ service cloud.firestore {
|
|||||||
match /join_codes/{joinCode} {
|
match /join_codes/{joinCode} {
|
||||||
allow get: if isSignedIn();
|
allow get: if isSignedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match /completed_progress/{setIds} {
|
||||||
|
allow get: if isSignedIn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ function cleanseVocabString(item) {
|
|||||||
* @param {object} data The data passed to the function.
|
* @param {object} data The data passed to the function.
|
||||||
* @param {string} data.progressId The ID of the progress document to update.
|
* @param {string} data.progressId The ID of the progress document to update.
|
||||||
* @param {string} data.answer The answer given by the user to the current prompt.
|
* @param {string} data.answer The answer given by the user to the current prompt.
|
||||||
|
* @return {string} averagePercentage The average percentage mark for the current collection of sets. Only returned when the test is complete.
|
||||||
* @return {boolean} correct Whether the provided answer was correct.
|
* @return {boolean} correct Whether the provided answer was correct.
|
||||||
* @return {array} correctAnswers An array of correct answers for the question just answered. If not all correct
|
* @return {array} correctAnswers An array of correct answers for the question just answered. If not all correct
|
||||||
* answers have yet been given, and the current answer is correct, this only contains the correct
|
* answers have yet been given, and the current answer is correct, this only contains the correct
|
||||||
@@ -551,8 +552,27 @@ exports.processAnswer = functions.https.onCall((data, context) => {
|
|||||||
|
|
||||||
if (mode === "lives" && docData.lives <= 0) docData.questions.length = returnData.totalQuestions = docData.progress;
|
if (mode === "lives" && docData.lives <= 0) docData.questions.length = returnData.totalQuestions = docData.progress;
|
||||||
|
|
||||||
|
const completedProgressDocId = db.collection("completed_progress").doc(progressDoc.data().setIds.sort().join("__"));
|
||||||
|
return transaction.get(completedProgressDocId).then((completedProgressDoc) => {
|
||||||
|
const totalPercentage = completedProgressDoc.data().total_percentage + (docData.correct.length / docData.questions.length * 100);
|
||||||
|
const attempts = completedProgressDoc.data().attempts + 1;
|
||||||
|
transaction.set(completedProgressDocId, {
|
||||||
|
attempts: attempts,
|
||||||
|
total_percentage: totalPercentage,
|
||||||
|
});
|
||||||
|
returnData.averagePercentage = (totalPercentage / attempts).toFixed(2);
|
||||||
|
transaction.set(progressDocId, docData);
|
||||||
|
return returnData;
|
||||||
|
}).catch((error) => {
|
||||||
|
const totalPercentage = docData.correct.length / docData.questions.length * 100;
|
||||||
|
transaction.set(completedProgressDocId, {
|
||||||
|
attempts: 1,
|
||||||
|
total_percentage: totalPercentage,
|
||||||
|
});
|
||||||
|
returnData.averagePercentage = totalPercentage.toFixed(2);
|
||||||
transaction.set(progressDocId, docData);
|
transaction.set(progressDocId, docData);
|
||||||
return returnData;
|
return returnData;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const nextVocabId = docData.questions[docData.progress];
|
const nextVocabId = docData.questions[docData.progress];
|
||||||
const nextSetOwner = nextVocabId.split("__")[0];
|
const nextSetOwner = nextVocabId.split("__")[0];
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
lives: 1,
|
lives: 1,
|
||||||
startLives: null,
|
startLives: null,
|
||||||
setComplete: false,
|
setComplete: false,
|
||||||
|
averagePercentage: null,
|
||||||
|
pageLoaded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
@@ -87,7 +89,7 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
const progressId = this.props.match.params.progressId;
|
const progressId = this.props.match.params.progressId;
|
||||||
const progressRef = this.state.db.collection("progress").doc(progressId);
|
const progressRef = this.state.db.collection("progress").doc(progressId);
|
||||||
|
|
||||||
let [ newState, setDone, incorrectAnswers, duration ] = await progressRef.get().then((doc) => {
|
let [ newState, setDone, incorrectAnswers, duration, setIds ] = await progressRef.get().then((doc) => {
|
||||||
const data = doc.data();
|
const data = doc.data();
|
||||||
|
|
||||||
document.title = `Study | ${data.set_title} | Parandum`;
|
document.title = `Study | ${data.set_title} | Parandum`;
|
||||||
@@ -107,6 +109,7 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
setIds: data.setIds,
|
setIds: data.setIds,
|
||||||
originalTotalQuestions: [...new Set(data.questions)].length,
|
originalTotalQuestions: [...new Set(data.questions)].length,
|
||||||
setComplete: data.duration !== null,
|
setComplete: data.duration !== null,
|
||||||
|
pageLoaded: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.lives) {
|
if (data.lives) {
|
||||||
@@ -114,7 +117,7 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
newState.startLives = data.start_lives;
|
newState.startLives = data.start_lives;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ newState, data.duration !== null, data.incorrect, data.duration ];
|
return [ newState, data.duration !== null, data.incorrect, data.duration, data.setIds ];
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.log(`Progress data inaccessible: ${error}`);
|
console.log(`Progress data inaccessible: ${error}`);
|
||||||
return [
|
return [
|
||||||
@@ -166,6 +169,16 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
promises.push(this.state.db.collection("completed_progress")
|
||||||
|
.doc(setIds.sort().join("__"))
|
||||||
|
.get()
|
||||||
|
.then((completedProgressDoc) => {
|
||||||
|
newState.averagePercentage = (completedProgressDoc.data().total_percentage / completedProgressDoc.data().attempts).toFixed(2);
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log(`Couldn't get average percentage: ${error}`);
|
||||||
|
newState.averagePercentage = null;
|
||||||
|
}));
|
||||||
|
|
||||||
if (incorrectAnswers.length > 0) {
|
if (incorrectAnswers.length > 0) {
|
||||||
newState.incorrectAnswers = {};
|
newState.incorrectAnswers = {};
|
||||||
|
|
||||||
@@ -363,6 +376,7 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
if (data.duration) {
|
if (data.duration) {
|
||||||
// test done
|
// test done
|
||||||
newState.duration = data.duration;
|
newState.duration = data.duration;
|
||||||
|
newState.averagePercentage = data.averagePercentage;
|
||||||
|
|
||||||
this.props.logEvent("test_complete", {
|
this.props.logEvent("test_complete", {
|
||||||
progress_id: this.props.match.params.progressId,
|
progress_id: this.props.match.params.progressId,
|
||||||
@@ -491,7 +505,8 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
this.state.progressInaccessible
|
this.state.pageLoaded &&
|
||||||
|
(this.state.progressInaccessible
|
||||||
?
|
?
|
||||||
<Error404 />
|
<Error404 />
|
||||||
:
|
:
|
||||||
@@ -570,6 +585,13 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
<p>You got</p>
|
<p>You got</p>
|
||||||
<h1>{`${(this.state.correct / this.state.totalQuestions * 100).toFixed(2)}%`}</h1>
|
<h1>{`${(this.state.correct / this.state.totalQuestions * 100).toFixed(2)}%`}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
{
|
||||||
|
this.state.averagePercentage !== null &&
|
||||||
|
<div className="stat-row stat-row--inline">
|
||||||
|
<p>The average is</p>
|
||||||
|
<h1>{`${this.state.averagePercentage}%`}</h1>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div className="stat-row stat-row--inline">
|
<div className="stat-row stat-row--inline">
|
||||||
<h1>{`${this.state.correct} of ${this.state.totalQuestions}`}</h1>
|
<h1>{`${this.state.correct} of ${this.state.totalQuestions}`}</h1>
|
||||||
<p>marks</p>
|
<p>marks</p>
|
||||||
@@ -739,7 +761,7 @@ export default withRouter(class Progress extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
</>
|
</>)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -820,4 +820,16 @@ describe("Parandum Firestore database", () => {
|
|||||||
const testDoc = db.collection("join_codes").doc(joinCodeOne);
|
const testDoc = db.collection("join_codes").doc(joinCodeOne);
|
||||||
await firebase.assertFails(testDoc.get());
|
await firebase.assertFails(testDoc.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Can read completed progress docs when signed in", async () => {
|
||||||
|
const db = getFirestore(myAuth);
|
||||||
|
const testDoc = db.collection("completed_progress").doc(setOne);
|
||||||
|
await firebase.assertSucceeds(testDoc.get());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Can't read completed progress docs when not signed in", async () => {
|
||||||
|
const db = getFirestore(null);
|
||||||
|
const testDoc = db.collection("completed_progress").doc(setOne);
|
||||||
|
await firebase.assertFails(testDoc.get());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user