Skip to content

Commit

Permalink
Merge pull request #51 from nora-kauczor/move-check-answer-to-backend
Browse files Browse the repository at this point in the history
Move check answer to backend
  • Loading branch information
nora-kauczor authored Nov 19, 2024
2 parents 5a60d8f + d1a6062 commit c37fa31
Show file tree
Hide file tree
Showing 16 changed files with 556 additions and 165 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.example.backend.check;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/api/check")
@RequiredArgsConstructor
public class CheckController {

private final CheckService checkService;


@GetMapping("/{vocabId}")
public boolean isUserAnswerCorrect(@PathVariable String vocabId, @RequestParam String answer) {
return checkService.isUserAnswerCorrect(vocabId, answer);
}

}
55 changes: 55 additions & 0 deletions backend/src/main/java/org/example/backend/check/CheckService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.example.backend.check;

import lombok.RequiredArgsConstructor;
import org.example.backend.vocab.Language;
import org.example.backend.vocab.Vocab;
import org.example.backend.vocab.VocabRepo;
import org.springframework.stereotype.Service;


import java.util.List;
import java.util.Optional;

import static org.example.backend.check.CorrectAnswers.getCorrectAnswers;

@RequiredArgsConstructor
@Service
public class CheckService {

private final VocabRepo vocabRepo;

public boolean isUserAnswerCorrect(String vocabId, String userAnswer) {
Optional<Vocab> vocabOptional = vocabRepo.findById(vocabId);
Vocab vocab = vocabOptional.orElseThrow();
String word = vocab.getWord();
Language language = vocab.getLanguage();
List<String> correctAnswers = getCorrectAnswers(word, language);
List<String> correctAnswersLowerCase = correctAnswers.stream()
.map(String::toLowerCase)
.toList();
String inputWithoutExtraSpaces = getInputWithoutExtraSpaces(userAnswer);
return correctAnswersLowerCase.stream()
.anyMatch(answer -> answer.equals(inputWithoutExtraSpaces.toLowerCase()));
}


public String getInputWithoutExtraSpaces(String userAnswer) {
String trimmedInput = userAnswer.trim();
StringBuilder result = new StringBuilder();
boolean previousWasSpace = false;
for (int i = 0; i < trimmedInput.length(); i++) {
char currentChar = trimmedInput.charAt(i);
if (currentChar == ' ') {
if (previousWasSpace) {
continue;
}
previousWasSpace = true;
} else {
previousWasSpace = false;
}

result.append(currentChar);
}
return result.toString();
}
}
137 changes: 137 additions & 0 deletions backend/src/main/java/org/example/backend/check/CorrectAnswers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package org.example.backend.check;

import org.example.backend.vocab.Language;

import java.util.List;


public class CorrectAnswers {

public static List<String> getCorrectAnswers(String word, Language language) {
String leftSideOfSlash = getLeftSideOfSlash(word);
String leftSideOfSlashWithoutArticle = getWordWithoutArticle(leftSideOfSlash, language);
String rightSideOfSlash = getRightSideOfSlash(word);
String rightSideOfSlashWithoutArticle = getWordWithoutArticle(word, language);
String leftSideOfSlashWithEndingOfRightSide = getLeftSideOfSlashWithEndingOfRightSide(word);
String wordWithoutArticle = getWordWithoutArticle(word, language);
String wordWithoutBrackets = getWordWithoutBrackets(word);
String wordWithoutBracketsRunTwice = getWordWithoutBrackets(wordWithoutBrackets);
String wordWithoutBracketsRunTwiceWithoutArticle = getWordWithoutArticle(wordWithoutBracketsRunTwice, language);
String wordWithoutBracketsAndWithoutContent = getWordWithoutBracketsAndWithoutBracketsContent(word);
String wordWithoutBracketsAndWithoutContentRunTwice = getWordWithoutBracketsAndWithoutBracketsContent(wordWithoutBracketsAndWithoutContent);
String wordWithoutBracketsAndWithoutContentRunTwiceWithoutArticle = getWordWithoutArticle(wordWithoutBracketsAndWithoutContentRunTwice, language);
return List.of(
word,
leftSideOfSlash,
leftSideOfSlashWithoutArticle,
rightSideOfSlash,
rightSideOfSlashWithoutArticle,
leftSideOfSlashWithEndingOfRightSide,
wordWithoutArticle,
wordWithoutBracketsRunTwiceWithoutArticle,
wordWithoutBracketsRunTwice,
wordWithoutBracketsAndWithoutContentRunTwiceWithoutArticle,
wordWithoutBracketsAndWithoutContentRunTwice
);
}

public static String getLeftSideOfSlash(String word) {
char slash = '/';
boolean wordHasSlash = word.indexOf(slash) != -1;
if (!wordHasSlash) {
return word;
}
int indexOfSlash = word.indexOf(slash);
return word.substring(0, indexOfSlash);
}

public static String getRightSideOfSlash(String word) {
char slash = '/';
boolean wordHasSlash = word.indexOf(slash) != -1;
if (!wordHasSlash) {
return word;
}
int indexOfSlash = word.indexOf(slash);
return word.substring(indexOfSlash + 1);
}

public static String getLeftSideOfSlashWithEndingOfRightSide(String word) {
char slash = '/';
boolean wordHasSlash = word.indexOf(slash) != -1;
if (!wordHasSlash) {
return word;
}
int indexOfSlash = word.indexOf(slash);
char minus = '-';
boolean wordHasMinus = word.indexOf(minus) != -1;
if (!wordHasMinus) {
return word;
}
String ending = word.substring(indexOfSlash + 2);
String leftSideWithoutLastLetter = word.substring(0, indexOfSlash - 1);
return leftSideWithoutLastLetter + ending;
}

public static String getWordWithoutArticle(String word, Language language) {
List<String> articles = List.of("el", "la", "los", "las", "un",
"una", "unos", "unas");
if (language.equals(Language.ITALIAN)) {
articles = List.of("il", "lo", "la", "i", "gli", "le",
"un", "uno", "una", "un'");
}
if (language.equals(Language.FRENCH)) {
articles = List.of("le", "la", "les", "un", "une", "des",
"l'");
}
boolean wordStartsWithArticlesLetters = articles.stream().anyMatch(word::contains);
if (!wordStartsWithArticlesLetters) {
return word;
}
String wordWithoutArticle = word;
for (String article : articles) {
boolean articleIsAtBeginning = word.indexOf(article) == 0;
int articleLength = article.length();
String substringBehindArticle = word.substring(articleLength, articleLength + 1);
boolean spaceBehindArticle = substringBehindArticle.equals(" ");
if (articleIsAtBeginning && spaceBehindArticle) {
wordWithoutArticle = word.substring(articleLength + 1);
}
boolean bracketBehindArticle = substringBehindArticle.equals("(");
if (articleIsAtBeginning && bracketBehindArticle) {
wordWithoutArticle = word.substring(articleLength + 4);
}
}
return wordWithoutArticle;
}

public static String getWordWithoutBrackets(String word) {
char openingBracket = '(';
char closingBracket = ')';
boolean wordHasBrackets = word.indexOf(openingBracket) != -1;
if (!wordHasBrackets) {
return word;
}
int indexOfOpeningBracket = word.indexOf(openingBracket);
int indexOfClosingBracket = word.indexOf(closingBracket);
String substringBeforeBrackets = word.substring(0, indexOfOpeningBracket);
String substringBetweenBrackets = word.substring(indexOfOpeningBracket + 1, indexOfClosingBracket);
String subStringAfterBrackets = word.substring(indexOfClosingBracket + 1);
return substringBeforeBrackets + substringBetweenBrackets + subStringAfterBrackets;
}

public static String getWordWithoutBracketsAndWithoutBracketsContent(String word) {
char openingBracket = '(';
char closingBracket = ')';
boolean wordHasBrackets = word.indexOf(openingBracket) != -1;
if (!wordHasBrackets) {
return word;
}
int indexOfOpeningBracket = word.indexOf(openingBracket);
int indexOfClosingBracket = word.indexOf(closingBracket);
String substringBeforeBrackets = word.substring(0, indexOfOpeningBracket);
String subStringAfterBrackets = word.substring(indexOfClosingBracket + 1);
return substringBeforeBrackets + subStringAfterBrackets;
}


}
12 changes: 2 additions & 10 deletions backend/src/main/java/org/example/backend/vocab/VocabRepo.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
package org.example.backend.vocab;

import org.example.backend.exception.LanguageNotFoundException;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

import static org.example.backend.vocab.Language.getEnumByString;

@Repository
public interface VocabRepo extends MongoRepository<Vocab, String> {
List<Vocab> getByLanguage(Language language);

// public static List<Vocab> getAllNEWTEST(String languageString, String userId) throws LanguageNotFoundException {
// Language language = getEnumByString(languageString);
// return vocabRepo.findAll().stream()
// .filter(vocab -> vocab.getCreatedBy().equals("Wordio") || vocab.getCreatedBy().equals(userId))
// .filter(vocab -> vocab.getLanguage().equals(language))
// .toList();
// }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.example.backend.check;

import org.example.backend.vocab.Language;
import org.example.backend.vocab.Vocab;
import org.example.backend.vocab.VocabRepo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.util.HashMap;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@SpringBootTest
@AutoConfigureMockMvc
class CheckControllerTest {

@Autowired
private MockMvc mvc;

@Autowired
private VocabRepo vocabRepo;

@BeforeEach
void setUp() {
Vocab testVocab = new Vocab("vocab-id", "beau/belle", "beautiful",
"", Language.FRENCH, new HashMap<>(), "Wordio");
Vocab testVocab2 = new Vocab("vocab-id2", "la liberté", "liberty",
"", Language.FRENCH, new HashMap<>(), "Wordio");
Vocab testVocab3 = new Vocab("vocab-id3", "rojo/-a", "red",
"", Language.FRENCH, new HashMap<>(), "Wordio");
vocabRepo.save(testVocab);
vocabRepo.save(testVocab2);
vocabRepo.save(testVocab3);
}

@Test
void isUserAnswerCorrect_ShouldReturnTrue_whenCalledWithIdOfBeauBelleAndUserAnswerBeau() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/check/vocab-id")
.param("answer", "beau")
.with(oauth2Login().attributes(attributes -> {
attributes.put("sub", "jane-doe");
})))
.andExpect(status().isOk())
.andExpect(content().string("true"));
}

@Test
void isUserAnswerCorrect_ShouldReturnFalse_whenCalledWithIdOfBeauBelleAndUserAnswerBaeu()throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/check/vocab-id")
.param("answer", "baeu")
.with(oauth2Login().attributes(attributes -> {
attributes.put("sub", "jane-doe");
})))
.andExpect(status().isOk())
.andExpect(content().string("false"));
}

@Test
void isUserAnswerCorrect_ShouldReturnTrue_whenCalledWithIdOfLaLiberteAndUserAnswerLaliberte() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/check/vocab-id2")
.param("answer", "la liberté")
.with(oauth2Login().attributes(attributes -> {
attributes.put("sub", "jane-doe");
})))
.andExpect(status().isOk())
.andExpect(content().string("true"));
}

@Test
void isUserAnswerCorrect_ShouldReturnTrue_whenCalledWithIdOfLaLiberteAndUserAnswerliberte() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/check/vocab-id2")
.param("answer", "liberté")
.with(oauth2Login().attributes(attributes -> {
attributes.put("sub", "jane-doe");
})))
.andExpect(status().isOk())
.andExpect(content().string("true"));
}

@Test
void isUserAnswerCorrect_ShouldReturnTrue_whenCalledWithIdOfRojoAAndUserAnswerRojo() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/check/vocab-id3")
.param("answer", "rojo")
.with(oauth2Login().attributes(attributes -> {
attributes.put("sub", "jane-doe");
})))
.andExpect(status().isOk())
.andExpect(content().string("true"));
}


@Test
void isUserAnswerCorrect_ShouldReturnTrue_whenCalledWithIdOfRojoAAndUserAnswerRoja() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/api/check/vocab-id3")
.param("answer", "roja")
.with(oauth2Login().attributes(attributes -> {
attributes.put("sub", "jane-doe");
})))
.andExpect(status().isOk())
.andExpect(content().string("true"));
}
}
Loading

0 comments on commit c37fa31

Please sign in to comment.