[Updated] Finished Frontend, Added statushandling to backend and frontend [Todo: session token handling at lvl 2]
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,7 @@
|
||||
import { Question } from "./question";
|
||||
|
||||
export interface Session {
|
||||
id: string;
|
||||
statusCode: number;
|
||||
questions: Question[];
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Question } from '../models/question';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CleanerService {
|
||||
|
||||
constructor() { }
|
||||
|
||||
/**
|
||||
* Sets decoded strings for the questions and the answers, so the special characters will be shown instead of their codes
|
||||
*/
|
||||
public cleanQuestionStrings(questions: Question[]): Question[] {
|
||||
for(let i = 0; i < questions.length; i++) {
|
||||
questions[i].question_decoded = this.decodeString(questions[i].question);
|
||||
questions[i].answers_decoded = [];
|
||||
for(let j = 0; j < questions[i].answers.length; j++){
|
||||
questions[i].answers_decoded!.push(this.decodeString(questions[i].answers[j]));
|
||||
}
|
||||
}
|
||||
return questions;
|
||||
}
|
||||
|
||||
/** Puts special characters back into the string, like ' and " */
|
||||
private decodeString(text: string) {
|
||||
const txt = document.createElement("textarea");
|
||||
txt.innerHTML = text;
|
||||
const decodedValue = txt.value;
|
||||
txt.remove(); // Clean up the temporary element
|
||||
return decodedValue;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ import {
|
||||
import { Question } from '../models/question';
|
||||
import { Answers } from '../models/answers';
|
||||
import { StorageService } from './storage.service';
|
||||
import { CleanerService } from './cleaner.service';
|
||||
import { ResponseHandlerService } from './response-handler.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -23,13 +25,22 @@ import { StorageService } from './storage.service';
|
||||
export class QuizService {
|
||||
private apiUrl = 'http://localhost:9090/quiz';
|
||||
|
||||
constructor(private http: HttpClient, private storageService: StorageService) {}
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private storageService: StorageService,
|
||||
private cleanerService: CleanerService,
|
||||
private reponseHandler: ResponseHandlerService) {}
|
||||
|
||||
public async startSession(quizParams: QuizParams) {
|
||||
public async startSession(quizParams: QuizParams): Promise<Question[] | null> {
|
||||
const sessionIdObj = await firstValueFrom(this.http.get<any>(this.apiUrl + '/questions' + this.convertParamsToUrl(quizParams)));
|
||||
/** No need to poll if the session is not created. Likely means the queue is full */
|
||||
if(sessionIdObj.statusCode !== 0) {
|
||||
return this.reponseHandler.handleResponse(sessionIdObj.statusCode);
|
||||
}
|
||||
this.storageService.setSession(sessionIdObj.sessionId);
|
||||
const questionsObj = await lastValueFrom(this.pollQuestions(sessionIdObj.sessionId));
|
||||
return this.cleanQuestionStrings(questionsObj.questions) as Question[];
|
||||
const sessionObj = await lastValueFrom(this.pollQuestions(sessionIdObj.sessionId));
|
||||
|
||||
return this.reponseHandler.handleResponse(sessionIdObj.statusCode, sessionObj);
|
||||
}
|
||||
|
||||
public pollQuestions(sessionId: string) {
|
||||
@@ -42,26 +53,6 @@ export class QuizService {
|
||||
);
|
||||
}
|
||||
|
||||
private cleanQuestionStrings(questions: Question[]): Question[] {
|
||||
for(let i = 0; i < questions.length; i++) {
|
||||
questions[i].question_decoded = this.decodeString(questions[i].question);
|
||||
questions[i].answers_decoded = [];
|
||||
for(let j = 0; j < questions[i].answers.length; j++){
|
||||
questions[i].answers_decoded!.push(this.decodeString(questions[i].answers[j]));
|
||||
}
|
||||
}
|
||||
return questions;
|
||||
}
|
||||
|
||||
/** Puts special characters back into the string, like ' and " */
|
||||
private decodeString(text: string) {
|
||||
const txt = document.createElement("textarea");
|
||||
txt.innerHTML = text;
|
||||
const decodedValue = txt.value;
|
||||
txt.remove(); // Clean up the temporary element
|
||||
return decodedValue;
|
||||
}
|
||||
|
||||
public async getScore(answers: string[]) {
|
||||
const answersJson: Answers = {
|
||||
sessionId: this.storageService.getSession()!,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Session } from '../models/session';
|
||||
import { CleanerService } from './cleaner.service';
|
||||
import { Question } from '../models/question';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ResponseHandlerService {
|
||||
constructor(private cleanerService: CleanerService) {}
|
||||
|
||||
/**
|
||||
* Session is optional, except for the success state (0)
|
||||
*/
|
||||
public handleResponse(statusCode: number, session?: Session): Question[] | null {
|
||||
switch (statusCode) {
|
||||
case 0:
|
||||
// Success
|
||||
session!.questions = this.cleanerService.cleanQuestionStrings(session!.questions);
|
||||
return session!.questions;
|
||||
case 1:
|
||||
// No Results (requests too much data for this combination of parameters)
|
||||
alert('Not enough data for this request, please try a different combination');
|
||||
return null;
|
||||
case 2:
|
||||
// Invalid parameter (should be handled by the backend)
|
||||
alert('Invalid input');
|
||||
return null;
|
||||
case 5:
|
||||
// Queue is full, try again later
|
||||
alert('The server is experiencing a lot of traffic, please try again later');
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,10 @@ export class SetupComponent {
|
||||
};
|
||||
|
||||
this.spinnerService.setActive(true);
|
||||
this.quizService.startSession(params).then((questions: Question[]) => {
|
||||
this.gotoQuiz(questions);
|
||||
this.quizService.startSession(params).then((questions: Question[] | null) => {
|
||||
if(questions !== null) {
|
||||
this.gotoQuiz(questions);
|
||||
}
|
||||
})
|
||||
.catch((e) => {alert("Something went wrong, please try again");})
|
||||
.finally(() => {this.spinnerService.setActive(false);});
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
<!-- <div class="h-screen"> -->
|
||||
<router-outlet></router-outlet>
|
||||
<!-- </div> -->
|
||||
<app-spinner></app-spinner>
|
||||
@@ -5,7 +5,7 @@
|
||||
<title>Quiz</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="icon" type="image/x-icon" href="question.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
|
||||
Reference in New Issue
Block a user