init impl
This commit is contained in:
parent
b48e5191d7
commit
7366e68ea6
4
Dockerfile
Normal file
4
Dockerfile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
FROM openjdk:17-jdk-slim
|
||||||
|
COPY target/*.jar app.jar
|
||||||
|
EXPOSE 8080
|
||||||
|
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
29
pom.xml
29
pom.xml
@ -88,6 +88,35 @@
|
|||||||
<artifactId>vaadin-testbench-junit5</artifactId>
|
<artifactId>vaadin-testbench-junit5</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.openhft</groupId>
|
||||||
|
<artifactId>compiler</artifactId>
|
||||||
|
<version>2.26ea0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hilerio</groupId>
|
||||||
|
<artifactId>ace-widget</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.hypersistence</groupId>
|
||||||
|
<artifactId>hypersistence-utils-hibernate-63</artifactId>
|
||||||
|
<version>3.7.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>in.virit</groupId>
|
||||||
|
<artifactId>viritin</artifactId>
|
||||||
|
<version>2.8.22</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowingcode.addons</groupId>
|
||||||
|
<artifactId>simple-timer</artifactId>
|
||||||
|
<version>2.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
32
src/main/bundles/README.md
Normal file
32
src/main/bundles/README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
This directory is automatically generated by Vaadin and contains the pre-compiled
|
||||||
|
frontend files/resources for your project (frontend development bundle).
|
||||||
|
|
||||||
|
It should be added to Version Control System and committed, so that other developers
|
||||||
|
do not have to compile it again.
|
||||||
|
|
||||||
|
Frontend development bundle is automatically updated when needed:
|
||||||
|
- an npm/pnpm package is added with @NpmPackage or directly into package.json
|
||||||
|
- CSS, JavaScript or TypeScript files are added with @CssImport, @JsModule or @JavaScript
|
||||||
|
- Vaadin add-on with front-end customizations is added
|
||||||
|
- Custom theme imports/assets added into 'theme.json' file
|
||||||
|
- Exported web component is added.
|
||||||
|
|
||||||
|
If your project development needs a hot deployment of the frontend changes,
|
||||||
|
you can switch Flow to use Vite development server (default in Vaadin 23.3 and earlier versions):
|
||||||
|
- set `vaadin.frontend.hotdeploy=true` in `application.properties`
|
||||||
|
- configure `vaadin-maven-plugin`:
|
||||||
|
```
|
||||||
|
<configuration>
|
||||||
|
<frontendHotdeploy>true</frontendHotdeploy>
|
||||||
|
</configuration>
|
||||||
|
```
|
||||||
|
- configure `jetty-maven-plugin`:
|
||||||
|
```
|
||||||
|
<configuration>
|
||||||
|
<systemProperties>
|
||||||
|
<vaadin.frontend.hotdeploy>true</vaadin.frontend.hotdeploy>
|
||||||
|
</systemProperties>
|
||||||
|
</configuration>
|
||||||
|
```
|
||||||
|
|
||||||
|
Read more [about Vaadin development mode](https://vaadin.com/docs/next/flow/configuration/development-mode#precompiled-bundle).
|
BIN
src/main/bundles/dev.bundle
Normal file
BIN
src/main/bundles/dev.bundle
Normal file
Binary file not shown.
23
src/main/frontend/index.html
Normal file
23
src/main/frontend/index.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
This file is auto-generated by Vaadin.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
body, #outlet {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!-- index.ts is included here automatically (either by the dev server or during the build) -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- This outlet div is where the views are rendered -->
|
||||||
|
<div id="outlet"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
src/main/java/com/primefactorsolutions/model/AppUser.java
Normal file
23
src/main/java/com/primefactorsolutions/model/AppUser.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class AppUser extends BaseEntity {
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "appUser")
|
||||||
|
private List<Assessment> assessments;
|
||||||
|
}
|
64
src/main/java/com/primefactorsolutions/model/Assessment.java
Normal file
64
src/main/java/com/primefactorsolutions/model/Assessment.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class Assessment extends BaseEntity {
|
||||||
|
@OneToMany(fetch = FetchType.EAGER)
|
||||||
|
private List<Question> questions;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "assessment", cascade = {CascadeType.ALL})
|
||||||
|
private List<Submission> submissions;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private AppUser appUser;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "assessment", cascade = {CascadeType.ALL})
|
||||||
|
private List<AssessmentEvent> assessmentEvents = List.of();
|
||||||
|
|
||||||
|
public Submission getCurrentSubmission() {
|
||||||
|
return submissions.getLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getRemainingTimeSeconds() {
|
||||||
|
final Optional<Instant> started = assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
||||||
|
.map(AssessmentEvent::getTimestamp)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
return started.map(instant -> 300L - (Instant.now().getEpochSecond() - instant.getEpochSecond()))
|
||||||
|
.orElse(300L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getStartingTime() {
|
||||||
|
final Optional<Instant> started = assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
||||||
|
.map(AssessmentEvent::getTimestamp)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
return started.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompleted() {
|
||||||
|
return assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.COMPLETED)
|
||||||
|
.map(AssessmentEvent::getTimestamp)
|
||||||
|
.findFirst()
|
||||||
|
.isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFirst(Submission currSubmission) {
|
||||||
|
return getQuestions().indexOf(currSubmission.getQuestion()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLast(Submission currSubmission) {
|
||||||
|
return getQuestions().indexOf(currSubmission.getQuestion()) == getQuestions().size() - 1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class AssessmentEvent extends BaseEntity {
|
||||||
|
private Instant timestamp;
|
||||||
|
private AssessmentStatus status;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Assessment assessment;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
public enum AssessmentStatus {
|
||||||
|
CREATED,
|
||||||
|
STARTED,
|
||||||
|
COMPLETED
|
||||||
|
}
|
51
src/main/java/com/primefactorsolutions/model/BaseEntity.java
Normal file
51
src/main/java/com/primefactorsolutions/model/BaseEntity.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
import jakarta.persistence.Version;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (getId() != null) {
|
||||||
|
return getId().hashCode();
|
||||||
|
}
|
||||||
|
return super.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (!(obj instanceof BaseEntity that)) {
|
||||||
|
return false; // null or not an AbstractEntity class
|
||||||
|
}
|
||||||
|
if (getId() != null) {
|
||||||
|
return getId().equals(that.getId());
|
||||||
|
}
|
||||||
|
return super.equals(that);
|
||||||
|
}
|
||||||
|
}
|
16
src/main/java/com/primefactorsolutions/model/Question.java
Normal file
16
src/main/java/com/primefactorsolutions/model/Question.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class Question extends BaseEntity{
|
||||||
|
private String content;
|
||||||
|
}
|
34
src/main/java/com/primefactorsolutions/model/Submission.java
Normal file
34
src/main/java/com/primefactorsolutions/model/Submission.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class Submission extends BaseEntity {
|
||||||
|
@ManyToOne
|
||||||
|
private Question question;
|
||||||
|
|
||||||
|
private String response;
|
||||||
|
|
||||||
|
@Type(JsonType.class)
|
||||||
|
@Column(columnDefinition = "json")
|
||||||
|
private Map<String, Object> results;
|
||||||
|
|
||||||
|
private SubmissionStatus submissionStatus;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Assessment assessment;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
public enum SubmissionStatus {
|
||||||
|
OK,
|
||||||
|
FAIL
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.primefactorsolutions.repositories;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.Assessment;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface AssessmentRepository extends JpaRepository<Assessment, UUID> {
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.primefactorsolutions.repositories;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.AppUser;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<AppUser, UUID> {
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package com.primefactorsolutions.service;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.*;
|
||||||
|
import com.primefactorsolutions.repositories.AssessmentRepository;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.checkerframework.checker.units.qual.A;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.swing.text.html.Option;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Data
|
||||||
|
public class AssessmentService {
|
||||||
|
|
||||||
|
private final AssessmentRepository assessmentRepository;
|
||||||
|
|
||||||
|
public Assessment createOrUpdate(final Assessment assessment) {
|
||||||
|
final Assessment saved = assessmentRepository.save(assessment);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Assessment> getAssessments() {
|
||||||
|
return assessmentRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assessment getAssessment(final UUID id) {
|
||||||
|
return assessmentRepository.findById(id).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assessment startAssessment(final UUID id) {
|
||||||
|
final Assessment assessment = assessmentRepository.findById(id).get();
|
||||||
|
final Optional<AssessmentEvent> started = assessment.getAssessmentEvents().stream()
|
||||||
|
.filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (started.isPresent()) {
|
||||||
|
return assessment;
|
||||||
|
}
|
||||||
|
|
||||||
|
assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.STARTED, assessment));
|
||||||
|
assessmentRepository.save(assessment);
|
||||||
|
|
||||||
|
return assessment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Submission getNextSubmission(final Assessment assessment, final Submission currSubmission) {
|
||||||
|
if (currSubmission == null) {
|
||||||
|
if (assessment.isCompleted()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question firstQuestion = assessment.getQuestions().stream().findFirst().get();
|
||||||
|
final Submission submissionToReturn = new Submission(firstQuestion, firstQuestion.getContent(), Map.of(), SubmissionStatus.FAIL, assessment);
|
||||||
|
assessment.getSubmissions().add(submissionToReturn);
|
||||||
|
assessmentRepository.save(assessment);
|
||||||
|
|
||||||
|
return submissionToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question currQuestion = currSubmission.getQuestion();
|
||||||
|
int idx = assessment.getQuestions().indexOf(currQuestion);
|
||||||
|
|
||||||
|
if (idx == assessment.getQuestions().size() - 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question nextQuestion = assessment.getQuestions().get(idx + 1);
|
||||||
|
|
||||||
|
final Optional<Submission> submissionToReturn = assessment.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(nextQuestion))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
final Submission result;
|
||||||
|
if (submissionToReturn.isEmpty()) {
|
||||||
|
result = new Submission(nextQuestion, nextQuestion.getContent(), Map.of(), SubmissionStatus.FAIL, assessment);
|
||||||
|
assessment.getSubmissions().add(result);
|
||||||
|
} else {
|
||||||
|
result = submissionToReturn.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
assessmentRepository.save(assessment);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Submission getPrevSubmission(final Assessment assessment, final Submission currSubmission) {
|
||||||
|
if (currSubmission == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question currQuestion = currSubmission.getQuestion();
|
||||||
|
int idx = assessment.getQuestions().indexOf(currQuestion);
|
||||||
|
|
||||||
|
if (idx == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question prevQuestion = assessment.getQuestions().get(idx - 1);
|
||||||
|
|
||||||
|
assessmentRepository.save(assessment);
|
||||||
|
|
||||||
|
|
||||||
|
return assessment.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(prevQuestion))
|
||||||
|
.findFirst().orElseThrow(() -> new IllegalStateException("submission invalid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assessment completeAssessment(final UUID id, final Submission submission) {
|
||||||
|
Assessment assessment = assessmentRepository.findById(id).get();
|
||||||
|
Optional<AssessmentEvent> completed = assessment.getAssessmentEvents().stream()
|
||||||
|
.filter(e -> e.getStatus() == AssessmentStatus.COMPLETED)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (completed.isPresent()) {
|
||||||
|
return assessment;
|
||||||
|
}
|
||||||
|
|
||||||
|
assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.COMPLETED, assessment));
|
||||||
|
assessmentRepository.save(assessment);
|
||||||
|
|
||||||
|
return assessment;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.primefactorsolutions.service;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.service.compiler.InMemoryClass;
|
||||||
|
import com.primefactorsolutions.service.compiler.InMemoryFileManager;
|
||||||
|
import com.primefactorsolutions.service.compiler.JavaSourceFromString;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.tools.DiagnosticCollector;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class CompilerService {
|
||||||
|
private static final Map<Boolean, String> RESULT_MESSAGE = Map.of(Boolean.TRUE, "OK", Boolean.FALSE, "ERROR");
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public Optional<String> doCompile(final String javaCode) {
|
||||||
|
final String qualifiedClassName = "com.primefactorsolutions.TestClass";
|
||||||
|
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
|
||||||
|
final InMemoryFileManager manager = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null));
|
||||||
|
|
||||||
|
final List<JavaFileObject> sourceFiles = Collections.singletonList(new JavaSourceFromString(qualifiedClassName, javaCode));
|
||||||
|
final JavaCompiler.CompilationTask task = compiler.getTask(null, manager, diagnostics,
|
||||||
|
List.of("-proc:full", "-Xlint:-options"), null, sourceFiles);
|
||||||
|
|
||||||
|
boolean result = task.call();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
final String errors = diagnostics.getDiagnostics().stream()
|
||||||
|
.map(String::valueOf)
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
|
||||||
|
return Optional.of(errors);
|
||||||
|
} else {
|
||||||
|
final ClassLoader classLoader = manager.getClassLoader(null);
|
||||||
|
final Class<?> clazz = classLoader.loadClass(qualifiedClassName);
|
||||||
|
final InMemoryClass instanceOfClass = (InMemoryClass) clazz.newInstance();
|
||||||
|
final Map<String, Boolean> results = instanceOfClass.runCode();
|
||||||
|
|
||||||
|
return Optional.of(results.entrySet().stream()
|
||||||
|
.map(e -> String.format("%-50s ... %4s", e.getKey(), RESULT_MESSAGE.get(e.getValue())))
|
||||||
|
.collect(Collectors.joining("\n")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.primefactorsolutions.service;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.AppUser;
|
||||||
|
import com.primefactorsolutions.repositories.UserRepository;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Data
|
||||||
|
public class UserService {
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
|
public AppUser createOrUpdate(final AppUser assessment) {
|
||||||
|
final AppUser saved = userRepository.save(assessment);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AppUser> getUsers() {
|
||||||
|
return userRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppUser getUser(final UUID id) {
|
||||||
|
return userRepository.findById(id).orElse(null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.primefactorsolutions.service.compiler;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface InMemoryClass {
|
||||||
|
|
||||||
|
Map<String, Boolean> runCode();
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.primefactorsolutions.service.compiler;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class InMemoryClassLoader extends ClassLoader {
|
||||||
|
|
||||||
|
private final InMemoryFileManager manager;
|
||||||
|
|
||||||
|
public InMemoryClassLoader(ClassLoader parent, InMemoryFileManager manager) {
|
||||||
|
super(parent);
|
||||||
|
this.manager = requireNonNull(manager, "manager must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
Map<String, JavaClassAsBytes> compiledClasses = manager
|
||||||
|
.getBytesMap();
|
||||||
|
|
||||||
|
if (compiledClasses.containsKey(name)) {
|
||||||
|
byte[] bytes = compiledClasses.get(name)
|
||||||
|
.getBytes();
|
||||||
|
return defineClass(name, bytes, 0, bytes.length);
|
||||||
|
} else {
|
||||||
|
throw new ClassNotFoundException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.primefactorsolutions.service.compiler;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.tools.FileObject;
|
||||||
|
import javax.tools.ForwardingJavaFileManager;
|
||||||
|
import javax.tools.JavaFileManager;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.JavaFileObject.Kind;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
|
||||||
|
public class InMemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
|
||||||
|
|
||||||
|
private final Map<String, JavaClassAsBytes> compiledClasses;
|
||||||
|
private final ClassLoader loader;
|
||||||
|
|
||||||
|
public InMemoryFileManager(StandardJavaFileManager standardManager) {
|
||||||
|
super(standardManager);
|
||||||
|
this.compiledClasses = new Hashtable<>();
|
||||||
|
this.loader = new InMemoryClassLoader(this.getClass()
|
||||||
|
.getClassLoader(),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get the class loader for our compiled class. It creates an anonymous class extending
|
||||||
|
* the SecureClassLoader which uses the byte code created by the compiler and stored in the
|
||||||
|
* JavaClassObject, and returns the Class for it
|
||||||
|
*
|
||||||
|
* @param location where to place or search for file objects.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ClassLoader getClassLoader(Location location) {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind,
|
||||||
|
FileObject sibling) {
|
||||||
|
|
||||||
|
JavaClassAsBytes classAsBytes = new JavaClassAsBytes(
|
||||||
|
className, kind);
|
||||||
|
compiledClasses.put(className, classAsBytes);
|
||||||
|
|
||||||
|
return classAsBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, JavaClassAsBytes> getBytesMap() {
|
||||||
|
return compiledClasses;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.primefactorsolutions.service.compiler;
|
||||||
|
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
public class JavaClassAsBytes extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
protected ByteArrayOutputStream bos =
|
||||||
|
new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
public JavaClassAsBytes(String name, Kind kind) {
|
||||||
|
super(URI.create("string:///" + name.replace('.', '/')
|
||||||
|
+ kind.extension), kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBytes() {
|
||||||
|
return bos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream openOutputStream() {
|
||||||
|
return bos;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.primefactorsolutions.service.compiler;
|
||||||
|
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class JavaSourceFromString extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
private String sourceCode;
|
||||||
|
|
||||||
|
public JavaSourceFromString(String name, String sourceCode) {
|
||||||
|
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension),
|
||||||
|
Kind.SOURCE);
|
||||||
|
this.sourceCode = requireNonNull(sourceCode, "sourceCode must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||||
|
return sourceCode;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.Assessment;
|
||||||
|
import com.primefactorsolutions.service.AssessmentService;
|
||||||
|
import com.vaadin.flow.component.Component;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.router.BeforeEvent;
|
||||||
|
import com.vaadin.flow.router.HasUrlParameter;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.vaadin.firitin.form.BeanValidationForm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SpringComponent
|
||||||
|
@Scope("prototype")
|
||||||
|
@PageTitle("Assessments")
|
||||||
|
@Route(value = "/assessments", layout = MainLayout.class)
|
||||||
|
public class AssessmentView extends BeanValidationForm<Assessment> implements HasUrlParameter<String> {
|
||||||
|
private final AssessmentService assessmentService;
|
||||||
|
|
||||||
|
private final TextField appUserName = new TextField();
|
||||||
|
|
||||||
|
public AssessmentView(AssessmentService assessmentService) {
|
||||||
|
super(Assessment.class);
|
||||||
|
setEntityWithEnabledSave(new Assessment());
|
||||||
|
this.assessmentService = assessmentService;
|
||||||
|
|
||||||
|
setSavedHandler((SavedHandler<Assessment>) assessment -> {
|
||||||
|
System.out.println(assessment);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||||
|
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
||||||
|
var assessment = assessmentService.getAssessment(UUID.fromString(s));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Component> getFormComponents() {
|
||||||
|
return List.of(appUserName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.Assessment;
|
||||||
|
import com.primefactorsolutions.service.AssessmentService;
|
||||||
|
import com.vaadin.flow.component.html.Main;
|
||||||
|
import com.vaadin.flow.data.provider.DataProvider;
|
||||||
|
import com.vaadin.flow.data.provider.DataProviderListener;
|
||||||
|
import com.vaadin.flow.data.provider.Query;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.shared.Registration;
|
||||||
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.vaadin.firitin.components.grid.VGrid;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@SpringComponent
|
||||||
|
@Scope("prototype")
|
||||||
|
@PageTitle("Assessments")
|
||||||
|
@Route(value = "/assessments", layout = MainLayout.class)
|
||||||
|
public class AssessmentsListView extends Main {
|
||||||
|
|
||||||
|
public AssessmentsListView(final AssessmentService assessmentService) {
|
||||||
|
final VGrid<Assessment> grid = new VGrid<>(Assessment.class);
|
||||||
|
grid.setDataProvider(new DataProvider<Assessment, Object>() {
|
||||||
|
@Override
|
||||||
|
public boolean isInMemory() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size(Query<Assessment, Object> query) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<Assessment> fetch(Query<Assessment, Object> query) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshItem(Assessment assessment) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAll() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Registration addDataProviderListener(DataProviderListener<Assessment> dataProviderListener) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add(grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Text;
|
||||||
|
import com.vaadin.flow.component.html.Main;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
|
||||||
|
@PageTitle("Assessment")
|
||||||
|
@Route(value = "/evaluation/completed", layout = MainLayout.class)
|
||||||
|
public class EvaluationCompletedView extends Main {
|
||||||
|
public EvaluationCompletedView() {
|
||||||
|
add(new Text("La evaluacion ha sido completada. Nos contactaremos con usted."));
|
||||||
|
}
|
||||||
|
}
|
414
src/main/java/com/primefactorsolutions/views/EvaluationView.java
Normal file
414
src/main/java/com/primefactorsolutions/views/EvaluationView.java
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.flowingcode.vaadin.addons.simpletimer.SimpleTimer;
|
||||||
|
import com.hilerio.ace.AceEditor;
|
||||||
|
import com.hilerio.ace.AceMode;
|
||||||
|
import com.hilerio.ace.AceTheme;
|
||||||
|
import com.primefactorsolutions.model.*;
|
||||||
|
import com.primefactorsolutions.service.AssessmentService;
|
||||||
|
import com.primefactorsolutions.service.CompilerService;
|
||||||
|
import com.vaadin.flow.component.*;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.contextmenu.MenuItem;
|
||||||
|
import com.vaadin.flow.component.dialog.Dialog;
|
||||||
|
import com.vaadin.flow.component.html.*;
|
||||||
|
import com.vaadin.flow.component.html.DescriptionList.Description;
|
||||||
|
import com.vaadin.flow.component.html.DescriptionList.Term;
|
||||||
|
import com.vaadin.flow.component.icon.Icon;
|
||||||
|
import com.vaadin.flow.component.menubar.MenuBar;
|
||||||
|
import com.vaadin.flow.component.menubar.MenuBarVariant;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
|
import com.vaadin.flow.component.notification.NotificationVariant;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.router.*;
|
||||||
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Background;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Display;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Flex;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.FlexDirection;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.FontWeight;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Height;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Overflow;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@PageTitle("Evaluacion")
|
||||||
|
@SpringComponent
|
||||||
|
@Scope("prototype")
|
||||||
|
@Route(value = "/evaluation", layout = MainLayout.class)
|
||||||
|
public class EvaluationView extends Main implements HasUrlParameter<String> {
|
||||||
|
|
||||||
|
final CompilerService compilerService;
|
||||||
|
final AssessmentService assessmentService;
|
||||||
|
|
||||||
|
AceEditor questionEditor = null;
|
||||||
|
Dialog dialog = null;
|
||||||
|
Dialog completeDialog = null;
|
||||||
|
AceEditor result = null;
|
||||||
|
|
||||||
|
Assessment assessment = null;
|
||||||
|
Submission currSubmission = null;
|
||||||
|
Boolean isCompleted = false;
|
||||||
|
|
||||||
|
Button start = null;
|
||||||
|
MenuItem prev = null;
|
||||||
|
MenuItem next = null;
|
||||||
|
Section sidebar = null;
|
||||||
|
SimpleTimer timer = null;
|
||||||
|
|
||||||
|
DescriptionList dl = null;
|
||||||
|
|
||||||
|
Section editorSection = null;
|
||||||
|
Section startSection = null;
|
||||||
|
|
||||||
|
Section completedSection = null;
|
||||||
|
|
||||||
|
public EvaluationView(final CompilerService compilerService, final AssessmentService assessmentService) {
|
||||||
|
this.compilerService = compilerService;
|
||||||
|
this.assessmentService = assessmentService;
|
||||||
|
|
||||||
|
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
||||||
|
|
||||||
|
initStartSection();
|
||||||
|
initCompletedSection();
|
||||||
|
initEditorSection();
|
||||||
|
initResultDialog();
|
||||||
|
initCompleteDialog();
|
||||||
|
initSidebar();
|
||||||
|
|
||||||
|
add(completedSection, startSection, editorSection, sidebar, dialog);
|
||||||
|
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initResultDialog() {
|
||||||
|
dialog = new Dialog();
|
||||||
|
dialog.setHeaderTitle("Resultados");
|
||||||
|
|
||||||
|
result = new AceEditor();
|
||||||
|
result.setTheme(AceTheme.xcode);
|
||||||
|
result.setMode(AceMode.text);
|
||||||
|
result.setFontSize(12);
|
||||||
|
result.setHeight("100%");
|
||||||
|
result.setWidth("100%");
|
||||||
|
result.setReadOnly(true);
|
||||||
|
result.setMinlines(20);
|
||||||
|
result.setMaxlines(30);
|
||||||
|
result.setDisplayIndentGuides(false);
|
||||||
|
result.setShowGutter(false);
|
||||||
|
|
||||||
|
final VerticalLayout dialogLayout = new VerticalLayout(result);
|
||||||
|
dialogLayout.setPadding(false);
|
||||||
|
dialogLayout.setSpacing(false);
|
||||||
|
dialogLayout.setAlignItems(FlexComponent.Alignment.STRETCH);
|
||||||
|
dialogLayout.getStyle()
|
||||||
|
.set("width", "800px")
|
||||||
|
.set("max-width", "100%");
|
||||||
|
|
||||||
|
dialog.add(dialogLayout);
|
||||||
|
|
||||||
|
final Button saveButton = new Button("Guardar y Siguiente", e -> {
|
||||||
|
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||||
|
goToNext();
|
||||||
|
dialog.close();
|
||||||
|
});
|
||||||
|
saveButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
final Button closeButton = new Button("Cerrar", e -> dialog.close());
|
||||||
|
|
||||||
|
dialog.getFooter().add(closeButton, saveButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCompleteDialog() {
|
||||||
|
completeDialog = new Dialog();
|
||||||
|
completeDialog.setHeaderTitle("Terminar Evaluacion");
|
||||||
|
|
||||||
|
final VerticalLayout dialogLayout = new VerticalLayout(new Text("Desea terminar la evaluacion? No podra editar las respuestas despues de terminar."));
|
||||||
|
dialogLayout.setPadding(false);
|
||||||
|
dialogLayout.setSpacing(false);
|
||||||
|
dialogLayout.setAlignItems(FlexComponent.Alignment.STRETCH);
|
||||||
|
dialogLayout.getStyle()
|
||||||
|
.set("width", "800px")
|
||||||
|
.set("max-width", "100%");
|
||||||
|
|
||||||
|
completeDialog.add(dialogLayout);
|
||||||
|
|
||||||
|
final Button completeButton = new Button("Terminar", e -> {
|
||||||
|
completeDialog.close();
|
||||||
|
this.assessment = assessmentService.completeAssessment(assessment.getId(), currSubmission);
|
||||||
|
goToCompleted();
|
||||||
|
updateUI();
|
||||||
|
});
|
||||||
|
completeButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
final Button closeButton = new Button("Cerrar", e -> completeDialog.close());
|
||||||
|
|
||||||
|
completeDialog.getFooter().add(closeButton, completeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initEditorSection() {
|
||||||
|
editorSection = new Section();
|
||||||
|
editorSection.addClassNames(Display.FLEX, FlexDirection.COLUMN, Flex.GROW, Height.FULL);
|
||||||
|
questionEditor = getCodeEditor();
|
||||||
|
|
||||||
|
final MenuBar runMenuBar = new MenuBar();
|
||||||
|
runMenuBar.addThemeVariants(MenuBarVariant.LUMO_PRIMARY);
|
||||||
|
runMenuBar.addItem("Verificar/Ejecutar", (ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
|
final String javaCode = questionEditor.getValue();
|
||||||
|
final Optional<String> result = this.compilerService.doCompile(javaCode);
|
||||||
|
|
||||||
|
if (result.isPresent()) {
|
||||||
|
this.result.setValue(result.get());
|
||||||
|
this.dialog.open();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuBar navMenuBar = new MenuBar();
|
||||||
|
prev = navMenuBar.addItem("Anterior pregunta", (ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
|
System.out.println(">>> prev");
|
||||||
|
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||||
|
this.currSubmission = this.assessmentService.getPrevSubmission(assessment, this.currSubmission);
|
||||||
|
updateUI();
|
||||||
|
});
|
||||||
|
next = navMenuBar.addItem("Siguiente pregunta", (ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
|
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||||
|
goToNext();
|
||||||
|
});
|
||||||
|
|
||||||
|
final Div menuBar = new Div();
|
||||||
|
menuBar.add(runMenuBar, navMenuBar);
|
||||||
|
|
||||||
|
setInlineBlock(runMenuBar);
|
||||||
|
setInlineBlock(navMenuBar);
|
||||||
|
|
||||||
|
editorSection.add(menuBar, questionEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCompletedSection() {
|
||||||
|
completedSection = new Section();
|
||||||
|
completedSection.addClassNames(Display.FLEX, FlexDirection.COLUMN, Flex.GROW, Height.FULL);
|
||||||
|
completedSection.setVisible(false);
|
||||||
|
Div completedHelp = new Div();
|
||||||
|
completedHelp.add(new Text("Evaluacion ha sido completada. Gracias!"));
|
||||||
|
|
||||||
|
completedSection.add(completedHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initStartSection() {
|
||||||
|
startSection = new Section();
|
||||||
|
startSection.addClassNames(Display.FLEX, FlexDirection.COLUMN, Flex.GROW, Height.FULL);
|
||||||
|
|
||||||
|
Div startHelp = new Div();
|
||||||
|
startHelp.add(new Text("Bienvenido(a) al examen de evaluacion de PFS. Apriete el boton 'Empezar' para empezar la evaluacion. Tiene 30 minutos para completar."));
|
||||||
|
startHelp.add(new HtmlComponent("br"));
|
||||||
|
startHelp.add(new Text("Las preguntas son de implementacion de codigo en JAVA. Las preguntas deben poder compilar y pasar los tests incluidos en el codigo. Puede pasar un pregunta o volver a una pregunta anterior."));
|
||||||
|
|
||||||
|
TextField tf = new TextField();
|
||||||
|
tf.setLabel("Ingrese su email (donde recibio el link de la evaluacion):");
|
||||||
|
|
||||||
|
start = new Button("Empezar");
|
||||||
|
start.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
|
start.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||||
|
System.out.println(">>> start");
|
||||||
|
this.assessment = this.assessmentService.startAssessment(this.assessment.getId());
|
||||||
|
|
||||||
|
if (tf.getValue().trim().equalsIgnoreCase(this.assessment.getAppUser().getEmail())) {
|
||||||
|
this.currSubmission = this.assessmentService.getNextSubmission(assessment, this.currSubmission);
|
||||||
|
updateUI();
|
||||||
|
} else {
|
||||||
|
Notification notification = new Notification();
|
||||||
|
notification.addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
notification.setPosition(Notification.Position.TOP_CENTER);
|
||||||
|
|
||||||
|
Div text = new Div(new Text("Email invalido. Verifique que el email corresponde al email donde recibio el enlace a la evaluacion."));
|
||||||
|
|
||||||
|
Button closeButton = new Button(new Icon("lumo", "cross"));
|
||||||
|
closeButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);
|
||||||
|
closeButton.setAriaLabel("Close");
|
||||||
|
closeButton.addClickListener(event -> {
|
||||||
|
notification.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
HorizontalLayout layout = new HorizontalLayout(text, closeButton);
|
||||||
|
layout.setAlignItems(FlexComponent.Alignment.CENTER);
|
||||||
|
|
||||||
|
notification.add(layout);
|
||||||
|
notification.open();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
startSection.add(startHelp, tf, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private AceEditor getCodeEditor() {
|
||||||
|
final AceEditor questionEditor;
|
||||||
|
questionEditor = new AceEditor();
|
||||||
|
questionEditor.setTheme(AceTheme.xcode);
|
||||||
|
questionEditor.setMode(AceMode.java);
|
||||||
|
questionEditor.setFontSize(15);
|
||||||
|
questionEditor.setHeight("100%");
|
||||||
|
questionEditor.setWidth("100%");
|
||||||
|
|
||||||
|
questionEditor.setReadOnly(false);
|
||||||
|
questionEditor.setShowInvisibles(true);
|
||||||
|
questionEditor.setShowGutter(false);
|
||||||
|
questionEditor.setShowPrintMargin(false);
|
||||||
|
questionEditor.setDisplayIndentGuides(false);
|
||||||
|
questionEditor.setUseWorker(false);
|
||||||
|
|
||||||
|
questionEditor.setSofttabs(true);
|
||||||
|
questionEditor.setTabSize(4);
|
||||||
|
questionEditor.setWrap(true);
|
||||||
|
questionEditor.setMinlines(20);
|
||||||
|
questionEditor.setMaxlines(30);
|
||||||
|
// aceEditor.setPlaceholder("... Edit ...");
|
||||||
|
questionEditor.setAutoComplete(true);
|
||||||
|
questionEditor.setCustomAutoCompletion(new String[] { "TEST", "TEST2", "TEST3" });
|
||||||
|
questionEditor.setHighlightActiveLine(true);
|
||||||
|
questionEditor.setHighlightSelectedWord(false);
|
||||||
|
return questionEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInlineBlock(MenuBar menuBar) {
|
||||||
|
menuBar.getStyle().set("display", "inline-block");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void goToNext() {
|
||||||
|
System.out.println(">>> next");
|
||||||
|
this.currSubmission = this.assessmentService.getNextSubmission(assessment, this.currSubmission);
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSidebar() {
|
||||||
|
sidebar = new Section();
|
||||||
|
sidebar.addClassNames(Background.CONTRAST_5, BoxSizing.BORDER, Display.FLEX, FlexDirection.COLUMN,
|
||||||
|
Flex.SHRINK_NONE, Overflow.AUTO, Padding.LARGE);
|
||||||
|
sidebar.setWidth("256px");
|
||||||
|
|
||||||
|
dl = new DescriptionList();
|
||||||
|
dl.addClassNames(Display.FLEX, FlexDirection.COLUMN, Gap.LARGE, Margin.Bottom.SMALL, Margin.Top.NONE,
|
||||||
|
FontSize.SMALL);
|
||||||
|
|
||||||
|
final Text text = new Text("Tiempo restante:");
|
||||||
|
|
||||||
|
timer = new SimpleTimer(0);
|
||||||
|
timer.setMinutes(true);
|
||||||
|
timer.addTimerEndEvent((ComponentEventListener<SimpleTimer.TimerEndedEvent>) timerEndedEvent -> {
|
||||||
|
Notification.show("Tiempo completado.", 5, Notification.Position.TOP_CENTER);
|
||||||
|
this.assessment = assessmentService.completeAssessment(assessment.getId(), currSubmission);
|
||||||
|
goToCompleted();
|
||||||
|
updateUI();
|
||||||
|
});
|
||||||
|
timer.setFractions(false);
|
||||||
|
|
||||||
|
final Button completeButton = new Button("Terminar evaluacion");
|
||||||
|
completeButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||||
|
completeButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||||
|
this.completeDialog.open();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add it all together
|
||||||
|
sidebar.add(dl, text, timer, completeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUI() {
|
||||||
|
if (currSubmission == null) {
|
||||||
|
editorSection.setVisible(false);
|
||||||
|
startSection.setVisible(true);
|
||||||
|
sidebar.setVisible(false);
|
||||||
|
} else {
|
||||||
|
questionEditor.setValue(this.currSubmission.getResponse());
|
||||||
|
editorSection.setVisible(true);
|
||||||
|
startSection.setVisible(false);
|
||||||
|
sidebar.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.assessment != null) {
|
||||||
|
prev.setEnabled(currSubmission != null && !assessment.isFirst(currSubmission));
|
||||||
|
next.setEnabled(currSubmission == null || !assessment.isLast(currSubmission));
|
||||||
|
|
||||||
|
if (this.assessment.isCompleted()) {
|
||||||
|
goToCompleted();
|
||||||
|
this.editorSection.setVisible(false);
|
||||||
|
this.sidebar.setVisible(false);
|
||||||
|
this.startSection.setVisible(false);
|
||||||
|
this.completedSection.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
||||||
|
dl.add(
|
||||||
|
createItem("Candidato:", assessment.getAppUser().getEmail()),
|
||||||
|
createItem("Hora comienzo:", Optional.ofNullable(assessment.getStartingTime())
|
||||||
|
.map(t -> ZonedDateTime.ofInstant(t, ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
||||||
|
.orElse("N/A"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.pause();
|
||||||
|
timer.setStartTime(this.assessment.getRemainingTimeSeconds());
|
||||||
|
timer.setMinutes(true);
|
||||||
|
timer.reset();
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Div createItem(String label, String value) {
|
||||||
|
return new Div(createTerm(label), createDescription(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// private Div createBadgeItem(String label, String value) {
|
||||||
|
// return new Div(createTerm(label), createDescription(value, "badge"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
private Term createTerm(String label) {
|
||||||
|
Term term = new Term(label);
|
||||||
|
term.addClassNames(FontWeight.MEDIUM, TextColor.SECONDARY);
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Description createDescription(String value, String... themeNames) {
|
||||||
|
Description desc = new Description(value);
|
||||||
|
desc.addClassName(Margin.Left.NONE);
|
||||||
|
|
||||||
|
for (String themeName : themeNames) {
|
||||||
|
desc.getElement().getThemeList().add(themeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParameter(BeforeEvent beforeEvent, String s) {
|
||||||
|
this.assessment = this.assessmentService.getAssessment(UUID.fromString(s));
|
||||||
|
|
||||||
|
if (this.assessment.isCompleted()) {
|
||||||
|
goToCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currSubmission = this.assessment.getSubmissions().isEmpty()
|
||||||
|
? null
|
||||||
|
: this.assessmentService.getNextSubmission(assessment, null);
|
||||||
|
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void goToCompleted() {
|
||||||
|
this.isCompleted = true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.primefactorsolutions.views;
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
import com.primefactorsolutions.views.codeeditor.CodeEditorView;
|
|
||||||
import com.vaadin.flow.component.applayout.AppLayout;
|
import com.vaadin.flow.component.applayout.AppLayout;
|
||||||
import com.vaadin.flow.component.applayout.DrawerToggle;
|
import com.vaadin.flow.component.applayout.DrawerToggle;
|
||||||
import com.vaadin.flow.component.html.Footer;
|
import com.vaadin.flow.component.html.Footer;
|
||||||
@ -9,10 +8,8 @@ import com.vaadin.flow.component.html.Header;
|
|||||||
import com.vaadin.flow.component.html.Span;
|
import com.vaadin.flow.component.html.Span;
|
||||||
import com.vaadin.flow.component.orderedlayout.Scroller;
|
import com.vaadin.flow.component.orderedlayout.Scroller;
|
||||||
import com.vaadin.flow.component.sidenav.SideNav;
|
import com.vaadin.flow.component.sidenav.SideNav;
|
||||||
import com.vaadin.flow.component.sidenav.SideNavItem;
|
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||||
import org.vaadin.lineawesome.LineAwesomeIcon;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main view is a top-level placeholder for other views.
|
* The main view is a top-level placeholder for other views.
|
||||||
@ -50,7 +47,7 @@ public class MainLayout extends AppLayout {
|
|||||||
private SideNav createNavigation() {
|
private SideNav createNavigation() {
|
||||||
SideNav nav = new SideNav();
|
SideNav nav = new SideNav();
|
||||||
|
|
||||||
nav.addItem(new SideNavItem("CodeEditor", CodeEditorView.class, LineAwesomeIcon.EDIT.create()));
|
//nav.addItem(new SideNavItem("CodeEditor", CodeEditorView.class, LineAwesomeIcon.EDIT.create()));
|
||||||
|
|
||||||
return nav;
|
return nav;
|
||||||
}
|
}
|
||||||
|
14
src/main/java/com/primefactorsolutions/views/MainView.java
Normal file
14
src/main/java/com/primefactorsolutions/views/MainView.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Text;
|
||||||
|
import com.vaadin.flow.component.html.Main;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
|
||||||
|
@PageTitle("Assessment")
|
||||||
|
@Route(value = "", layout = MainLayout.class)
|
||||||
|
public class MainView extends Main {
|
||||||
|
public MainView() {
|
||||||
|
add(new Text("welcome"));
|
||||||
|
}
|
||||||
|
}
|
51
src/main/java/com/primefactorsolutions/views/UserView.java
Normal file
51
src/main/java/com/primefactorsolutions/views/UserView.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.AppUser;
|
||||||
|
import com.primefactorsolutions.service.UserService;
|
||||||
|
import com.vaadin.flow.component.Component;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.router.BeforeEvent;
|
||||||
|
import com.vaadin.flow.router.HasUrlParameter;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.vaadin.firitin.form.BeanValidationForm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SpringComponent
|
||||||
|
@Scope("prototype")
|
||||||
|
@PageTitle("Assessments")
|
||||||
|
@Route(value = "/users", layout = MainLayout.class)
|
||||||
|
public class UserView extends BeanValidationForm<AppUser> implements HasUrlParameter<String> {
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
private final TextField appUserName = new TextField();
|
||||||
|
|
||||||
|
public UserView(UserService userService) {
|
||||||
|
super(AppUser.class);
|
||||||
|
setEntityWithEnabledSave(new AppUser("foo@bar.com", List.of()));
|
||||||
|
this.userService = userService;
|
||||||
|
|
||||||
|
setSavedHandler((SavedHandler<AppUser>) appUser -> {
|
||||||
|
System.out.println(appUser);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||||
|
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
||||||
|
var assessment = userService.getUser(UUID.fromString(s));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Component> getFormComponents() {
|
||||||
|
return List.of(appUserName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.primefactorsolutions.views;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.AppUser;
|
||||||
|
import com.vaadin.flow.component.html.Main;
|
||||||
|
import com.vaadin.flow.data.provider.DataProvider;
|
||||||
|
import com.vaadin.flow.data.provider.DataProviderListener;
|
||||||
|
import com.vaadin.flow.data.provider.Query;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.shared.Registration;
|
||||||
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.vaadin.firitin.components.grid.VGrid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@SpringComponent
|
||||||
|
@Scope("prototype")
|
||||||
|
@PageTitle("Users")
|
||||||
|
@Route(value = "/users", layout = MainLayout.class)
|
||||||
|
public class UsersListView extends Main {
|
||||||
|
|
||||||
|
public UsersListView() {
|
||||||
|
final VGrid<AppUser> grid = new VGrid<>(AppUser.class);
|
||||||
|
|
||||||
|
grid.setDataProvider(new DataProvider<AppUser, Object>() {
|
||||||
|
@Override
|
||||||
|
public boolean isInMemory() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size(Query<AppUser, Object> query) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<AppUser> fetch(Query<AppUser, Object> query) {
|
||||||
|
int limit = query.getLimit();
|
||||||
|
int pagerSize = query.getPageSize();
|
||||||
|
int page = query.getPage();
|
||||||
|
return Stream.of(new AppUser("foo@bar.com", List.of()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshItem(AppUser appUser) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAll() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Registration addDataProviderListener(DataProviderListener<AppUser> dataProviderListener) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add(grid);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
@ -6,5 +6,13 @@ spring.mustache.check-template-location = false
|
|||||||
vaadin.launch-browser=true
|
vaadin.launch-browser=true
|
||||||
# To improve the performance during development.
|
# To improve the performance during development.
|
||||||
# For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters
|
# For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters
|
||||||
vaadin.allowed-packages = com.vaadin,org.vaadin,com.primefactorsolutions
|
vaadin.allowed-packages = com.vaadin,org.vaadin,com.primefactorsolutions,com.hilerio.ace,com.flowingcode.vaadin
|
||||||
|
|
||||||
|
|
||||||
|
spring.datasource.url=jdbc:h2:mem:testdb
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=sa
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||||
spring.jpa.defer-datasource-initialization = true
|
spring.jpa.defer-datasource-initialization = true
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
10
src/main/resources/data.sql
Normal file
10
src/main/resources/data.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
insert into app_user (id, version, email) values ('23471ab3-f639-4d2b-9541-7227f4ea7ee6', 1, 'foo@bar.com');
|
||||||
|
|
||||||
|
insert into question (id, version, content) values ('a7e00ff8-da41-4624-b31c-1b13c3f2e3ae', 1, 'foo bar');
|
||||||
|
insert into question (id, version, content) values ('8a4b213c-ca81-4c38-b56d-d7028c2dde88', 1, 'foo buzz');
|
||||||
|
|
||||||
|
insert into assessment(id, version, app_user_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 1, '23471ab3-f639-4d2b-9541-7227f4ea7ee6');
|
||||||
|
|
||||||
|
insert into ASSESSMENT_QUESTIONS (assessment_id, questions_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 'a7e00ff8-da41-4624-b31c-1b13c3f2e3ae');
|
||||||
|
|
||||||
|
insert into ASSESSMENT_QUESTIONS (assessment_id, questions_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', '8a4b213c-ca81-4c38-b56d-d7028c2dde88');
|
55
src/main/resources/questions/fibonaci.java.txt
Normal file
55
src/main/resources/questions/fibonaci.java.txt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package com.primefactorsolutions;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.service.compiler.InMemoryClass;
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TestClass implements InMemoryClass {
|
||||||
|
|
||||||
|
// ------------ IMPLEMENTAR AQUI --------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static int getFibonaci(int n) {
|
||||||
|
// TODO: implementar aca
|
||||||
|
throw new RuntimeException("not implemented yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------- NO MODIFICAR DESDE ESTA LINEA --------------------
|
||||||
|
|
||||||
|
public static class Tests {
|
||||||
|
public static Map.Entry<String, Boolean> testFibonaciSingle() {
|
||||||
|
boolean result = getFibonaci(1) == 0;
|
||||||
|
|
||||||
|
return Map.entry("fibonaci primer", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map.Entry<String, Boolean> testFibonaciInvalido() {
|
||||||
|
try {
|
||||||
|
getFibonaci(-1);
|
||||||
|
return Map.entry("palindrome vacio es valido", false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Map.entry("palindrome vacio es valido", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Boolean> runCode() {
|
||||||
|
Map<String, Boolean> results = Arrays.stream(Tests.class.getDeclaredMethods())
|
||||||
|
.map(m -> {
|
||||||
|
try {
|
||||||
|
return (Map.Entry<String, Boolean>) m.invoke(null);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
60
src/main/resources/questions/palindroma.java.txt
Normal file
60
src/main/resources/questions/palindroma.java.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package com.primefactorsolutions;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.service.compiler.InMemoryClass;
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TestClass implements InMemoryClass {
|
||||||
|
|
||||||
|
// ------------ IMPLEMENTAR AQUI --------------------------------
|
||||||
|
|
||||||
|
public static String getPalindroma(String s) {
|
||||||
|
return "TODO";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------- NO MODIFICAR DESDE ESTA LINEA --------------------
|
||||||
|
|
||||||
|
public static class Tests {
|
||||||
|
public static Map.Entry<String, Boolean> testPalindromaValido() {
|
||||||
|
boolean result = getPalindroma("Ab").equals("ABBA");
|
||||||
|
|
||||||
|
return Map.entry("palindrome es valido", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map.Entry<String, Boolean> testPalindromaVacio() {
|
||||||
|
boolean result = getPalindroma("").equals("");
|
||||||
|
|
||||||
|
return Map.entry("palindrome vacio es valido", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map.Entry<String, Boolean> testPalindromaUnico() {
|
||||||
|
boolean result = getPalindroma("z").equals("ZZ");
|
||||||
|
|
||||||
|
return Map.entry("palindrome una solo caracter es valido", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map.Entry<String, Boolean> testPalindromaNull() {
|
||||||
|
boolean result = getPalindroma(null) == null;
|
||||||
|
|
||||||
|
return Map.entry("palindrome null es valido", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Boolean> runCode() {
|
||||||
|
Map<String, Boolean> results = Arrays.stream(Tests.class.getDeclaredMethods())
|
||||||
|
.map(m -> {
|
||||||
|
try {
|
||||||
|
return (Map.Entry<String, Boolean>) m.invoke(null);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user