├── src ├── main │ ├── resources │ │ ├── build.properties │ │ ├── public │ │ │ ├── style │ │ │ │ ├── login.less │ │ │ │ ├── expercise.less │ │ │ │ ├── footer.less │ │ │ │ ├── tagListing.less │ │ │ │ ├── addUpdateChallenge.less │ │ │ │ ├── show-hint.css │ │ │ │ ├── profile.less │ │ │ │ ├── index.less │ │ │ │ ├── avatars.less │ │ │ │ ├── bootstrap-tagsinput.css │ │ │ │ └── challenge.less │ │ │ ├── img │ │ │ │ ├── java8-logo.png │ │ │ │ ├── python-logo.png │ │ │ │ ├── expercise-logo.png │ │ │ │ ├── sprite-green.png │ │ │ │ ├── sprite-orange.png │ │ │ │ ├── javascript-logo.png │ │ │ │ ├── expercise-logo-rounded.png │ │ │ │ ├── flags │ │ │ │ │ └── tr.svg │ │ │ │ └── ATTRIBUTION.md │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── black-rose.ttf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ └── js │ │ │ │ ├── locale.js │ │ │ │ ├── profile.js │ │ │ │ ├── home.js │ │ │ │ ├── header.js │ │ │ │ ├── expercise.js │ │ │ │ ├── bootstrapper.js │ │ │ │ ├── forgottenPassword.js │ │ │ │ ├── utils.js │ │ │ │ ├── tagListing.js │ │ │ │ └── codemirror │ │ │ │ └── anyword-hint.js │ │ ├── emails │ │ │ ├── emailLayout.html │ │ │ └── forgotMyPasswordEmail.html │ │ ├── messagesForEmails_en.properties │ │ ├── messagesForEmails_pt.properties │ │ ├── messagesForEmails_tr.properties │ │ ├── templates │ │ │ ├── fragments │ │ │ │ ├── inputHiddens.html │ │ │ │ └── footer.html │ │ │ ├── tag │ │ │ │ └── tagsList.html │ │ │ ├── error │ │ │ │ └── errorPage.html │ │ │ └── user │ │ │ │ └── forgotMyPassword.html │ │ ├── db │ │ │ └── changelog │ │ │ │ ├── change-sets │ │ │ │ ├── change-set-1.xml │ │ │ │ └── dev-change-set-1.xml │ │ │ │ └── changelog-master.xml │ │ ├── application-dev.properties │ │ ├── application-prod.properties │ │ └── application.properties │ └── java │ │ └── com │ │ └── expercise │ │ ├── enums │ │ ├── ManagementMode.java │ │ ├── ChallengeListingMode.java │ │ ├── UserRole.java │ │ ├── ProgrammingLanguage.java │ │ ├── SocialSignInProvider.java │ │ └── DataType.java │ │ ├── domain │ │ ├── token │ │ │ ├── TokenType.java │ │ │ └── Token.java │ │ ├── challenge │ │ │ ├── ChallengeType.java │ │ │ ├── ChallengeInputType.java │ │ │ ├── TestCaseInputValue.java │ │ │ ├── TestCase.java │ │ │ ├── Solution.java │ │ │ └── UserPoint.java │ │ ├── PrioritizedEntity.java │ │ ├── user │ │ │ ├── SocialUserDetails.java │ │ │ └── RememberMeToken.java │ │ ├── quote │ │ │ └── Quote.java │ │ └── BaseEntity.java │ │ ├── utils │ │ ├── caching │ │ │ ├── Caching.java │ │ │ └── CachingSubject.java │ │ ├── Constants.java │ │ ├── EnvironmentUtils.java │ │ ├── collection │ │ │ ├── MapBuilder.java │ │ │ └── RandomElement.java │ │ ├── PasswordEncoder.java │ │ ├── Clock.java │ │ ├── validation │ │ │ ├── PasswordMatch.java │ │ │ ├── ValidationUtils.java │ │ │ ├── UniqueEmail.java │ │ │ ├── EmailUniquenessValidator.java │ │ │ ├── BaseValidator.java │ │ │ └── PasswordMatchValidator.java │ │ ├── UrlUtils.java │ │ ├── TextUtils.java │ │ ├── CookieUtils.java │ │ └── NumberUtils.java │ │ ├── service │ │ ├── util │ │ │ ├── Prioritized.java │ │ │ ├── PrioritySorter.java │ │ │ ├── UrlService.java │ │ │ └── TokenService.java │ │ ├── cache │ │ │ ├── JsonRedisTemplate.java │ │ │ └── ObjectRedisTemplate.java │ │ ├── email │ │ │ ├── EmailSenderService.java │ │ │ ├── TemplateEngineWrapper.java │ │ │ ├── EmailTemplateProcessor.java │ │ │ ├── EmailService.java │ │ │ ├── model │ │ │ │ └── Email.java │ │ │ └── SendGridEmailSenderService.java │ │ ├── challenge │ │ │ ├── model │ │ │ │ ├── ChallengeSolutionStatus.java │ │ │ │ └── LeaderBoardModel.java │ │ │ ├── action │ │ │ │ ├── PreEvaluationAction.java │ │ │ │ ├── PreEvaluationExecutor.java │ │ │ │ ├── PostEvaluationAction.java │ │ │ │ ├── PostEvaluationExecutor.java │ │ │ │ └── postaction │ │ │ │ │ ├── GiveSuccessPointPostAction.java │ │ │ │ │ ├── InterpretationFailureCheckForTestCasesPostAction.java │ │ │ │ │ ├── PrepareChallengeUserSolutionsPostAction.java │ │ │ │ │ └── SaveUserTestCaseStatePostAction.java │ │ │ ├── ChallengeDisplayRule.java │ │ │ ├── LeaderBoardWarmUpUtil.java │ │ │ ├── LeaderBoardCalculatorService.java │ │ │ └── SolutionCountService.java │ │ ├── language │ │ │ ├── SignatureGenerator.java │ │ │ ├── SignatureGeneratorService.java │ │ │ ├── Python2SignatureGenerator.java │ │ │ ├── Python3SignatureGenerator.java │ │ │ └── JavaScriptSignatureGenerator.java │ │ ├── user │ │ │ ├── CurrentUserHolder.java │ │ │ ├── SocialUserDetailsProvider.java │ │ │ ├── SocialUserDetailsHelper.java │ │ │ └── PersistentRememberMeTokenRepositoryService.java │ │ ├── notification │ │ │ ├── SlackMessage.java │ │ │ └── SlackNotificationService.java │ │ ├── configuration │ │ │ └── Configurations.java │ │ └── quote │ │ │ └── QuoteService.java │ │ ├── interpreter │ │ ├── TestCaseResult.java │ │ ├── InterpreterFailureType.java │ │ ├── InterpreterException.java │ │ ├── InterpretRequest.java │ │ ├── InterpreterClient.java │ │ ├── InterpretResponse.java │ │ ├── InterpreterResult.java │ │ ├── Interpreter.java │ │ ├── TestCasesWithSourceModel.java │ │ ├── TestCaseWithResult.java │ │ ├── TestCaseModel.java │ │ └── TestCasesWithSourceCacheModel.java │ │ ├── repository │ │ ├── quote │ │ │ └── QuoteRepository.java │ │ ├── BaseRepository.java │ │ ├── user │ │ │ ├── UserConnectionRepository.java │ │ │ ├── UserRepository.java │ │ │ ├── RememberMeTokenRepository.java │ │ │ └── TokenRepository.java │ │ └── challenge │ │ │ ├── UserPointRepository.java │ │ │ ├── SolutionRepository.java │ │ │ └── ChallengeRepository.java │ │ ├── configuration │ │ ├── SpringSessionRedisConfiguration.java │ │ ├── ResourceBundleMessageSources.java │ │ └── redis │ │ │ └── EmbeddedRedis.java │ │ ├── controller │ │ ├── BaseManagementController.java │ │ ├── user │ │ │ ├── model │ │ │ │ ├── EmailRequestModel.java │ │ │ │ ├── PasswordResetModel.java │ │ │ │ ├── PasswordModel.java │ │ │ │ ├── ForgotMyPasswordResponse.java │ │ │ │ └── UserModel.java │ │ │ ├── SignInController.java │ │ │ └── management │ │ │ │ └── UserListingController.java │ │ ├── challenge │ │ │ ├── model │ │ │ │ ├── ChallengeResetModel.java │ │ │ │ ├── TagModel.java │ │ │ │ ├── SolutionFromUser.java │ │ │ │ └── SaveChallengeResponse.java │ │ │ ├── management │ │ │ │ ├── TagsManagementController.java │ │ │ │ └── ChallengeListManagementController.java │ │ │ ├── ChallengeListingController.java │ │ │ ├── StartCodingController.java │ │ │ └── TagsChallengeController.java │ │ ├── HomeController.java │ │ ├── utils │ │ │ └── BrowserCacheableContent.java │ │ ├── error │ │ │ └── ErrorController.java │ │ ├── leaderboard │ │ │ └── LeaderBoardController.java │ │ ├── RedirectUtils.java │ │ ├── caching │ │ │ └── CachingController.java │ │ └── MessagesForClientSideController.java │ │ ├── exception │ │ ├── ExperciseGenericException.java │ │ └── ExperciseJsonException.java │ │ └── Application.java └── test │ ├── resources │ ├── renderedEmails │ │ └── forgotMyPasswordEmail.html │ └── application.properties │ ├── java │ └── com │ │ └── expercise │ │ ├── testutils │ │ ├── builder │ │ │ ├── QuoteBuilder.java │ │ │ ├── BasePrioritizedEntityBuilder.java │ │ │ ├── BaseEntityBuilder.java │ │ │ ├── TestCaseInputValueBuilder.java │ │ │ ├── ChallengeInputTypeBuilder.java │ │ │ ├── TestCaseBuilder.java │ │ │ ├── UserPointBuilder.java │ │ │ ├── SolutionBuilder.java │ │ │ └── UserBuilder.java │ │ ├── matchers │ │ │ └── Matchers.java │ │ ├── FileTestUtils.java │ │ └── asserts │ │ │ └── Asserts.java │ │ ├── interpreter │ │ ├── InfiniteLoopTestInterpreter.java │ │ └── InterpreterTest.java │ │ ├── domain │ │ └── user │ │ │ └── UserTest.java │ │ ├── BaseSpringIntegrationTest.java │ │ ├── service │ │ ├── challenge │ │ │ └── action │ │ │ │ └── PreEvaluationExecutorTest.java │ │ ├── language │ │ │ ├── Python2SignatureGeneratorTest.java │ │ │ ├── JavaScriptSignatureGeneratorTest.java │ │ │ └── JavaSignatureGeneratorTest.java │ │ └── user │ │ │ └── UserServiceTest.java │ │ ├── controller │ │ ├── HomeControllerTest.java │ │ └── user │ │ │ └── management │ │ │ └── UserListingControllerTest.java │ │ └── utils │ │ ├── JsonUtilsTest.java │ │ └── CookieUtilsTest.java │ └── groovy │ └── com │ └── expercise │ ├── utils │ ├── NumberUtilsSpec.groovy │ └── UrlUtilsSpec.groovy │ ├── controller │ └── RedirectUtilsSpec.groovy │ └── service │ ├── util │ └── UrlServiceSpec.groovy │ └── email │ ├── SendGridEmailServiceSpec.groovy │ └── EmailTemplateProcessorSpec.groovy ├── .elasticbeanstalk ├── .ebextensions │ ├── nginx │ │ └── conf.d │ │ │ └── proxy.conf │ └── 00-set-spring-boot-port.config ├── Procfile └── config.yml ├── README.md ├── .gitignore └── init-dev-environment.sh /src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | build.id=-1 -------------------------------------------------------------------------------- /.elasticbeanstalk/.ebextensions/nginx/conf.d/proxy.conf: -------------------------------------------------------------------------------- 1 | client_max_body_size 10M; -------------------------------------------------------------------------------- /.elasticbeanstalk/Procfile: -------------------------------------------------------------------------------- 1 | web: java -Dspring.profiles.active=prod -Djava.security.egd=file:/dev/./urandom -jar coding-expercise.jar -------------------------------------------------------------------------------- /src/main/resources/public/style/login.less: -------------------------------------------------------------------------------- 1 | .rememberMeContainer { 2 | &.col-xs-2 { 3 | padding-left: 0; 4 | padding-right: 0; 5 | } 6 | } -------------------------------------------------------------------------------- /src/main/resources/public/img/java8-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/java8-logo.png -------------------------------------------------------------------------------- /src/main/resources/public/img/python-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/python-logo.png -------------------------------------------------------------------------------- /src/main/resources/public/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/main/resources/public/fonts/black-rose.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/black-rose.ttf -------------------------------------------------------------------------------- /src/main/resources/public/img/expercise-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/expercise-logo.png -------------------------------------------------------------------------------- /src/main/resources/public/img/sprite-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/sprite-green.png -------------------------------------------------------------------------------- /src/main/resources/public/img/sprite-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/sprite-orange.png -------------------------------------------------------------------------------- /src/main/resources/public/img/javascript-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/javascript-logo.png -------------------------------------------------------------------------------- /src/main/java/com/expercise/enums/ManagementMode.java: -------------------------------------------------------------------------------- 1 | package com.expercise.enums; 2 | 3 | public enum ManagementMode { 4 | 5 | Add, 6 | Update 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/domain/token/TokenType.java: -------------------------------------------------------------------------------- 1 | package com.expercise.domain.token; 2 | 3 | public enum TokenType { 4 | 5 | FORGOT_MY_PASSWORD 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/caching/Caching.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.caching; 2 | 3 | public interface Caching { 4 | 5 | void flush(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/resources/public/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/main/resources/public/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/main/resources/public/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/main/resources/public/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/main/resources/public/img/expercise-logo-rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/img/expercise-logo-rounded.png -------------------------------------------------------------------------------- /src/main/java/com/expercise/enums/ChallengeListingMode.java: -------------------------------------------------------------------------------- 1 | package com.expercise.enums; 2 | 3 | public enum ChallengeListingMode { 4 | 5 | Admin, 6 | User 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/util/Prioritized.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.util; 2 | 3 | public interface Prioritized { 4 | 5 | int getPriority(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /.elasticbeanstalk/.ebextensions/00-set-spring-boot-port.config: -------------------------------------------------------------------------------- 1 | option_settings: 2 | - namespace: aws:elasticbeanstalk:application:environment 3 | option_name: PORT 4 | value: 8080 -------------------------------------------------------------------------------- /src/main/resources/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/main/resources/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/main/resources/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/main/java/com/expercise/domain/challenge/ChallengeType.java: -------------------------------------------------------------------------------- 1 | package com.expercise.domain.challenge; 2 | 3 | public enum ChallengeType { 4 | 5 | ALGORITHM, 6 | CODE_KATA 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/public/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expercise/coding-expercise/HEAD/src/main/resources/public/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/main/java/com/expercise/interpreter/TestCaseResult.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | public enum TestCaseResult { 4 | 5 | NEW, 6 | PASSED, 7 | FAILED 8 | 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | coding-expercise 2 | ================ 3 | 4 | Learn to code. Code to make the dreams come true. 5 | 6 |  7 | -------------------------------------------------------------------------------- /src/main/resources/emails/emailLayout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |{ 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/challenge/model/ChallengeSolutionStatus.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.challenge.model; 2 | 3 | public enum ChallengeSolutionStatus { 4 | 5 | FAILED, 6 | TESTS_PASSED_BUT_NOT_COMPLETED_YET, 7 | CHALLENGE_COMPLETED 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/configuration/SpringSessionRedisConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.expercise.configuration; 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; 4 | 5 | @EnableRedisHttpSession 6 | public class SpringSessionRedisConfiguration { 7 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/cache/ObjectRedisTemplate.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.cache; 2 | 3 | import org.springframework.data.redis.core.RedisTemplate; 4 | 5 | import java.io.Serializable; 6 | 7 | public final class ObjectRedisTemplate extends RedisTemplate{ 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/renderedEmails/forgotMyPasswordEmail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello Ahmet Mehmet,
7 |Please click link below to reset your password.
8 | Reset Password 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/challenge/action/PreEvaluationAction.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.challenge.action; 2 | 3 | import com.expercise.service.challenge.model.ChallengeEvaluationContext; 4 | 5 | public interface PreEvaluationAction { 6 | 7 | void execute(ChallengeEvaluationContext context); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/resources/public/style/expercise.less: -------------------------------------------------------------------------------- 1 | @import "common.less"; 2 | @import "avatars.less"; 3 | @import "challenge.less"; 4 | @import "profile.less"; 5 | @import "index.less"; 6 | @import "header.less"; 7 | @import "footer.less"; 8 | @import "tagListing.less"; 9 | @import "addUpdateChallenge.less"; 10 | @import "login.less"; -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/BaseManagementController.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | @Controller 7 | @RequestMapping("/manage") 8 | public abstract class BaseManagementController { 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/testutils/builder/QuoteBuilder.java: -------------------------------------------------------------------------------- 1 | package com.expercise.testutils.builder; 2 | 3 | import com.expercise.domain.quote.Quote; 4 | 5 | public class QuoteBuilder extends BaseEntityBuilder{ 6 | 7 | @Override 8 | protected Quote doBuild() { 9 | return new Quote(); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/user/model/EmailRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.user.model; 2 | 3 | public class EmailRequestModel { 4 | 5 | private String email; 6 | 7 | public String getEmail() { 8 | return email; 9 | } 10 | 11 | public void setEmail(String email) { 12 | this.email = email; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/util/PrioritySorter.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.util; 2 | 3 | import java.util.Comparator; 4 | 5 | public class PrioritySorter implements Comparator{ 6 | 7 | @Override 8 | public int compare(Prioritized o1, Prioritized o2) { 9 | return Integer.compare(o1.getPriority(), o2.getPriority()); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/public/style/footer.less: -------------------------------------------------------------------------------- 1 | div#footer { 2 | margin-top: 20px; 3 | margin-bottom: 20px; 4 | text-align: center; 5 | text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); 6 | 7 | .text-muted { 8 | color: whitesmoke; 9 | } 10 | 11 | a { 12 | color: whitesmoke; 13 | text-decoration: none; 14 | font-size: 15px; 15 | font-weight: bold; 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/resources/templates/fragments/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/exception/ExperciseGenericException.java: -------------------------------------------------------------------------------- 1 | package com.expercise.exception; 2 | 3 | public class ExperciseGenericException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -4059537275690891978L; 6 | 7 | public ExperciseGenericException(String message, Throwable exception) { 8 | super(message, exception); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/BaseRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository; 2 | 3 | import com.expercise.domain.BaseEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.repository.NoRepositoryBean; 6 | 7 | @NoRepositoryBean 8 | public interface BaseRepository extends JpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/exception/ExperciseJsonException.java: -------------------------------------------------------------------------------- 1 | package com.expercise.exception; 2 | 3 | import java.io.IOException; 4 | 5 | public class ExperciseJsonException extends IOException { 6 | 7 | private static final long serialVersionUID = 5314405037914650141L; 8 | 9 | public ExperciseJsonException(String message, Throwable exception) { 10 | super(message, exception); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/user/UserConnectionRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.user; 2 | 3 | import com.expercise.domain.user.UserConnection; 4 | import com.expercise.repository.BaseRepository; 5 | 6 | public interface UserConnectionRepository extends BaseRepository { 7 | 8 | UserConnection findByProviderIdAndProviderUserId(String providerId, String providerUserId); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/change-sets/change-set-1.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/enums/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.expercise.enums; 2 | 3 | public enum UserRole { 4 | 5 | User("ROLE_USER"), 6 | Admin("ROLE_USER", "ROLE_ADMIN"); 7 | 8 | private String[] authorities; 9 | 10 | private UserRole(String... authorities) { 11 | this.authorities = authorities; 12 | } 13 | 14 | public String[] getAuthorities() { 15 | return authorities; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/interpreter/InterpreterFailureType.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | public enum InterpreterFailureType { 4 | 5 | NO_RESULT("interpreter.noResult"); 6 | 7 | private String messageKey; 8 | 9 | InterpreterFailureType(String messageKey) { 10 | this.messageKey = messageKey; 11 | } 12 | 13 | public String getMessageKey() { 14 | return messageKey; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/EnvironmentUtils.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils; 2 | 3 | public final class EnvironmentUtils { 4 | 5 | private EnvironmentUtils() { 6 | } 7 | 8 | public static boolean isProduction(String environment) { 9 | return "prod".equals(environment); 10 | } 11 | 12 | public static boolean isDevelopment(String environment) { 13 | return !isProduction(environment); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/interpreter/InfiniteLoopTestInterpreter.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | import com.expercise.service.challenge.model.ChallengeEvaluationContext; 4 | 5 | public class InfiniteLoopTestInterpreter extends Interpreter { 6 | 7 | @Override 8 | protected void interpretInternal(ChallengeEvaluationContext context) { 9 | while (true) { 10 | // Infinite loop 11 | } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/public/style/tagListing.less: -------------------------------------------------------------------------------- 1 | .tagList { 2 | text-align: center; 3 | margin-bottom: 15px; 4 | margin-top: 30px; 5 | 6 | a.tagLink { 7 | margin-right: 12px; 8 | font-weight: bold; 9 | font-size: 12px; 10 | line-height: 36px; 11 | 12 | &.x2 { 13 | font-size: 18px; 14 | } 15 | 16 | &.x3 { 17 | font-size: 24px; 18 | } 19 | 20 | &.x4 { 21 | font-size: 30px; 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/collection/MapBuilder.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.collection; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class MapBuilder{ 7 | 8 | private Map map = new HashMap<>(); 9 | 10 | public Map build() { 11 | return map; 12 | } 13 | 14 | public MapBuilder put(K key, V value) { 15 | map.put(key, value); 16 | return this; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/testutils/matchers/Matchers.java: -------------------------------------------------------------------------------- 1 | package com.expercise.testutils.matchers; 2 | 3 | import org.hamcrest.Matcher; 4 | 5 | import static org.hamcrest.Matchers.hasItem; 6 | import static org.hamcrest.Matchers.not; 7 | 8 | public final class Matchers { 9 | 10 | private Matchers() { 11 | } 12 | 13 | public static Matcher > notHasItem(T item) { 14 | return not(hasItem(item)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/language/SignatureGenerator.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.language; 2 | 3 | import com.expercise.domain.challenge.Challenge; 4 | import com.expercise.enums.ProgrammingLanguage; 5 | 6 | public interface SignatureGenerator { 7 | 8 | String[] LETTERS = new String[]{"a", "b", "c", "d", "e", "f", "g", "h"}; 9 | 10 | boolean canGenerateFor(ProgrammingLanguage language); 11 | 12 | String generate(Challenge challenge); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/user/SignInController.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.user; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.servlet.ModelAndView; 6 | 7 | @Controller 8 | public class SignInController { 9 | 10 | @RequestMapping("/signin") 11 | public ModelAndView loginPage() { 12 | return new ModelAndView("signin"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/emails/forgotMyPasswordEmail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.user; 2 | 3 | import com.expercise.domain.user.User; 4 | import com.expercise.repository.BaseRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface UserRepository extends BaseRepository { 10 | 11 | User findByEmail(String email); 12 | 13 | @Query("select u.id from User u") 14 | List findAllIds(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/user/RememberMeTokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.user; 2 | 3 | import com.expercise.domain.user.RememberMeToken; 4 | import com.expercise.repository.BaseRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | 7 | public interface RememberMeTokenRepository extends BaseRepository { 8 | 9 | RememberMeToken findBySeries(String series); 10 | 11 | @Modifying 12 | void deleteByEmail(String email); 13 | 14 | } -------------------------------------------------------------------------------- /.elasticbeanstalk/config.yml: -------------------------------------------------------------------------------- 1 | deploy: 2 | artifact: target/elasticbeanstalk-artifact.zip 3 | global: 4 | application_name: coding-expercise 5 | branch: null 6 | default_ec2_keyname: coding-expercise 7 | default_platform: Java 8 8 | default_region: us-east-1 9 | instance_profile: null 10 | platform_name: null 11 | platform_version: null 12 | profile: null 13 | repository: null 14 | sc: null 15 | workspace_type: Application 16 | branch-defaults: 17 | master: 18 | environment: null 19 | group_suffix: null -------------------------------------------------------------------------------- /src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | # Spring Boot 2 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect 3 | spring.jpa.hibernate.ddl-auto=validate 4 | spring.jpa.generate-ddl=false 5 | spring.datasource.url=jdbc:postgresql://localhost:5432/codingexpercise 6 | spring.datasource.driverClassName=org.postgresql.Driver 7 | spring.datasource.initialize=false 8 | spring.datasource.username=root 9 | spring.datasource.password=123qwe 10 | 11 | liquibase.enabled=true 12 | liquibase.contexts=dev 13 | 14 | # Coding Expercise 15 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/PasswordEncoder.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.security.authentication.encoding.ShaPasswordEncoder; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | public class PasswordEncoder { 9 | 10 | @Autowired 11 | private ShaPasswordEncoder shaPasswordEncoder; 12 | 13 | public String encode(String password) { 14 | return shaPasswordEncoder.encodePassword(password, null); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/interpreter/InterpreterException.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | public class InterpreterException extends Exception { 4 | 5 | private static final long serialVersionUID = -9010793998200028098L; 6 | 7 | private final InterpreterResult interpreterResult; 8 | 9 | public InterpreterException(InterpreterResult interpreterResult) { 10 | this.interpreterResult = interpreterResult; 11 | } 12 | 13 | public InterpreterResult getInterpreterResult() { 14 | return interpreterResult; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/resources/public/style/addUpdateChallenge.less: -------------------------------------------------------------------------------- 1 | #testCasesTable > tbody tr, #testCasesTable > tbody tr:hover { 2 | cursor: pointer; 3 | } 4 | 5 | #testCasesTable > tbody tr:hover { 6 | background-color: #eee; 7 | } 8 | 9 | #testCasesTable > tbody > tr > td { 10 | vertical-align: middle; 11 | } 12 | 13 | .removeInput, #addNewInput, .removeTestCase, #addNewTestCase { 14 | cursor: pointer; 15 | } 16 | 17 | #testCasesTable > tbody > tr > td > input { 18 | margin-bottom: 5px; 19 | } 20 | 21 | #testCasesTable > tbody > tr > td > a.btn { 22 | margin-bottom: 5px; 23 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/user/TokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.user; 2 | 3 | import com.expercise.domain.token.Token; 4 | import com.expercise.domain.token.TokenType; 5 | import com.expercise.domain.user.User; 6 | import com.expercise.repository.BaseRepository; 7 | import org.springframework.data.jpa.repository.Modifying; 8 | 9 | public interface TokenRepository extends BaseRepository { 10 | 11 | Token findByTokenAndTokenType(String token, TokenType tokenType); 12 | 13 | @Modifying 14 | void deleteByUser(User user); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/domain/user/UserTest.java: -------------------------------------------------------------------------------- 1 | package com.expercise.domain.user; 2 | 3 | import com.expercise.testutils.builder.UserBuilder; 4 | import org.junit.Test; 5 | 6 | import static org.hamcrest.Matchers.equalTo; 7 | import static org.junit.Assert.assertThat; 8 | 9 | public class UserTest { 10 | 11 | @Test 12 | public void shouldReturnBookmarkableUrlByIdAndFullName() { 13 | User user = new UserBuilder().id(1989L).firstName("Ufuk").lastName("Uzun").build(); 14 | 15 | assertThat(user.getBookmarkableUrl(), equalTo("/user/1989/ufuk-uzun")); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/email/TemplateEngineWrapper.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.email; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import org.thymeleaf.TemplateEngine; 6 | import org.thymeleaf.context.Context; 7 | 8 | @Service 9 | public class TemplateEngineWrapper { 10 | 11 | @Autowired 12 | private TemplateEngine templateEngine; 13 | 14 | public String process(String templateName, Context context) { 15 | return templateEngine.process(templateName, context); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/Clock.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils; 2 | 3 | import java.util.Calendar; 4 | import java.util.Date; 5 | 6 | public final class Clock { 7 | 8 | private static Date frozenTime; 9 | 10 | private Clock() { 11 | } 12 | 13 | public static void freeze(Date frozenTime) { 14 | Clock.frozenTime = frozenTime; 15 | } 16 | 17 | public static void unfreeze() { 18 | frozenTime = null; 19 | } 20 | 21 | public static Date getTime() { 22 | return frozenTime != null ? frozenTime : Calendar.getInstance().getTime(); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/main/resources/public/js/profile.js: -------------------------------------------------------------------------------- 1 | expercise.Profile = { 2 | 3 | bindEvents: function () { 4 | $('#avatarsCollapse a').click(this.selectAvatar); 5 | 6 | $('#connectTwitterAccount').click(function (e) { 7 | e.preventDefault(); 8 | 9 | $(e.target).parents('form').submit(); 10 | }); 11 | }, 12 | 13 | selectAvatar: function (event) { 14 | var avatarType = $(event.target).closest('a').data('avatar-type'); 15 | var url = expercise.utils.urlFor("user/selectAvatar/" + avatarType); 16 | expercise.utils.go(url); 17 | } 18 | 19 | }; -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/validation/PasswordMatch.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.validation; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.*; 6 | 7 | @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Constraint(validatedBy = PasswordMatchValidator.class) 10 | @Documented 11 | public @interface PasswordMatch { 12 | 13 | String message() default "{fieldMatch.error}"; 14 | 15 | Class>[] groups() default {}; 16 | 17 | Class extends Payload>[] payload() default {}; 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/interpreter/InterpretRequest.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | public class InterpretRequest { 4 | 5 | private final String sourceCode; 6 | private final String programmingLanguage; 7 | 8 | public InterpretRequest(String sourceCode, String programmingLanguage) { 9 | this.sourceCode = sourceCode; 10 | this.programmingLanguage = programmingLanguage; 11 | } 12 | 13 | public String getSourceCode() { 14 | return sourceCode; 15 | } 16 | 17 | public String getProgrammingLanguage() { 18 | return programmingLanguage; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/Application.java: -------------------------------------------------------------------------------- 1 | package com.expercise; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 6 | import org.springframework.context.annotation.PropertySource; 7 | 8 | @SpringBootApplication 9 | @EnableAspectJAutoProxy 10 | @PropertySource(value = "build.properties", ignoreResourceNotFound = true) 11 | public class Application { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(Application.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/caching/CachingSubject.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.caching; 2 | 3 | import com.expercise.service.challenge.SolutionCountService; 4 | import com.expercise.service.quote.QuoteService; 5 | 6 | public enum CachingSubject { 7 | 8 | SolutionCount(SolutionCountService.class), 9 | Quote(QuoteService.class); 10 | 11 | private Class extends Caching> cachingClass; 12 | 13 | CachingSubject(Class extends Caching> cachingClass) { 14 | this.cachingClass = cachingClass; 15 | } 16 | 17 | public Class extends Caching> getCachingClass() { 18 | return cachingClass; 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/challenge/model/ChallengeResetModel.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.challenge.model; 2 | 3 | public class ChallengeResetModel { 4 | 5 | private Long challengeId; 6 | 7 | private String language; 8 | 9 | public Long getChallengeId() { 10 | return challengeId; 11 | } 12 | 13 | public void setChallengeId(Long challengeId) { 14 | this.challengeId = challengeId; 15 | } 16 | 17 | public String getLanguage() { 18 | return language; 19 | } 20 | 21 | public void setLanguage(String language) { 22 | this.language = language; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/interpreter/InterpreterClient.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.client.RestTemplate; 6 | 7 | @Component 8 | public class InterpreterClient { 9 | 10 | @Value("${coding-expercise.interpreter.api.url}") 11 | private String interpreterApiUrl; 12 | 13 | public InterpretResponse interpret(InterpretRequest interpretRequest) { 14 | return new RestTemplate().postForEntity(interpreterApiUrl + "/eval", interpretRequest, InterpretResponse.class).getBody(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /init-dev-environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # STOP CONTAINERS 4 | 5 | echo "PostgreSQL container is being stopped..." 6 | docker rm -f codingexpercise-postgres || true 7 | 8 | echo "Redis container is being stopped..." 9 | docker rm -f codingexpercise-redis || true 10 | 11 | # START CONTAINERS 12 | 13 | echo "PostgreSQL container is being started..." 14 | docker run --name codingexpercise-postgres -d -p 5432:5432 -e POSTGRES_PASSWORD=123qwe -e POSTGRES_USER=root -e POSTGRES_DB=codingexpercise postgres 15 | 16 | echo "Redis container is being started..." 17 | docker run --name codingexpercise-redis -d -p 6379:6379 redis 18 | 19 | echo "All containers have been started successfully." -------------------------------------------------------------------------------- /src/test/groovy/com/expercise/utils/NumberUtilsSpec.groovy: -------------------------------------------------------------------------------- 1 | package com.expercise.utils 2 | 3 | import spock.lang.Specification 4 | import spock.lang.Unroll 5 | 6 | class NumberUtilsSpec extends Specification { 7 | 8 | @Unroll 9 | def "should calculate percentage as #percentage when partial is #partial and total is #total"(int partial, int total, int percentage) { 10 | expect: 11 | NumberUtils.toPercentage(partial, total) == percentage 12 | 13 | where: 14 | partial | total | percentage 15 | 1 | 2 | 50 16 | 49 | 100 | 49 17 | 3 | 4 | 75 18 | 11 | 12 | 92 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/user/CurrentUserHolder.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.user; 2 | 3 | import com.expercise.domain.user.User; 4 | import org.springframework.context.annotation.Scope; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | @Scope("request") 9 | public class CurrentUserHolder { 10 | 11 | private User currentUser; 12 | 13 | public boolean hasNotCurrentUser() { 14 | return currentUser == null; 15 | } 16 | 17 | public User getCurrentUser() { 18 | return currentUser; 19 | } 20 | 21 | public void setCurrentUser(User currentUser) { 22 | this.currentUser = currentUser; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/validation/ValidationUtils.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.validation; 2 | 3 | import org.springframework.context.support.DefaultMessageSourceResolvable; 4 | import org.springframework.validation.BindingResult; 5 | 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | public class ValidationUtils { 10 | 11 | private ValidationUtils() { 12 | } 13 | 14 | public static List extractAllErrorCodes(BindingResult bindingResult) { 15 | return bindingResult.getAllErrors().stream() 16 | .map(DefaultMessageSourceResolvable::getCode) 17 | .collect(Collectors.toList()); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/db/changelog/changelog-master.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/configuration/ResourceBundleMessageSources.java: -------------------------------------------------------------------------------- 1 | package com.expercise.configuration; 2 | 3 | import org.springframework.context.i18n.LocaleContextHolder; 4 | import org.springframework.context.support.ResourceBundleMessageSource; 5 | 6 | import java.util.ResourceBundle; 7 | 8 | public class ResourceBundleMessageSources extends ResourceBundleMessageSource { 9 | 10 | public ResourceBundle getApplicationMessages() { 11 | return getResourceBundle("messages", LocaleContextHolder.getLocale()); 12 | } 13 | 14 | public ResourceBundle getEmailMessages() { 15 | return getResourceBundle("messagesForEmails", LocaleContextHolder.getLocale()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/user/model/PasswordResetModel.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.user.model; 2 | 3 | import javax.validation.Valid; 4 | 5 | public class PasswordResetModel { 6 | 7 | @Valid 8 | private PasswordModel passwordModel; 9 | 10 | private String token; 11 | 12 | public PasswordModel getPasswordModel() { 13 | return passwordModel; 14 | } 15 | 16 | public void setPasswordModel(PasswordModel passwordModel) { 17 | this.passwordModel = passwordModel; 18 | } 19 | 20 | public String getToken() { 21 | return token; 22 | } 23 | 24 | public void setToken(String token) { 25 | this.token = token; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/collection/RandomElement.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.collection; 2 | 3 | import org.apache.commons.lang3.RandomUtils; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.Collection; 8 | import java.util.List; 9 | 10 | public final class RandomElement { 11 | 12 | private RandomElement() { 13 | } 14 | 15 | public static9 | 10 | 11 | 12 | 13 | T from(Collection collection) { 16 | List list = new ArrayList<>(collection); 17 | return list.isEmpty() ? null : list.get(RandomUtils.nextInt(0, list.size())); 18 | } 19 | 20 | public static T from(T[] array) { 21 | return from(Arrays.asList(array)); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/testutils/builder/BasePrioritizedEntityBuilder.java: -------------------------------------------------------------------------------- 1 | package com.expercise.testutils.builder; 2 | 3 | import com.expercise.domain.PrioritizedEntity; 4 | 5 | public abstract class BasePrioritizedEntityBuilder extends BaseEntityBuilder { 6 | 7 | private int priority; 8 | 9 | protected abstract T getInstance(); 10 | 11 | @Override 12 | protected T doBuild() { 13 | T entity = getInstance(); 14 | entity.setPriority(priority); 15 | return entity; 16 | } 17 | 18 | public B priority(int priority) { 19 | this.priority = priority; 20 | return (B) this; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/challenge/action/PreEvaluationExecutor.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.challenge.action; 2 | 3 | import com.expercise.service.challenge.model.ChallengeEvaluationContext; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | @Service 11 | public class PreEvaluationExecutor { 12 | 13 | @Autowired(required = false) 14 | private List preEvaluationActions = new ArrayList<>(); 15 | 16 | public void execute(ChallengeEvaluationContext context) { 17 | preEvaluationActions.forEach(a -> a.execute(context)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/public/img/flags/tr.svg: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/testutils/FileTestUtils.java: -------------------------------------------------------------------------------- 1 | package com.expercise.testutils; 2 | 3 | import com.expercise.exception.ExperciseGenericException; 4 | import org.apache.commons.io.IOUtils; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | public final class FileTestUtils { 10 | 11 | private FileTestUtils() { 12 | } 13 | 14 | public static String getFileContentFrom(String file) { 15 | InputStream inputStream = FileTestUtils.class.getResourceAsStream(file); 16 | try { 17 | return IOUtils.toString(inputStream); 18 | } catch (IOException e) { 19 | throw new ExperciseGenericException("File couldn't be read: " + file, e); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/groovy/com/expercise/controller/RedirectUtilsSpec.groovy: -------------------------------------------------------------------------------- 1 | package com.expercise.controller 2 | 3 | import spock.lang.Specification 4 | import spock.lang.Unroll 5 | 6 | class RedirectUtilsSpec extends Specification { 7 | 8 | @Unroll 9 | def "should redirect #path to #redirectedPath"() { 10 | expect: 11 | RedirectUtils.redirectTo(path).getViewName() == redirectedPath 12 | 13 | where: 14 | path | redirectedPath 15 | "/" | "redirect:/" 16 | "/signin" | "redirect:/signin" 17 | "/signin?newmember" | "redirect:/signin?newmember" 18 | "/404" | "redirect:/404" 19 | "/403" | "redirect:/403" 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/challenge/management/TagsManagementController.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.challenge.management; 2 | 3 | import com.expercise.controller.BaseManagementController; 4 | import com.expercise.service.challenge.TagIndexService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | 9 | @Controller 10 | public class TagsManagementController extends BaseManagementController { 11 | 12 | @Autowired 13 | private TagIndexService tagIndexService; 14 | 15 | @GetMapping("/tags/re-index") 16 | public void listChallengesForAdmin() { 17 | tagIndexService.indexTags(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/public/js/home.js: -------------------------------------------------------------------------------- 1 | expercise.Home = { 2 | 3 | constructor: function () { 4 | this.showAssistant(); 5 | }, 6 | 7 | showAssistant: function () { 8 | expercise.assistant.speak( 9 | { 10 | title: expercise.utils.i18n('assistant.home.welcome.title'), 11 | message: expercise.utils.i18n('assistant.home.welcome.content', [expercise.utils.urlFor('start-coding')]), 12 | buttonText: expercise.utils.i18n('assistant.home.welcome.button'), 13 | onButtonClick: function () { 14 | expercise.utils.go(expercise.utils.urlFor('start-coding')); 15 | } 16 | } 17 | ); 18 | expercise.assistant.hide(15); 19 | } 20 | 21 | }; -------------------------------------------------------------------------------- /src/main/resources/public/js/header.js: -------------------------------------------------------------------------------- 1 | expercise.Header = { 2 | 3 | $header: $('#header'), 4 | 5 | bindEvents: function () { 6 | this.menuToggles(); 7 | }, 8 | 9 | menuToggles: function () { 10 | if (expercise.utils.isMobileClient()) { 11 | return; 12 | } 13 | 14 | $('#userMenuDropdown').mouseenter(function () { 15 | if ($('#userMenuDropdownContainer').hasClass('open') == false) { 16 | $(this).dropdown('toggle'); 17 | } 18 | }); 19 | 20 | $('#lingoMenuDropdown').mouseenter(function () { 21 | if ($('#lingoMenuDropdownContainer').hasClass('open') == false) { 22 | $(this).dropdown('toggle'); 23 | } 24 | }); 25 | } 26 | 27 | }; -------------------------------------------------------------------------------- /src/main/java/com/expercise/enums/ProgrammingLanguage.java: -------------------------------------------------------------------------------- 1 | package com.expercise.enums; 2 | 3 | import java.util.Arrays; 4 | import java.util.Optional; 5 | 6 | public enum ProgrammingLanguage { 7 | 8 | JavaScript("js"), 9 | Python2("py2"), 10 | Python3("py3"), 11 | Java("java"); 12 | 13 | private String shortName; 14 | 15 | ProgrammingLanguage(String shortName) { 16 | this.shortName = shortName; 17 | } 18 | 19 | public static Optional getLanguage(String shortName) { 20 | return Arrays.asList(values()).stream() 21 | .filter(p -> p.getShortName().equals(shortName)) 22 | .findFirst(); 23 | } 24 | 25 | public String getShortName() { 26 | return shortName; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/interpreter/InterpretResponse.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | public class InterpretResponse { 4 | 5 | private String stdOut; 6 | private String stdErr; 7 | 8 | public String getStdOut() { 9 | return stdOut; 10 | } 11 | 12 | public void setStdOut(String stdOut) { 13 | this.stdOut = stdOut; 14 | } 15 | 16 | public String getStdErr() { 17 | return stdErr; 18 | } 19 | 20 | public void setStdErr(String stdErr) { 21 | this.stdErr = stdErr; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "InterpretResponse{" + 27 | "stdOut='" + stdOut + '\'' + 28 | ", stdErr='" + stdErr + '\'' + 29 | '}'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller; 2 | 3 | import com.expercise.service.quote.QuoteService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.servlet.ModelAndView; 8 | 9 | @Controller 10 | @RequestMapping("/") 11 | public class HomeController { 12 | 13 | @Autowired 14 | private QuoteService quoteService; 15 | 16 | @RequestMapping 17 | public ModelAndView homePage() { 18 | ModelAndView modelAndView = new ModelAndView("index"); 19 | modelAndView.addObject("quote", quoteService.randomQuote()); 20 | return modelAndView; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/notification/SlackMessage.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.notification; 2 | 3 | public class SlackMessage { 4 | 5 | private String channel; 6 | 7 | private String text; 8 | 9 | public String getChannel() { 10 | return channel; 11 | } 12 | 13 | public void setChannel(String channel) { 14 | this.channel = channel; 15 | } 16 | 17 | public String getText() { 18 | return text; 19 | } 20 | 21 | public void setText(String text) { 22 | this.text = text; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "SlackMessage{" + 28 | "channel='" + channel + '\'' + 29 | ", text='" + text + '\'' + 30 | '}'; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/validation/UniqueEmail.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.validation; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.Target; 7 | 8 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 9 | import static java.lang.annotation.ElementType.FIELD; 10 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 11 | 12 | @Target({FIELD, ANNOTATION_TYPE}) 13 | @Retention(RUNTIME) 14 | @Constraint(validatedBy = EmailUniquenessValidator.class) 15 | public @interface UniqueEmail { 16 | 17 | String message() default "{UniqueEmail.message}"; 18 | 19 | Class>[] groups() default {}; 20 | 21 | Class extends Payload>[] payload() default {}; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/public/js/expercise.js: -------------------------------------------------------------------------------- 1 | expercise = { 2 | 3 | assistant: new Assistant(), 4 | 5 | constructor: function () { 6 | this.assistant.init({ 7 | image: expercise.utils.urlFor('img/assistant-robot.svg'), 8 | width: '100px', 9 | height: '166px' 10 | }); 11 | }, 12 | 13 | bindEvents: function () { 14 | this.configureTooltips(); 15 | }, 16 | 17 | configureTooltips: function () { 18 | var $tooltips = $('[data-toggle="tooltip"]'); 19 | $tooltips.tooltip(); 20 | 21 | var $showOnLoadTooltips = $tooltips.filter('.showOnLoad'); 22 | $showOnLoadTooltips.tooltip('show'); 23 | setTimeout(function () { 24 | $showOnLoadTooltips.tooltip('hide'); 25 | }, 2000); 26 | } 27 | 28 | }; -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/user/model/PasswordModel.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.user.model; 2 | 3 | import com.expercise.utils.validation.PasswordMatch; 4 | 5 | import javax.validation.constraints.Size; 6 | 7 | @PasswordMatch 8 | public class PasswordModel { 9 | 10 | @Size(min = 6, max = 16) 11 | private String password; 12 | 13 | private String passwordRetype; 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | 23 | public String getPasswordRetype() { 24 | return passwordRetype; 25 | } 26 | 27 | public void setPasswordRetype(String passwordRetype) { 28 | this.passwordRetype = passwordRetype; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/UrlUtils.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils; 2 | 3 | import java.text.Normalizer; 4 | import java.util.Locale; 5 | import java.util.regex.Pattern; 6 | 7 | public final class UrlUtils { 8 | 9 | private UrlUtils() { 10 | } 11 | 12 | public static String makeBookmarkable(String text) { 13 | return Pattern.compile("\\p{InCombiningDiacriticalMarks}+") 14 | .matcher(Normalizer.normalize(text.replaceAll("[ı]", "i"), Normalizer.Form.NFD)) 15 | .replaceAll("") 16 | .toLowerCase(Locale.ENGLISH) 17 | .replaceAll("\\s+", " ") 18 | .trim() 19 | .replaceAll(" ", "-") 20 | .replaceAll("[^a-z0-9\\-]*", "") 21 | .replaceAll("(\\-)+", "-"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | # Spring Boot 2 | spring.profiles.active=prod 3 | 4 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect 5 | spring.jpa.hibernate.ddl-auto=validate 6 | spring.jpa.generate-ddl=false 7 | spring.datasource.url=${SPRING_DATASOURCE_URL} 8 | spring.datasource.driverClassName=org.postgresql.Driver 9 | spring.datasource.initialize=false 10 | spring.datasource.username=${SPRING_DATASOURCE_USERNAME} 11 | spring.datasource.password=${SPRING_DATASOURCE_PASSWORD} 12 | 13 | spring.thymeleaf.cache=true 14 | 15 | liquibase.enabled=true 16 | liquibase.contexts=prod 17 | 18 | # Coding Expercise 19 | coding-expercise.root-url=https://coding.expercise.com 20 | coding-expercise.interpreter.api.url=${INTERPRETER_API_URL} 21 | 22 | coding-expercise.challenge-approval-strategy=admin 23 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/enums/SocialSignInProvider.java: -------------------------------------------------------------------------------- 1 | package com.expercise.enums; 2 | 3 | import java.util.Optional; 4 | import java.util.stream.Stream; 5 | 6 | public enum SocialSignInProvider { 7 | 8 | Twitter("twitter"), 9 | Facebook("facebook"), 10 | LinkedIn("linkedin"), 11 | GitHub("github"), 12 | Google("google"); 13 | 14 | private final String providerId; 15 | 16 | SocialSignInProvider(String providerId) { 17 | this.providerId = providerId; 18 | } 19 | 20 | public static Optional getForProviderId(String providerId) { 21 | return Stream.of(values()) 22 | .filter(it -> it.providerId.equals(providerId)) 23 | .findFirst(); 24 | } 25 | 26 | public String getProviderId() { 27 | return providerId; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/challenge/action/PostEvaluationAction.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.challenge.action; 2 | 3 | import com.expercise.service.challenge.model.ChallengeEvaluationContext; 4 | import com.expercise.service.util.Prioritized; 5 | 6 | public interface PostEvaluationAction extends Prioritized { 7 | 8 | boolean canExecute(ChallengeEvaluationContext context); 9 | 10 | void execute(ChallengeEvaluationContext context); 11 | 12 | enum PostEvaluationActionOrder { 13 | 14 | INTERPRETATION_FAILURE_CHECK_FOR_TEST_CASES, 15 | SAVE_USER_TEST_CASE_STATE, 16 | CREATE_SOLUTION_RESPONSE, 17 | CREATE_KATA_SOLUTION_RESPONSE, 18 | GIVE_SUCCESS_POINT, 19 | SAVE_USER_SOLUTION, 20 | PREPARE_CHALLENGE_USER_SOLUTIONS, 21 | NOTIFY_CHALLENGE_COMPLETED 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/user/SocialUserDetailsProvider.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.user; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 5 | import org.springframework.social.security.SocialUserDetailsService; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class SocialUserDetailsProvider implements SocialUserDetailsService { 10 | 11 | @Autowired 12 | private UserDetailsProvider userDetailsProvider; 13 | 14 | @Override 15 | public org.springframework.social.security.SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException { 16 | return (org.springframework.social.security.SocialUserDetails) userDetailsProvider.loadUserByUserId(userId); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/utils/BrowserCacheableContent.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.utils; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | public abstract class BrowserCacheableContent { 9 | 10 | public abstract String generateContent(); 11 | 12 | public String getContent(HttpServletRequest request, HttpServletResponse response) { 13 | long ifModifiedSince = request.getDateHeader("If-Modified-Since"); 14 | 15 | if (ifModifiedSince > -1) { 16 | response.setStatus(HttpStatus.NOT_MODIFIED.value()); 17 | return ""; 18 | } 19 | 20 | response.addDateHeader("Last-Modified", System.currentTimeMillis()); 21 | 22 | return generateContent(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/domain/PrioritizedEntity.java: -------------------------------------------------------------------------------- 1 | package com.expercise.domain; 2 | 3 | import com.expercise.service.util.Prioritized; 4 | 5 | import javax.persistence.MappedSuperclass; 6 | import java.util.List; 7 | 8 | @MappedSuperclass 9 | public abstract class PrioritizedEntity extends BaseEntity implements Prioritized { 10 | 11 | private int priority; 12 | 13 | public static void prioritize(List prioritizedEntityList) { 14 | int priority = 1; 15 | for (T each : prioritizedEntityList) { 16 | each.setPriority(priority); 17 | priority++; 18 | } 19 | } 20 | 21 | @Override 22 | public int getPriority() { 23 | return priority; 24 | } 25 | 26 | public void setPriority(int priority) { 27 | this.priority = priority; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/challenge/UserPointRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.challenge; 2 | 3 | import com.expercise.domain.challenge.Challenge; 4 | import com.expercise.domain.challenge.UserPoint; 5 | import com.expercise.domain.user.User; 6 | import com.expercise.enums.ProgrammingLanguage; 7 | import com.expercise.repository.BaseRepository; 8 | import org.springframework.data.jpa.repository.Query; 9 | 10 | public interface UserPointRepository extends BaseRepository { 11 | 12 | UserPoint findByChallengeAndUser(Challenge challenge, User user); 13 | 14 | Long countByChallengeAndUserAndProgrammingLanguage(Challenge challenge, User user, ProgrammingLanguage programmingLanguage); 15 | 16 | @Query("select sum(up.pointAmount) from UserPoint up where up.user.id = ?1") 17 | Long getTotalPointsOf(Long userId); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/utils/validation/EmailUniquenessValidator.java: -------------------------------------------------------------------------------- 1 | package com.expercise.utils.validation; 2 | 3 | import com.expercise.service.user.UserService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.validation.ConstraintValidator; 8 | import javax.validation.ConstraintValidatorContext; 9 | 10 | @Component 11 | public class EmailUniquenessValidator implements ConstraintValidator { 12 | 13 | @Autowired 14 | private UserService userService; 15 | 16 | @Override 17 | public void initialize(UniqueEmail constraintAnnotation) { 18 | } 19 | 20 | @Override 21 | public boolean isValid(String value, ConstraintValidatorContext context) { 22 | return userService.emailNotRegisteredYet(value); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/service/challenge/model/LeaderBoardModel.java: -------------------------------------------------------------------------------- 1 | package com.expercise.service.challenge.model; 2 | 3 | import com.expercise.domain.user.User; 4 | 5 | import java.io.Serializable; 6 | 7 | public class LeaderBoardModel implements Serializable { 8 | 9 | private User user; 10 | 11 | private Integer point; 12 | 13 | public LeaderBoardModel() { 14 | } 15 | 16 | public LeaderBoardModel(User user, Integer point) { 17 | this.user = user; 18 | this.point = point; 19 | } 20 | 21 | public User getUser() { 22 | return user; 23 | } 24 | 25 | public void setUser(User user) { 26 | this.user = user; 27 | } 28 | 29 | public Integer getPoint() { 30 | return point; 31 | } 32 | 33 | public void setPoint(Integer point) { 34 | this.point = point; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/challenge/SolutionRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.challenge; 2 | 3 | import com.expercise.domain.challenge.Challenge; 4 | import com.expercise.domain.challenge.Solution; 5 | import com.expercise.domain.user.User; 6 | import com.expercise.enums.ProgrammingLanguage; 7 | import com.expercise.repository.BaseRepository; 8 | 9 | import java.util.List; 10 | 11 | public interface SolutionRepository extends BaseRepository { 12 | 13 | Solution findByChallengeAndUserAndProgrammingLanguage(Challenge challenge, User user, ProgrammingLanguage programmingLanguage); 14 | 15 | List findByChallengeApprovedIsTrueAndUser(User user); 16 | 17 | List findByChallengeAndUser(Challenge challenge, User user); 18 | 19 | Long countByChallenge(Challenge challenge); 20 | 21 | Long countByUser(User user); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/expercise/interpreter/InterpreterTest.java: -------------------------------------------------------------------------------- 1 | package com.expercise.interpreter; 2 | 3 | import com.expercise.service.challenge.model.ChallengeEvaluationContext; 4 | import org.junit.Test; 5 | 6 | import static org.hamcrest.Matchers.equalTo; 7 | import static org.junit.Assert.assertFalse; 8 | import static org.junit.Assert.assertThat; 9 | 10 | public class InterpreterTest { 11 | 12 | @Test 13 | public void shouldLimitInterpretationTime() { 14 | InfiniteLoopTestInterpreter interpreter = new InfiniteLoopTestInterpreter(); 15 | 16 | ChallengeEvaluationContext context = new ChallengeEvaluationContext(); 17 | 18 | interpreter.interpret(context); 19 | 20 | assertFalse(context.getInterpreterResult().isSuccess()); 21 | assertThat(context.getInterpreterResult().getFailureType(), equalTo(InterpreterFailureType.NO_RESULT)); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/main/resources/public/img/ATTRIBUTION.md: -------------------------------------------------------------------------------- 1 | Attribution 2 | =========== 3 | 4 | The original version of Avatars (sprites/avatars-sprite.svg) designed by Freepik.com and named as [Animal avatars collection](http://www.freepik.com/free-vector/animal-avatars-collection_766290.htm). 5 | 6 | The original version of background/green-landscape.svg designed by Freepik.com and named as [Urban landscape with a big wheel](http://www.freepik.com/free-vector/urban-landscape-with-a-big-wheel_766759.htm). 7 | 8 | The original version of background/programming-on-the-cloud.svg designed by Freepik.com and named as [Businessman using a tablet](http://www.freepik.com/free-vector/businessman-using-a-tablet_767018.htm). 9 | 10 | The original version of Assistant Robot (assistant-robot.svg) designed by Freepik.com and named as [Retro robots vector elements](http://www.freepik.com/free-vector/retro-robots-vector-elements_721189.htm). -------------------------------------------------------------------------------- /src/main/resources/public/js/bootstrapper.js: -------------------------------------------------------------------------------- 1 | var coreModules = [ 2 | expercise, 3 | expercise.utils, 4 | expercise.Header, 5 | expercise.Locale 6 | ]; 7 | 8 | $(function () { 9 | initCoreModules(); 10 | initPageSpecificModules(); 11 | }); 12 | 13 | function initCoreModules() { 14 | coreModules.forEach(function (eachModule) { 15 | initModule(eachModule); 16 | }); 17 | } 18 | 19 | function initPageSpecificModules() { 20 | var $moduleNamesHolder = $('#javaScriptModules'); 21 | if ($moduleNamesHolder.length) { 22 | var pageSpecificModules = $moduleNamesHolder.val().split(" "); 23 | pageSpecificModules.forEach(function (eachModule) { 24 | initModule(expercise[eachModule]); 25 | }); 26 | } 27 | } 28 | 29 | function initModule(module) { 30 | module.constructor && module.constructor(); 31 | module.bindEvents && module.bindEvents(); 32 | } -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/challenge/model/TagModel.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.challenge.model; 2 | 3 | public class TagModel { 4 | 5 | private String name; 6 | 7 | private int count; 8 | 9 | private int rank = 1; 10 | 11 | public TagModel() { 12 | } 13 | 14 | public TagModel(String name, int count) { 15 | this.name = name; 16 | this.count = count; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | 27 | public int getCount() { 28 | return count; 29 | } 30 | 31 | public void setCount(int count) { 32 | this.count = count; 33 | } 34 | 35 | public int getRank() { 36 | return rank; 37 | } 38 | 39 | public void setRank(int rank) { 40 | this.rank = rank; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/resources/public/style/show-hint.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-hints { 2 | position: absolute; 3 | z-index: 10; 4 | overflow: hidden; 5 | list-style: none; 6 | 7 | margin: 0; 8 | padding: 2px; 9 | 10 | -webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); 11 | -moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); 12 | box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); 13 | border-radius: 3px; 14 | border: 1px solid silver; 15 | 16 | background: white; 17 | font-size: 90%; 18 | font-family: monospace; 19 | 20 | max-height: 20em; 21 | overflow-y: auto; 22 | } 23 | 24 | .CodeMirror-hint { 25 | margin: 0; 26 | padding: 0 4px; 27 | border-radius: 2px; 28 | max-width: 19em; 29 | overflow: hidden; 30 | white-space: pre; 31 | color: black; 32 | cursor: pointer; 33 | } 34 | 35 | li.CodeMirror-hint-active { 36 | background: #08f; 37 | color: white; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/controller/user/management/UserListingController.java: -------------------------------------------------------------------------------- 1 | package com.expercise.controller.user.management; 2 | 3 | import com.expercise.controller.BaseManagementController; 4 | import com.expercise.service.user.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.servlet.ModelAndView; 9 | 10 | @Controller 11 | public class UserListingController extends BaseManagementController { 12 | 13 | @Autowired 14 | private UserService userService; 15 | 16 | @RequestMapping("/users") 17 | public ModelAndView listUsersForAdmin() { 18 | ModelAndView modelAndView = new ModelAndView("user/userList"); 19 | modelAndView.addObject("users", userService.findAll()); 20 | return modelAndView; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/expercise/repository/challenge/ChallengeRepository.java: -------------------------------------------------------------------------------- 1 | package com.expercise.repository.challenge; 2 | 3 | import com.expercise.domain.challenge.Challenge; 4 | import com.expercise.domain.user.User; 5 | import com.expercise.repository.BaseRepository; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.Query; 8 | 9 | import java.util.List; 10 | 11 | public interface ChallengeRepository extends BaseRepository { 12 | 13 | List findByApprovedIsTrue(); 14 | 15 | List findByUserOrderByCreateDateDesc(User user); 16 | 17 | List findAllByOrderByCreateDateDesc(); 18 | 19 | List findByApprovedIsTrueAndUser(User user); 20 | 21 | @Query("select c.id, c.tags from Challenge c where c.approved = true order by c.createDate desc") 22 | List