[Updated] Finished Frontend, Added statushandling to backend and frontend [Todo: session token handling at lvl 2]

This commit is contained in:
Ninjaws
2024-11-01 17:02:24 +01:00
parent 3188f6ce20
commit 675bdc7f8e
16 changed files with 247 additions and 102 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+7
View File
@@ -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;
}
}
+15 -24
View File
@@ -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);});
-2
View File
@@ -1,4 +1,2 @@
<!-- <div class="h-screen"> -->
<router-outlet></router-outlet>
<!-- </div> -->
<app-spinner></app-spinner>
+1 -1
View File
@@ -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>