Skip to content

Commit

Permalink
Merge pull request #42 from alejandrocalleja/develop
Browse files Browse the repository at this point in the history
v1.0 release
  • Loading branch information
alejandrocalleja authored Jan 26, 2022
2 parents b84e996 + 3eb5018 commit 2fe04d9
Show file tree
Hide file tree
Showing 163 changed files with 12,205 additions and 615 deletions.
14 changes: 5 additions & 9 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ pipeline {
when {
branch 'develop'
}
withCredentials(bindings: [usernamePassword(credentialsId: 'dockerhub-credentials', passwordVariable: 'pass', usernameVariable: 'name')]) {
sh 'mvn compile jib:dockerBuild -Djib.to.auth.username=$name -Djib.to.auth.password=$pass'
steps {
withCredentials(bindings: [usernamePassword(credentialsId: 'dockerhub-credentials', passwordVariable: 'pass', usernameVariable: 'name')]) {
sh 'mvn compile jib:dockerBuild -Djib.to.auth.username=$name -Djib.to.auth.password=$pass'
}
}
}

Expand All @@ -70,14 +72,8 @@ pipeline {
}

}

post {
always {
junit 'build/reports/**/*.xml'
}
}

tools {
maven 'maven'
}
}
}
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,55 @@
# PBL5
PBL5
<p align="center">
<img width="250px" src="https://github.com/alejandrocalleja/PBL5/blob/develop/src/main/resources/static/images/DeckLearn.png?raw=true" align="center" alt="GitHub Readme Stats" />
<h2 align="center">Deck Learn</h2>
<p align="center">A spaced repetition based learning application</p>
</p>

<p align="center">
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
<img alt="Tests Passing" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
</a>
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
</a>
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
</a>
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
</a>
</p>

## Description
Learning is an everyday necessity worldwide, which needs to be done the correct way
to be effective. Information tends to fade in what is known as “the forgetting curve”, a problem
that concerns a wide range of population. However, the fading of the data can be reverted and
stabilised by means of various techniques. One that can be used to achieve a good procure of
knowledge is spaced repetition. This method has been demonstrated to provide a sustainable
capacity of memorization for its users. One of the many ways of using it is by means of the
Leitner system, a flashcard approach that determines when is necessary to regain certain
knowledge. Those flashcards are composed by a question and its answer, storing cards of the
same topic in decks. Spaced repetition does not usually consider the motivation of the user.
However, as it is highly important to maintain the user comfortable, gamification has been
introduced to fulfil that purpose. Due to the importance of providing social interaction, a social
network-like approach has been embraced by the application. Due to the importance of fulfilling
the 2030 agenda of the United Nations, considering the SDGs has also been relevant. This work
explains the development of the product, named DeckLearn, as well as its impact towards the
established objectives and working hypotheses.

## Used technologies
* [![image](https://img.shields.io/badge/Spring_Boot-F2F4F9?style=for-the-badge&logo=spring-boot)](https://spring.io/projects/spring-boot)
* [Thymeleaf](https://www.thymeleaf.org/)
* [![image](https://img.shields.io/badge/Hibernate-59666C?style=for-the-badge&logo=Hibernate&logoColor=white)](https://hibernate.org/)
* [![image](https://img.shields.io/badge/Jenkins-D24939?style=for-the-badge&logo=Jenkins&logoColor=white)](https://www.jenkins.io/)
* [![image](https://img.shields.io/badge/Nginx-009639?style=for-the-badge&logo=nginx&logoColor=white)](https://www.nginx.com/)
* [Sonarqube](https://www.sonarqube.org/)


## CI/CD

##

## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.
31 changes: 29 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</parent>
<groupId>eus.blankcard</groupId>
<artifactId>decklearn</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>1.0</version>
<name>decklearn</name>
<description>DeckLearn project source code</description>
<properties>
Expand Down Expand Up @@ -61,6 +61,14 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>


</dependencies>

<build>
Expand Down Expand Up @@ -93,7 +101,26 @@
</to>
</configuration>
</plugin>

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down
223 changes: 223 additions & 0 deletions src/main/java/eus/blankcard/decklearn/controller/DeckController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
package eus.blankcard.decklearn.controller;

import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import eus.blankcard.decklearn.models.deck.DeckModel;
import eus.blankcard.decklearn.models.user.UserModel;
import eus.blankcard.decklearn.repository.deck.DeckRepository;
import eus.blankcard.decklearn.repository.user.UserRepository;
import eus.blankcard.decklearn.util.DeckCreationUtils;
import eus.blankcard.decklearn.util.StatsCalculator;

@Controller
public class DeckController {

@Autowired
UserRepository userRepository;

@Autowired
DeckRepository deckRepository;

@Autowired
DeckCreationUtils deckCreationUtils;

@Autowired
StatsCalculator statsCalculator;

String redirectError = "redirect:/error";

@GetMapping("/deck/{deckId}")
public String getMethodName(@PathVariable("deckId") Integer deckId, HttpServletRequest req,
HttpServletResponse response) {

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String loggedUsername = authentication.getName();

UserModel loggedUser = userRepository.findByUsername(loggedUsername);

DeckModel deck = deckRepository.getById(deckId);
UserModel creator = deck.getCreator();

req.setAttribute("deck", deck);
req.setAttribute("cardNumber", deck.getCards().size());
req.setAttribute("types", deck.getTypes());
req.setAttribute("creator", creator.getUsername());
req.setAttribute("studies", deck.getTrainings().size());
req.setAttribute("home", true);
req.setAttribute("saved", loggedUser.getSavedDecks().contains(deck));
req.setAttribute("isCreator", loggedUser.getDecks().contains(deck));

return "/deck/deck_view";
}

@GetMapping("/deck/{deckId}/stats")
public String getDeckStats(@PathVariable("deckId") Integer deckId, HttpServletRequest req,
HttpServletResponse response) {
DeckModel deck = deckRepository.getById(deckId);

AtomicInteger monthStudies = statsCalculator.getMonthStudies(deck);
int totalStudies = deck.getTrainings().size();
Time avgTime = statsCalculator.getAvgResponseTime(deck);
String timeFormat = new SimpleDateFormat("mm:ss").format(avgTime);

int totalSaves = deck.getSavers().size();
int averagePass = statsCalculator.getAveragePassRatio(deck);

req.setAttribute("deck", deck);
req.setAttribute("monthStudies", monthStudies);
req.setAttribute("totalStudies", totalStudies);
req.setAttribute("avgTime", timeFormat);
req.setAttribute("totalSaves", totalSaves);
req.setAttribute("averagePass", averagePass);
req.setAttribute("stats", true);

return "/deck/deck_stats";
}

@PostMapping("/deck/{deckId}/save")
public String saveDeck(@PathVariable("deckId") Integer deckId, HttpServletRequest req,
HttpServletResponse response) {

Optional<DeckModel> optionalDeck = deckRepository.findById(deckId);

if (optionalDeck.isPresent()) {
DeckModel deckModel = optionalDeck.get();

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String loggedUsername = authentication.getName();

UserModel userModel = userRepository.findByUsername(loggedUsername);

if (userModel.getSavedDecks().contains(deckModel)) {
userModel.getSavedDecks().remove(deckModel);
} else {
userModel.getSavedDecks().add(deckModel);
}

userRepository.save(userModel);

return "redirect:/deck/" + deckModel.getId();
} else {
return redirectError;
}
}

@PostMapping("/deck/{deckId}/remove")
public String deleteDeck(@PathVariable("deckId") Integer deckId, HttpServletRequest req,
HttpServletResponse response) {

Optional<DeckModel> optionalDeck = deckRepository.findById(deckId);

if (optionalDeck.isPresent()) {
DeckModel deck = optionalDeck.get();

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String loggedUsername = authentication.getName();

UserModel loggedUser = userRepository.findByUsername(loggedUsername);

if (deck.getCreator().getId().equals(loggedUser.getId())) {
deckRepository.delete(deck);
} else {
return redirectError;
}

return "redirect:/" + loggedUsername;

} else {
return redirectError;
}
}

@GetMapping("/create/deck")
public String getCreationForm(HttpServletRequest req,
HttpServletResponse response) {

DeckModel deck = new DeckModel();
deck.setCards(new ArrayList<>());

req.setAttribute("deck", deck);
req.setAttribute("cardNum", deck.getCards().size());
req.setAttribute("action", "new");
req.setAttribute("create", true);

return "deck/deck_creation";
}

@GetMapping("/create/deck/{deckId}")
public String getCreateFormWithDeck(@PathVariable("deckId") Integer deckId, HttpServletRequest req,
HttpServletResponse res) {

DeckModel deck = deckRepository.getById(deckId);

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String loggedUsername = authentication.getName();
UserModel userModel = userRepository.findByUsername(loggedUsername);

if (deck.getCreator().getId().equals(userModel.getId())) {
req.setAttribute("deck", deck);
req.setAttribute("cardNum", deck.getCards().size());
req.setAttribute("action", "edit");
req.setAttribute("create", true);
return "deck/deck_creation";
} else {
return redirectError;
}

}

@PostMapping("/create/deck")
public String saveDeckForFirstTime(HttpServletRequest req, HttpServletResponse res) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String loggedUsername = authentication.getName();
UserModel loggedUser = userRepository.findByUsername(loggedUsername);

DeckModel deck = new DeckModel();

deck.setCreator(loggedUser);
deck = deckRepository.save(deck);

deck.setTitle(req.getParameter("title"));
deck.setDescription(req.getParameter("description"));
deck.setImgPath("/images/deck/default.png");

String redirectUrl = "redirect:/create/deck/" + deck.getId();
String action = req.getParameter("action");

redirectUrl = deckCreationUtils.checkAction(req, res, deck, action);

return redirectUrl;
}

@PostMapping("/create/deck/{deckId}")
public String createDeck(@PathVariable("deckId") Integer deckId, HttpServletRequest req,
HttpServletResponse res) {

DeckModel deck = deckRepository.getById(deckId);
deck.setTitle(req.getParameter("title"));
deck.setDescription(req.getParameter("description"));
deck.setImgPath("/images/deck/default.png");

String redirectUrl = "redirect:/create/deck/" + deck.getId();
String action = req.getParameter("action");

redirectUrl = deckCreationUtils.checkAction(req, res, deck, action);

return redirectUrl;
}
}
Loading

0 comments on commit 2fe04d9

Please sign in to comment.