wyf 5 rokov pred
rodič
commit
b30715cfb7
65 zmenil súbory, kde vykonal 1237 pridanie a 223 odobranie
  1. 19 0
      mooctest-site-server/pom.xml
  2. 3 1
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/acyncTask/OnlineJudgeAndCulScoreCallBack.java
  3. 117 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/aspect/LogAspect.java
  4. 3 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/constant/CaseBlockConstants.java
  5. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/constant/DevLanguageConstants.java
  6. 13 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/event/EventsListener.java
  7. 21 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/event/QuitCompetitionEvent.java
  8. 7 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/configure/OSSConfiguration.java
  9. 9 9
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/configure/RedisSessionConfiguration.java
  10. 1 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/configure/ShiroConfiguration.java
  11. 18 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/AddOns2QualificationDao.java
  12. 19 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/AnswerAnnexDao.java
  13. 1 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/QualificationDao.java
  14. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/UploadRecordDao.java
  15. 1 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/data/UploadRecordDTO.java
  16. 1 1
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/data/config/OSSClientConfig.java
  17. 32 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/data/config/STSConfig.java
  18. 36 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/AnswerAnnex.java
  19. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/Competition.java
  20. 3 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/UploadRecord.java
  21. 14 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/AnswerAnnexService.java
  22. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/CaseService.java
  23. 11 1
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/CompetitionService.java
  24. 3 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/GeneralCalculateScoreService.java
  25. 5 4
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/common/impl/ZipServiceImpl.java
  26. 54 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/AnswerAnnexServiceImpl.java
  27. 10 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/CaseServiceImpl.java
  28. 163 35
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/CompetitionServiceImpl.java
  29. 6 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/GeneralCalculateScoreServiceImpl.java
  30. 22 4
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/SubmitRecordServiceImpl.java
  31. 10 7
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/updownload/impl/DownloadServiceImpl.java
  32. 71 12
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/CompetitionController.java
  33. 20 6
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/ExamController.java
  34. 14 2
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/ScoreController.java
  35. 35 7
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/TestController.java
  36. 3 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/CaseExtendsVO.java
  37. 1 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/CompetitionVO.java
  38. 19 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/CrowdScoreResponse.java
  39. 17 3
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/EclipseCaseVO.java
  40. 0 12
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/GroupVO.java
  41. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/KibugPluginCaseVO.java
  42. 22 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/OSSClientConfigVO.java
  43. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/PluginCaseVO.java
  44. 3 2
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/CalculateSocreLogic.java
  45. 9 2
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/CompetitionLogic.java
  46. 3 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/ExamLogic.java
  47. 6 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/OSSLogic.java
  48. 14 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/SpecialScoreLogic.java
  49. 5 18
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/fromDev/impl/UpDownloadLogicImpl.java
  50. 10 8
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/CalculateScoreLogicImpl.java
  51. 52 33
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/CaseLogicImpl.java
  52. 41 4
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/CompetitionLogicImpl.java
  53. 21 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/ExamLogicImpl.java
  54. 72 39
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/OSSLogicImpl.java
  55. 65 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/SpecialScoreLogicImpl.java
  56. 2 0
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/TargetLogicImpl.java
  57. 1 3
      mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/UserLogicImpl.java
  58. 2 1
      mooctest-site-server/src/main/resources/log4j2.online.yaml
  59. 2 1
      mooctest-site-server/src/main/resources/log4j2.test.yaml
  60. 1 1
      mooctest-site-server/src/main/resources/log4j2.yaml
  61. 6 1
      mooctest-site-server/src/test/java/cn/iselab/mooctest/site/service/impl/CaseServiceImplTest.java
  62. 2 0
      mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/CaseLogicImplTest.java
  63. 7 5
      mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/CompetitionLogicImplTest.java
  64. 1 1
      mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/GeneralCalculateScoreComponentTest.java
  65. 96 0
      mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/VerficationLogicImplTest.java

+ 19 - 0
mooctest-site-server/pom.xml

@@ -209,6 +209,12 @@
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-zookeeper-config</artifactId>
         </dependency>
+        <!-- 分布式链路追踪 -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-zipkin</artifactId>
+            <version>1.0.0.RELEASE</version>
+        </dependency>
         <!-- zookeeper 依赖的健康检查的jar,所以需要引入actuator这个依赖 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -362,6 +368,19 @@
             <!--<version>1.3.5.RELEASE</version>-->
             <!--<optional>true</optional>-->
         <!--</dependency>-->
+
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-mockito</artifactId>
+            <version>1.6.5</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-module-junit4</artifactId>
+            <version>1.6.5</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 3 - 1
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/acyncTask/OnlineJudgeAndCulScoreCallBack.java

@@ -67,7 +67,9 @@ class OnlineJudgeAndCulScoreCallBack implements AsyncTaskCallBack {
         scores.add(new TypeScoreJson("cases",score));
         ResponseVO<ApplyUploadRecord> applyUploadRecordResponseVO = calculateSocreLogic.validateSubmit(uploadId);
         if(applyUploadRecordResponseVO.getCode() == ServerCode.SUCCESS.getCode()) {
-            calculateSocreLogic.recordTypeScoreDirectly(examId, caseId, userId, String.valueOf(System.currentTimeMillis()), applyUploadRecordResponseVO.getData().getOssUrl(), "慕码社区", scores);
+            calculateSocreLogic.recordTypeScoreDirectly(examId, caseId, userId, String.valueOf
+                    (System.currentTimeMillis()), applyUploadRecordResponseVO.getData().getOssUrl
+                    (), "慕码社区", scores, uploadId);
         }
         else {
             onlineJudgeResultDTOS.get(0).setResultMsg(onlineJudgeResultDTOS.get(0).getResultMsg()+" 提示:"+applyUploadRecordResponseVO.getMsg());

+ 117 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/aspect/LogAspect.java

@@ -0,0 +1,117 @@
+package cn.iselab.mooctest.site.common.aspect;
+
+import com.google.common.base.Stopwatch;
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.*;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.StringJoiner;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @program: mooctest-site
+ * @mail: menduo96@gmail.com
+ * @author: menduo
+ * @create: 2019-10-15 14:18
+ **/
+@Aspect
+@Component
+@Slf4j
+public class LogAspect {
+
+    @Pointcut("execution(public * cn.iselab.mooctest.site.web..*(..))")
+    private void logicPointCut(){}
+
+    @Pointcut("execution(public * cn.iselab.mooctest.site.web.data..*(..))")
+    private void wrapperPointCut(){}
+
+    @Pointcut("execution(public * cn.iselab.mooctest.site.web.SessionCounter.*(..))")
+    private void sessionCounter(){}
+
+
+    @Around("logicPointCut() && !wrapperPointCut() && !sessionCounter()")
+    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
+        beforeMethod(joinPoint);
+        Stopwatch stopwatch = Stopwatch.createStarted();
+        Object result = null;
+        try {
+            result = joinPoint.proceed();
+            stopwatch.stop();
+            return result;
+        } finally {
+            afterMethod(joinPoint,stopwatch,result);
+        }
+    }
+
+
+    private void beforeMethod(JoinPoint joinPoint) {
+        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
+        Method method = signature.getMethod();
+        Object[] args = joinPoint.getArgs();
+        String[] names = signature.getParameterNames();
+        Class[] classes = signature.getParameterTypes();
+        StringJoiner stringJoiner = new StringJoiner(",","[","]");
+        for (int i = 0; i < names.length; i++) {
+            if(isString(args[i]) || isPrimitive(args[i]) || classes[i].getName().contains("cn.iselab")) {
+                stringJoiner.add(names[i] + ":"+ createFilterGson().toJson(args[i]));
+            } else {
+                stringJoiner.add(names[i]);
+            }
+        }
+
+        log.info("方法名: [" + method.getDeclaringClass() + "." + method.getName() + "]"
+                + "--参数列表: " + stringJoiner.toString());
+    }
+
+
+    private void afterMethod(JoinPoint joinPoint,Stopwatch stopwatch,Object result) {
+        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
+        Method method = signature.getMethod();
+        log.info("方法名: [" + method.getDeclaringClass() + "." + method.getName() + "]"
+                + "--返回值: [" + object2String(result)  + "]"
+                + "--执行时间: [" + stopwatch.elapsed(TimeUnit.MILLISECONDS) + "ms].");
+
+    }
+
+    private String object2String(Object result) {
+        if(result ==null) {
+            return null;
+        } else {
+            return result.toString();
+        }
+    }
+
+    private static boolean isPrimitive(Object obj) {
+        try {
+            return ((Class<?>) obj.getClass().getField("TYPE").get(null)).isPrimitive();
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    private static boolean isString(Object obj) {
+        return obj instanceof String;
+    }
+
+
+    private Gson createFilterGson() {
+       return  new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
+            @Override
+            public boolean shouldSkipField(FieldAttributes f) {
+                return f.getName().contains("password");
+            }
+           @Override
+           public boolean shouldSkipClass(Class<?> aClass) {
+               return false;
+           }
+       }).create();
+    }
+}

+ 3 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/constant/CaseBlockConstants.java

@@ -28,4 +28,7 @@ public class CaseBlockConstants {
 
     //缺陷评分
     public static final int BUG_MARK=6;
+
+    //上传附件
+    public static final int UPLOAD_FILE=7;
 }

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/constant/DevLanguageConstants.java

@@ -11,4 +11,6 @@ public class DevLanguageConstants {
     public static final String JAVA="Java";
 
     public static final String PYTHON="Python";
+
+    public static final String CPP = "C++";
 }

+ 13 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/event/EventsListener.java

@@ -78,4 +78,17 @@ public class EventsListener implements InitializingBean {
             }
         }
     }
+
+    @Subscribe
+    public void afterQuitCompetition(QuitCompetitionEvent quitCompetitionEvent) throws Exception {
+        Competition competition = competitionService.getCompetiton(quitCompetitionEvent.getCompetitionId());
+        if (competition.getStatus() > 0) {
+            Competition2Exam competition2Exam = competitionService.getCompetition2TaskbyCompetitionIdAndIndex(
+                    quitCompetitionEvent.getCompetitionId(), competition.getStatus());
+            Long groupId = examLogic.getExamById(competition2Exam.getExamId()).getGroupIds().get(0);
+            if (groupService.isUserInGroup(quitCompetitionEvent.getUserId(), groupId)) {
+                groupService.deleteUserFromGroup(quitCompetitionEvent.getUserId(), groupId);
+            }
+        }
+    }
 }

+ 21 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/common/event/QuitCompetitionEvent.java

@@ -0,0 +1,21 @@
+package cn.iselab.mooctest.site.common.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-09-11 17:38
+ */
+@Getter
+@AllArgsConstructor
+public class QuitCompetitionEvent implements Event {
+    private Long userId;
+    private Long competitionId;
+
+    @Override
+    public String getDescription() {
+        return String.format("user %s quit competition %s", userId,competitionId);
+    }
+}

+ 7 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/configure/OSSConfiguration.java

@@ -1,6 +1,7 @@
 package cn.iselab.mooctest.site.configure;
 
 import cn.iselab.mooctest.site.data.config.OSSClientConfig;
+import cn.iselab.mooctest.site.data.config.STSConfig;
 import com.aliyun.oss.OSSClient;
 import com.aliyuncs.DefaultAcsClient;
 import com.aliyuncs.profile.DefaultProfile;
@@ -37,4 +38,10 @@ public class OSSConfiguration {
         OSSClient client = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret());
         return client;
     }
+
+    @Bean
+    @ConfigurationProperties(prefix = "sts")
+    public STSConfig createSTSConfig() {
+        return new STSConfig();
+    }
 }

+ 9 - 9
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/configure/RedisSessionConfiguration.java

@@ -19,14 +19,14 @@ public class RedisSessionConfiguration {
         return new SessionCounter();
     }
 
-    @Bean
-    public CookieSerializer cookieSerializer() {
-        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
-//        serializer.setCookieName("SESSION");
-        serializer.setCookiePath("/");
-        serializer.setDomainName(".mooctest.net");
-//        serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
-        return serializer;
-    }
+     @Bean
+     public CookieSerializer cookieSerializer() {
+         DefaultCookieSerializer serializer = new DefaultCookieSerializer();
+ //        serializer.setCookieName("SESSION");
+         serializer.setCookiePath("/");
+         serializer.setDomainName(".mooctest.net");
+ //        serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
+         return serializer;
+     }
 
 }

+ 1 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/configure/ShiroConfiguration.java

@@ -101,6 +101,7 @@ public class ShiroConfiguration {
 
         Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();
 
+        filterChainDefinitionManager.put("/api/cookie/set", "anon");
         filterChainDefinitionManager.put("/api/test/login", "anon");
         filterChainDefinitionManager.put("/api/test/register", "anon");
         filterChainDefinitionManager.put("/api/featureSwitch", "anon");

+ 18 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/AddOns2QualificationDao.java

@@ -1,6 +1,9 @@
 package cn.iselab.mooctest.site.dao;
 
 import cn.iselab.mooctest.site.models.AddOns2Qualification;
+import cn.iselab.mooctest.site.models.Qualification;
+import cn.iselab.mooctest.site.models.User;
+import java.math.BigInteger;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.data.repository.query.Param;
@@ -26,4 +29,19 @@ public interface AddOns2QualificationDao  extends CrudRepository<AddOns2Qualific
 
     @Query("select q.competitionId from AddOns2Qualification aq,Qualification q where aq.email=:userEmail and aq.qualificationId=q.id")
     List<Long> findSupervisedCompetitionId(@Param("userEmail")String userEmail);
+
+    @Query(nativeQuery = true, value = "select u.* from add_ons_2_qualification a2q "
+            + "JOIN qualification q on a2q.qualification_id = q.id "
+            + "JOIN `user` u on u.id = q.user_id "
+            + "where q.competition_id=:competitionId and a2q.add_ons_type=0 and a2q.email= "
+            + ":teacherEmail")
+    List<Object[]> findTeacherCompetitionStudents(@Param("competitionId") long competitionId, @Param
+            ("teacherEmail")String teacherEmail);
+
+    @Query(nativeQuery = true, value = "select q.id from add_ons_2_qualification a2q "
+            + "left JOIN qualification q on a2q.qualification_id = q.id "
+            + "where q.competition_id=:competitionId and a2q.add_ons_type=0 and a2q"
+            + ".email=:teacherEmail")
+    List<BigInteger> findTeachderTeamLeaderQid(@Param("competitionId") long competitionId, @Param
+            ("teacherEmail")String teacherEmail);
 }

+ 19 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/AnswerAnnexDao.java

@@ -0,0 +1,19 @@
+package cn.iselab.mooctest.site.dao;
+
+import cn.iselab.mooctest.site.models.AnswerAnnex;
+import org.springframework.data.repository.CrudRepository;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-09-25 17:31
+ */
+@Transactional
+public interface AnswerAnnexDao extends CrudRepository<AnswerAnnex, Long> {
+    List<AnswerAnnex> findAllByUserId(Long userId);
+
+    List<AnswerAnnex> findAllByUserIdAndExamIdAndCaseId(Long userId, Long examId, Long caseId);
+}

+ 1 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/QualificationDao.java

@@ -21,4 +21,5 @@ public interface QualificationDao extends CrudRepository<Qualification, Long> {
     //获取状态最新的qualification
     @Query(value="select * from qualification q where q.competition_id=:competitionId and q.user_id=:userId order by q.status desc limit 1",nativeQuery = true)
     Qualification findLatestQulificationByCompetitionIdAndUserId(@Param("competitionId")Long competitionId, @Param("userId")Long userId);
+    List<Qualification> findByCompetitionId(Long competitionId);
 }

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/UploadRecordDao.java

@@ -27,4 +27,6 @@ public interface UploadRecordDao extends JpaRepository<UploadRecord, Long> {
       + "where u.examId = :examId and u.caseId = :caseId")
     List<Long> retrieveUserIdsByExamIdAndCaseId(@Param("examId") long examId, @Param("caseId") long
       caseId);
+
+    UploadRecord findByApplyUploadId(long applyUploadId);
 }

+ 1 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/data/UploadRecordDTO.java

@@ -21,6 +21,7 @@ public class UploadRecordDTO {
     String OSSUrl;
     String source;
     String uploadTime;
+    Long applyUploadId;
 
     public UploadRecordDTO(UploadRecord uploadRecord) {
         BeanUtils.copyProperties(uploadRecord, this);

+ 1 - 1
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/data/config/OSSClientConfig.java

@@ -9,7 +9,7 @@ public class OSSClientConfig {
     private String endpoint;
     private String accessKeyId;
     private String accessKeySecret;
-    private String bucket;
+    private String bucket; // == oss.bucket.main
     private long expireTime;
     private String roleArn;
     private String region;

+ 32 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/data/config/STSConfig.java

@@ -0,0 +1,32 @@
+package cn.iselab.mooctest.site.data.config;
+
+import lombok.Data;
+
+/**
+ * @program: mooctest-site
+ * @mail: menduo96@gmail.com
+ * @author: menduo
+ * @create: 2019-11-07 15:49
+ **/
+@Data
+public class STSConfig {
+    private String endpoint;
+    private String accessKeyId;
+    private String accessKeySecret;
+    private String roleArn;
+    private final String roleSessionName = "mooctest";
+    private final String policy = "{\n" +
+            "    \"Version\": \"1\", \n" +
+            "    \"Statement\": [\n" +
+            "        {\n" +
+            "            \"Action\": [\n" +
+            "                \"oss:*\"\n" +
+            "            ], \n" +
+            "            \"Resource\": [\n" +
+            "                \"acs:oss:*:*:*\" \n" +
+            "            ], \n" +
+            "            \"Effect\": \"Allow\"\n" +
+            "        }\n" +
+            "    ]\n" +
+            "}";
+}

+ 36 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/AnswerAnnex.java

@@ -0,0 +1,36 @@
+package cn.iselab.mooctest.site.models;
+
+import lombok.Data;
+
+import javax.persistence.*;
+import java.sql.Timestamp;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-09-25 17:17
+ */
+@Data
+@Entity
+@Table(name = "answer_annex")
+public class AnswerAnnex {
+
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    @Column(name = "user_id")
+    private Long userId;
+
+    @Column(name = "exam_id")
+    private Long examId;
+
+    @Column(name = "case_id")
+    private Long caseId;
+
+    @Column(name = "url")
+    private String url;
+
+    @Column(name = "upload_time")
+    private Timestamp uploadTime;
+}

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/Competition.java

@@ -30,6 +30,8 @@ public class Competition {
     private String description;
     @Column(name="allow_enter")
     private Boolean allowEnter;
+    @Column(name="allow_quit")
+    private Boolean allowQuit;
     @Column(name="rank_weight")
     private Integer rankWeight;
     @Column(name="add_ons_editable")

+ 3 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/UploadRecord.java

@@ -40,4 +40,7 @@ public class UploadRecord {
     @Column(name = "upload_time")
     String uploadTime;
 
+    @Column(name = "apply_upload_id")
+    Long applyUploadId;
+
 }

+ 14 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/AnswerAnnexService.java

@@ -0,0 +1,14 @@
+package cn.iselab.mooctest.site.service;
+
+import java.util.List;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-09-25 18:19
+ */
+public interface AnswerAnnexService {
+    List<String> getUrls(Long userId, Long examId, Long caseId);
+
+    void recordUpload(Long examId, Long caseId, Long userId, String url);
+}

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/CaseService.java

@@ -25,4 +25,6 @@ public interface CaseService {
     CaseExtends save(CaseExtends caseExtends);
 
     Page<CaseExtends> getCasesByTargetId(long targetId, String keyword, Pageable pageable);
+
+    Map<String, String> getCaseProperties(long caseId);
 }

+ 11 - 1
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/CompetitionService.java

@@ -3,7 +3,9 @@ package cn.iselab.mooctest.site.service;
 import cn.iselab.mooctest.site.models.*;
 import cn.iselab.mooctest.site.web.data.AddonsVO;
 
+import cn.iselab.mooctest.site.web.data.UserVO;
 import java.util.List;
+import java.util.Map;
 
 /**
  *
@@ -42,6 +44,8 @@ public interface CompetitionService {
 
     List<AddOns2Qualification> getAddons2Qualification(Long qualificationId);
 
+    void deleteQualification(Long qualificationId);
+
     /**
      * create createAddons2Qualification
      * @param addOns2Qualification
@@ -89,5 +93,11 @@ public interface CompetitionService {
 
     Competition2Exam updateCompetition2TaskNextStatus(Long competitionId, Integer Index, Integer nextIndex);
 
-    boolean checkAddons(List<AddonsVO> addonsList, Long qualificationId, Integer type);
+    Map<String, Object> checkAddons(List<AddonsVO> addonsList, Long qualificationId, Integer type);
+
+    Map<String, Object> checkEnterCompetition(Long competitionId, Long userId);
+
+    List<UserVO> getSingleCompetitionStudents(long competitionId, long teacherId);
+
+    List<List<UserVO>> getTeamCompetitionStudents(long competitionId, long teacherId);
 }

+ 3 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/GeneralCalculateScoreService.java

@@ -1,5 +1,6 @@
 package cn.iselab.mooctest.site.service;
 
+import cn.iselab.mooctest.site.dao.UploadRecordDao;
 import cn.iselab.mooctest.site.data.GeneralGradeDTO;
 import cn.iselab.mooctest.site.data.UploadRecordDTO;
 import cn.iselab.mooctest.site.models.ApplyUploadRecord;
@@ -29,6 +30,8 @@ public interface GeneralCalculateScoreService {
 
   UploadRecordDTO getUploadRecord(long workerId, long examId, long caseId, String uploadTime);
 
+  UploadRecordDTO getUploadRecordByApplyId(long applyUploadId);
+
   UploadRecordDTO saveUploadRecords(UploadRecordDTO record);
 
   List<Long> getUploadUsers(long examId, long caseId);

+ 5 - 4
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/common/impl/ZipServiceImpl.java

@@ -27,10 +27,12 @@ public class ZipServiceImpl implements ZipService {
     private final String APP_SITE="kikbug-public";
 
     @Autowired
-    CaseTakeService CaseTakeService;
+    private CaseTakeService CaseTakeService;
 
     @Autowired
-    ReportService reportService;
+    private ReportService reportService;
+    @Autowired
+    private OSSClient ossClient;
 
     @Value("${oss.endPoint}")
     private String endPoint;
@@ -47,7 +49,6 @@ public class ZipServiceImpl implements ZipService {
 
     @Override
     public void zipForReport(long examId,long participantId,String path) throws Exception{
-        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
         List<CaseTake> caseTakes=CaseTakeService.getCaseTakeList2(examId,participantId);
         for (CaseTake caseTake:caseTakes){
             Report report=reportService.getReportByCaseTakeId(caseTake.getId());
@@ -67,7 +68,7 @@ public class ZipServiceImpl implements ZipService {
                 }
             }
         }
-        ossClient.shutdown();
+
     }
 
     private void downloadFromOSS(String path,String ossUrl,OSSClient ossClient){

+ 54 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/AnswerAnnexServiceImpl.java

@@ -0,0 +1,54 @@
+package cn.iselab.mooctest.site.service.impl;
+
+import cn.iselab.mooctest.site.dao.AnswerAnnexDao;
+import cn.iselab.mooctest.site.models.AnswerAnnex;
+import cn.iselab.mooctest.site.service.AnswerAnnexService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.sql.Timestamp;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-09-25 18:21
+ */
+@Slf4j
+@Service
+public class AnswerAnnexServiceImpl implements AnswerAnnexService {
+
+    @Autowired
+    private AnswerAnnexDao answerAnnexDao;
+
+    @Override
+    public List<String> getUrls(Long userId, Long examId, Long caseId) {
+        return answerAnnexDao.findAllByUserIdAndExamIdAndCaseId(userId, examId, caseId)
+                .stream().map(AnswerAnnex::getUrl).collect(Collectors.toList());
+    }
+
+    @Override
+    public void recordUpload(Long examId, Long caseId, Long userId, String url) {
+        List<AnswerAnnex> annexes = answerAnnexDao.findAllByUserIdAndExamIdAndCaseId(userId, examId, caseId);
+        AnswerAnnex answerAnnex = null;
+
+        if (annexes!=null && annexes.size()>0){
+            log.info("上传做题附件:考试-"+ examId +",题目-"+caseId + ", 用户-"+userId);
+            answerAnnex = annexes.stream().max(Comparator.comparing(AnswerAnnex::getId)).get();
+            answerAnnex.setUrl(url);
+            answerAnnex.setUploadTime(new Timestamp(System.currentTimeMillis()));
+        }else{
+            log.info("更新做题附件:考试-"+ examId +",题目-"+caseId + ", 用户-"+userId);
+            answerAnnex = new AnswerAnnex();
+            answerAnnex.setUploadTime(new Timestamp(System.currentTimeMillis()));
+            answerAnnex.setUrl(url);
+            answerAnnex.setExamId(examId);
+            answerAnnex.setCaseId(caseId);
+            answerAnnex.setUserId(userId);
+        }
+        answerAnnexDao.save(answerAnnex);
+    }
+}

+ 10 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/CaseServiceImpl.java

@@ -5,6 +5,9 @@ import cn.iselab.mooctest.site.dao.*;
 import cn.iselab.mooctest.site.models.*;
 import cn.iselab.mooctest.site.service.CaseService;
 import cn.iselab.mooctest.site.service.Entity2TagService;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import java.util.HashMap;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -124,6 +127,13 @@ public class CaseServiceImpl implements CaseService {
         return caseDao.findAll(where,pageable);
     }
 
+    @Override
+    public Map<String, String> getCaseProperties(long caseId) {
+        CaseExtends caseExtends = getCaseById(caseId);
+        return new Gson().fromJson(caseExtends.getProperties(), new
+                TypeToken<HashMap<String, String>>(){}.getType());
+    }
+
     private Specification<CaseExtends> getWhereTarget(long targetId, String keyword){
         return new Specification<CaseExtends>() {
             @Override

+ 163 - 35
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/CompetitionServiceImpl.java

@@ -6,16 +6,18 @@ import cn.iselab.mooctest.site.dao.*;
 import cn.iselab.mooctest.site.models.*;
 import cn.iselab.mooctest.site.service.CompetitionService;
 import cn.iselab.mooctest.site.web.data.AddonsVO;
+import cn.iselab.mooctest.site.web.data.UserVO;
+import java.math.BigInteger;
+import javax.jws.soap.SOAPBinding.Use;
 import org.apache.commons.collections.IteratorUtils;
+import org.apache.shiro.SecurityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
- *
  * @author tangshanshan
  * @date 2017/11/3
  */
@@ -61,36 +63,38 @@ public class CompetitionServiceImpl implements CompetitionService {
 
     @Override
     public Qualification getQualification(Long competitionId, Long userId) {
-        return qualificationDao.findLatestQulificationByCompetitionIdAndUserId(competitionId,userId);
+        return qualificationDao.findLatestQulificationByCompetitionIdAndUserId(competitionId, userId);
     }
 
-    //    @Override
-//    public Qualification createOrUpdateQualification(Qualification qualification) {
-//        Qualification qualification1 = qualificationDao.findByCompetitionIdAndUserIdAndStatus(qualification.getCompetitionId(),
-//                qualification.getUserId(), qualification.getStatus());
-//        if(qualification1 == null) {
-//            return qualificationDao.save(qualification);
-//        }
-//        return qualification1;
-//    }
     @Override
     public Qualification createOrUpdateQualification(Qualification qualification) {
-        Qualification qualification1 = qualificationDao.findByCompetitionIdAndUserIdAndStatus(qualification.getCompetitionId(),
+        Qualification newQualification = qualificationDao.findByCompetitionIdAndUserIdAndStatus(qualification.getCompetitionId(),
                 qualification.getUserId(), qualification.getStatus());
-        //System.out.println(qualification1.toString());
-        if(qualification1 == null) {
-            //修改原有数据
-
+        if (newQualification == null) {
             //插入新数据
-            qualification1 = new Qualification();
-            qualification1.setCompetitionId(qualification.getCompetitionId());
-            qualification1.setNextRound(qualification.getNextRound());
-            qualification1.setStatus(qualification.getStatus());
-            qualification1.setUserId(qualification.getUserId());
-            return qualificationDao.save(qualification1);
+            Qualification temp = new Qualification();
+            temp.setCompetitionId(qualification.getCompetitionId());
+            temp.setNextRound(qualification.getNextRound());
+            temp.setStatus(qualification.getStatus());
+            temp.setUserId(qualification.getUserId());
+            newQualification = qualificationDao.save(temp);
+            //修改add_ons_2_qualification表
+            List<AddOns2Qualification> oldAddOns2Qualifications = addOns2QualificationDao.findByQualificationId(qualification.getId());
+            List<AddOns2Qualification> newAddOns2Qualifications = new LinkedList<>();
+            for (AddOns2Qualification addOns2Qualification : oldAddOns2Qualifications) {
+                AddOns2Qualification tmpAddOn = new AddOns2Qualification();
+                tmpAddOn.setQualificationId(newQualification.getId());
+                tmpAddOn.setName(addOns2Qualification.getName());
+                tmpAddOn.setEmail(addOns2Qualification.getEmail());
+                tmpAddOn.setAddonsType(addOns2Qualification.getAddonsType());
+                newAddOns2Qualifications.add(tmpAddOn);
+            }
+            addOns2QualificationDao.save(newAddOns2Qualifications);
+
         }
-        return qualification1;
+        return newQualification;
     }
+
     @Override
     public List<Qualification> getQualificationByCompetitionIdAndIndex(Long competitionId, Integer status) {
         return qualificationDao.findByCompetitionIdAndStatus(competitionId, status);
@@ -107,6 +111,11 @@ public class CompetitionServiceImpl implements CompetitionService {
     }
 
     @Override
+    public void deleteQualification(Long qualificationId) {
+        qualificationDao.delete(qualificationId);
+    }
+
+    @Override
     public AddOns2Qualification createAddOns2Qualification(AddOns2Qualification addOns2Qualification) {
         return null;
     }
@@ -123,7 +132,7 @@ public class CompetitionServiceImpl implements CompetitionService {
         competition2Exam.setCompetitionId(competitionId);
         int index = 1;
         ArrayList<Competition2Exam> competition2Exams = competition2ExamDao.findByCompetitionIdOrderByIndexDesc(competitionId);
-        if (competition2Exams.size()>0) {
+        if (competition2Exams.size() > 0) {
             index = competition2Exams.get(0).getIndex() + 1;
         }
         competition2Exam.setIndex(index);
@@ -139,15 +148,15 @@ public class CompetitionServiceImpl implements CompetitionService {
 
     @Override
     public List<AddOns2Qualification> updateAddons(List<AddOns2Qualification> addonsList, Long qualificationId, Integer type) {
-        List<AddOns2Qualification> deletedAddons = addOns2QualificationDao.findByQualificationIdAndAddonsType(qualificationId,type);
+        List<AddOns2Qualification> deletedAddons = addOns2QualificationDao.findByQualificationIdAndAddonsType(qualificationId, type);
         addOns2QualificationDao.delete(deletedAddons);
 
         List<AddOns2Qualification> savedAddons = IteratorUtils.toList(addOns2QualificationDao.save(addonsList).iterator());
 
         List<String> changedAddons = deletedAddons.stream().map(AddOns2Qualification::getEmail).collect(Collectors.toList());
         changedAddons.addAll(savedAddons.stream().map(AddOns2Qualification::getEmail).collect(Collectors.toList()));
-        if(type == AddOns2Qualification.ADDONS_TYPE_TEACHER){
-            eventUtil.post(new UpdateContestMentorEvent(qualificationId,changedAddons));
+        if (type == AddOns2Qualification.ADDONS_TYPE_TEACHER) {
+            eventUtil.post(new UpdateContestMentorEvent(qualificationId, changedAddons));
         }
         return savedAddons;
     }
@@ -164,6 +173,7 @@ public class CompetitionServiceImpl implements CompetitionService {
         competition2ExamDao.save(result);
         return result;
     }
+
     @Override
     public Competition2Exam getCompetition2TaskbyCompetitionIdAndIndex(Long competitionId, Integer index) {
         return competition2ExamDao.findByCompetitionIdAndIndex(competitionId, index);
@@ -172,7 +182,7 @@ public class CompetitionServiceImpl implements CompetitionService {
     @Override
     public Competition2Exam updateCompetition2TaskbyCompetitionIdAndIndex(Long competitionId, Integer index, boolean activeStatusAfterUpdating) {
         Competition2Exam result = competition2ExamDao.findByCompetitionIdAndIndex(competitionId, index);
-        if(result.isActive() ==  activeStatusAfterUpdating) {
+        if (result.isActive() == activeStatusAfterUpdating) {
             return result;
         }
         result.setActive(activeStatusAfterUpdating);
@@ -180,8 +190,26 @@ public class CompetitionServiceImpl implements CompetitionService {
         return result;
 
     }
+
     @Override
-    public boolean checkAddons(List<AddonsVO> addonsList, Long qualificationId, Integer type) {
+    public Map<String, Object> checkAddons(List<AddonsVO> addonsList, Long qualificationId, Integer type) {
+        Map<String, Object> res = new HashMap<>();
+//        if (type == null)
+//            return false;
+//        if (type == 0)
+//            return true;
+        if (type == null) {
+            res.put("code", 1);
+            res.put("message", "类型出错");
+            return res;
+        }
+        if (type == 0) {
+            res.put("code", 0);
+            res.put("message", "修改成功");
+            return res;
+        }
+        //获取当前用户信息
+        Long currentUserId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
         //获取当前队伍比赛信息
         Qualification qualification = qualificationDao.findOne(qualificationId);
         //获取所有参加当前比赛的队伍
@@ -195,7 +223,10 @@ public class CompetitionServiceImpl implements CompetitionService {
                     for (AddonsVO currAddons : addonsList) {
                         //如果信息已存在则返回错误
                         if (currAddons.getEmail().equals(addons.getEmail())) {
-                            return false;
+                            res.put("code", 2);
+                            res.put("message", "修改失败,队员'" + addons.getEmail() + "'已加入其它队伍!");
+                            return res;
+                            //return false;
                         }
                     }
                 }
@@ -205,15 +236,112 @@ public class CompetitionServiceImpl implements CompetitionService {
         for (AddonsVO addonsVO : addonsList) {
             User user = userDao.findByEmail(addonsVO.getEmail());
             if (null != user) {
+                //查看添加的队员是否为当前登录用户
+                if (user.getId().equals(currentUserId)) {
+                    res.put("code", 4);
+                    res.put("message", "修改失败,队员'" + user.getEmail() + "'已是队长,无法添加为队员");
+                    return res;
+                }
                 for (Qualification temp : qualifications) {
                     if (temp.getUserId().equals(user.getId())) {
-                        return false;
+                        res.put("code", 3);
+                        res.put("message", "修改失败,队员'" + user.getEmail() + "'已是其他队伍的队长");
+                        return res;
                     }
                 }
             }
         }
-        //默认返回
-        return true;
+        res.put("code", 0);
+        res.put("message", "修改成功");
+        return res;
+    }
+
+    @Override
+    public Map<String, Object> checkEnterCompetition(Long competitionId, Long userId) {
+        //获取所有competitionId与当前参加的比赛id相同的队伍
+        List<Qualification> qualifications = qualificationDao.findByCompetitionId(competitionId);
+        //获取当前用户信息
+        User user = userDao.findById(userId);
+        Map<String, Object> res = new HashMap<>();
+        for (Qualification qualification : qualifications) {
+            Long captainId = qualification.getUserId();
+            //当队长id与参赛的id相同,说明该用户已经是其他队伍的队长,返回错误信息
+            if (captainId.equals(userId)) {
+                res.put("code", 1);
+                res.put("message", "您(" + user.getEmail() + ")已参加该比赛,无法再次报名");
+                return res;
+            }
+            //获取该队伍的所有队员信息
+            List<AddOns2Qualification> addOns2Qualifications = addOns2QualificationDao.findByQualificationId(qualification.getId());
+            //遍历所有队员信息,如果存在队员邮箱与当前用户邮箱相同,说明该用户已加入其他队伍,返回错误信息
+            for (AddOns2Qualification addOns2Qualification : addOns2Qualifications) {
+                if (addOns2Qualification.getEmail().equals(user.getEmail())) {
+                    res.put("code", 2);
+                    res.put("message", "您(" + user.getEmail() + ")已加入其他队伍,无法再次报名");
+                    return res;
+                }
+            }
+        }
+        res.put("code", 0);
+        res.put("message", "加入成功");
+        return res;
+    }
+
+    @Override
+    public List<UserVO> getSingleCompetitionStudents(long competitionId, long teacherId) {
+        User teacher = userDao.findById(teacherId);
+        if(teacher == null){
+            throw new IllegalArgumentException("教师不存在!teacherId:"+teacherId);
+        }
+        List<Object[]> students = addOns2QualificationDao.findTeacherCompetitionStudents
+                (competitionId, teacher.getEmail());
+        return students.stream().map(s->{
+            UserVO uv = new UserVO();
+            uv.setName((String)s[1]);
+            uv.setEmail((String)s[2]);
+            return uv;
+        }).collect(Collectors.toList());
     }
 
+    @Override
+    public List<List<UserVO>> getTeamCompetitionStudents(long competitionId, long teacherId) {
+        User teacher = userDao.findById(teacherId);
+        if(teacher == null){
+            throw new IllegalArgumentException("教师不存在!teacherId:"+teacherId);
+        }
+        List<BigInteger> leaderQid = addOns2QualificationDao.findTeachderTeamLeaderQid(competitionId,
+                teacher.getEmail());
+
+        List<List<UserVO>> teamList = new ArrayList<>();
+        leaderQid.forEach(bgid -> {
+            //bigInteger转Long
+            Long qid = Long.parseLong(String.valueOf(bgid));
+            //团队赛队员
+            List<AddOns2Qualification> a2qs = addOns2QualificationDao
+                    .findByQualificationIdAndAddonsType(qid, AddOns2Qualification
+                            .ADDONS_TYPE_MEMBER);
+            List<UserVO> userVOList = a2qs.stream().map(a2q -> {
+                UserVO userVO = new UserVO();
+                userVO.setName(a2q.getName());
+                userVO.setEmail(a2q.getEmail());
+                return userVO;
+            }).collect(Collectors.toList());
+
+            //团队赛队长
+            Qualification leaderQua = qualificationDao.findOne(qid);
+            User leader = userDao.findById(leaderQua.getUserId());
+            if(leader == null){
+                throw new IllegalArgumentException("队长不存在!队长id:"+leaderQua.getUserId());
+            }
+            UserVO leaderVO = new UserVO();
+            leaderVO.setName(leader.getName());
+            leaderVO.setEmail(leader.getEmail());
+            userVOList.add(leaderVO);
+
+            teamList.add(userVOList);
+
+        });
+
+        return teamList;
+    }
 }

+ 6 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/GeneralCalculateScoreServiceImpl.java

@@ -164,6 +164,12 @@ public class GeneralCalculateScoreServiceImpl implements GeneralCalculateScoreSe
   }
 
   @Override
+  public UploadRecordDTO getUploadRecordByApplyId(long applyUploadId) {
+    UploadRecord uploadRecord = uploadRecordDao.findByApplyUploadId(applyUploadId);
+    return uploadRecord==null?null:new UploadRecordDTO(uploadRecord);
+  }
+
+  @Override
   public UploadRecordDTO saveUploadRecords(UploadRecordDTO recordDTO) {
     UploadRecord uploadRecord = uploadRecordDao.save(recordDTO.toUploadRecord());
     return uploadRecord==null?null:new UploadRecordDTO(uploadRecord);

+ 22 - 4
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/SubmitRecordServiceImpl.java

@@ -9,6 +9,7 @@ import cn.iselab.mooctest.site.models.ContestMentorSubmitRecord;
 import cn.iselab.mooctest.site.models.SubmitRecord;
 import cn.iselab.mooctest.site.models.CaseExtends;
 import cn.iselab.mooctest.site.models.Exam;
+import cn.iselab.mooctest.site.service.CaseService;
 import cn.iselab.mooctest.site.service.SubmitRecordService;
 import cn.iselab.mooctest.site.service.BaseService;
 import cn.iselab.mooctest.site.service.ExamService;
@@ -16,10 +17,12 @@ import cn.iselab.mooctest.site.service.webIDE.WebIDEUrlService;
 import cn.iselab.mooctest.site.web.exception.HttpNotFoundException;
 import cn.iselab.mooctest.site.web.logic.CalculateSocreLogic;
 import com.google.common.collect.Lists;
+import java.util.Map;
 import org.apache.shiro.SecurityUtils;
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
@@ -53,6 +56,13 @@ public class SubmitRecordServiceImpl extends BaseService implements SubmitRecord
 
     @Autowired
     private WebIDEUrlService webIDEUrlService;
+
+    @Autowired
+    private CaseService caseService;
+
+    @Value("${crowd.address}")
+    private String crowdAddress;
+
     @Override
     public SubmitRecord saveOrUpdateAssignedTask(SubmitRecord submitRecord) {
         return submitRecordDao.save(submitRecord);
@@ -94,12 +104,20 @@ public class SubmitRecordServiceImpl extends BaseService implements SubmitRecord
                     Result submitResult = new Result();
                     submitResult.setResultUrl(resultUrlJsonArray.getString(i));
 
-
                     if (submitResult.getResultUrl().isEmpty()) {
 
-                        submitResult.setResultUrl(
-                                webIDEUrlService.generateUrlForWebIDE(submitRecord.getParticipantId(),
-                                        submitRecord.getExamId(), targetId, assignedCase.getCaseId(), assignedCase.getCaseName(), false, true));
+                        Map<String, String> caseProperties = caseService.getCaseProperties(caseJson
+                                .getLong("id"));
+                        if(caseProperties.get("testType").equals("13")){
+                            submitResult.setResultUrl
+                                    (crowdAddress+"/report/detail/"+submitRecord.getExamId
+                                            ()+"/"+caseJson.getLong("id")+"/"+submitRecord.getParticipantId());
+                        }else{
+                            submitResult.setResultUrl(
+                                    webIDEUrlService.generateUrlForWebIDE(submitRecord.getParticipantId(),
+                                            submitRecord.getExamId(), targetId, assignedCase.getCaseId(), assignedCase.getCaseName(), false, true));
+                        }
+
                     }
                     resultList.add(submitResult);
                 }

+ 10 - 7
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/updownload/impl/DownloadServiceImpl.java

@@ -7,7 +7,9 @@ import com.aliyun.oss.model.GeneratePresignedUrlRequest;
 import com.aliyun.oss.model.GetObjectRequest;
 import com.aliyun.oss.model.OSSObjectSummary;
 import com.aliyun.oss.model.ObjectListing;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
 import org.springframework.stereotype.Service;
@@ -23,6 +25,7 @@ import java.util.List;
  * @Modified By:
  */
 @Service
+@Slf4j
 @ConditionalOnExpression("${featureSwitch.client.oss}==true")
 public class DownloadServiceImpl implements DownloadService {
 
@@ -43,14 +46,16 @@ public class DownloadServiceImpl implements DownloadService {
 
     private String DOWNLOAD_PATH = "/download/";
 
+    @Autowired
+    private OSSClient ossClient;
+
     @Override
     public String generateUrlForDevAnalysis(long taskID,long stuID,String caseName){
         //生成路径
         String ossDir = "data/answers/" + taskID + "/" + stuID + "/";
-        System.out.println(accessKeyId+" "+endPoint+" "+accessKeySecret);
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
+        //System.out.println(accessKeyId+" "+endPoint+" "+accessKeySecret);
 
-        ObjectListing objectListing = client.listObjects(bucketNameDev, ossDir);
+        ObjectListing objectListing = ossClient.listObjects(bucketNameDev, ossDir);
         List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
         long latestTimestamp = 0;
         //遍历该目录下所有的文件找到最新的提交文件
@@ -68,7 +73,7 @@ public class DownloadServiceImpl implements DownloadService {
             request.setContentType("application/octet-stream");
             // 添加user meta
             request.addUserMetadata("author", "aliy");
-            return client.generatePresignedUrl(request).toString().split("\\?")[0];
+            return ossClient.generatePresignedUrl(request).toString().split("\\?")[0];
         }else {
             File file=new File(LOCAL_PATH+ossDir);
             if(file.exists()){
@@ -84,9 +89,8 @@ public class DownloadServiceImpl implements DownloadService {
     }
 
     @Override
-    public String download(String url)throws Exception{
+    public String download(String url) {
         String name = url.split("/")[url.split("/").length - 1];
-        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
         if(url.contains("http://")){
             if(url.contains(bucketNameDev)) {
                 ossClient.getObject(new GetObjectRequest(bucketNameDev, url.substring(49)), new File(FileUtils.getUserDirectory() + "/" + name));
@@ -96,7 +100,6 @@ public class DownloadServiceImpl implements DownloadService {
         }else {
             ossClient.getObject(new GetObjectRequest(bucketNameDev, url), new File(FileUtils.getUserDirectory() + "/" + name));
         }
-        ossClient.shutdown();
         return FileUtils.getUserDirectory()+"/"+name;
     }
 

+ 71 - 12
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/CompetitionController.java

@@ -1,17 +1,18 @@
 package cn.iselab.mooctest.site.web.ctrl;
 
 import cn.iselab.mooctest.site.common.constant.UrlConstants;
-import cn.iselab.mooctest.site.models.Qualification;
-import cn.iselab.mooctest.site.models.User;
 import cn.iselab.mooctest.site.web.data.AddonsVO;
 import cn.iselab.mooctest.site.web.data.CompetitionVO;
+import cn.iselab.mooctest.site.web.data.UserVO;
 import cn.iselab.mooctest.site.web.logic.CompetitionLogic;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.annotation.RequiresRoles;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Created by tangshanshan on 2017/11/3.
@@ -32,6 +33,12 @@ public class CompetitionController {
         return competitionLogic.updateAnnouncement(announcement);
     }
 
+    @RequestMapping(value = UrlConstants.API + "competition/quit/{competitionId}", method = RequestMethod.POST)
+    public void quitContest(@PathVariable("competitionId") Long competitionId) {
+        Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
+        competitionLogic.quitCompetition(competitionId, userId);
+    }
+
     @RequestMapping(value = UrlConstants.API + "competition", method = RequestMethod.GET)
     public List<CompetitionVO> getContest() {
         Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
@@ -39,26 +46,78 @@ public class CompetitionController {
     }
 
     @RequestMapping(value = UrlConstants.API + "competition/enter/{competitionId}", method = RequestMethod.POST)
-    public Qualification enterContest(@PathVariable("competitionId") Long competitionId) {
+    public Map<String, Object> enterContest(@PathVariable("competitionId") Long competitionId) {
         Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
         return competitionLogic.enterCompetition(competitionId, userId);
     }
 
+    //    @RequestMapping(value = UrlConstants.API + "competition/addons/{qualificationId}/{type}", method = RequestMethod.POST)
+//    public List<AddonsVO> updateAddons(@PathVariable("qualificationId") Long qualificationId,
+//                                       @PathVariable("type") Integer type,
+//                                       @RequestBody List<AddonsVO> addonsVOList) {
+//        //TODO 校验addonsVOList的大小是否超过上限
+//        for(int i=0;i<addonsVOList.size();i++){
+//            if(!addonsVOList.get(i).getAddonsType().equals(type)
+//                    || !addonsVOList.get(i).getQualificationId().equals(qualificationId)){
+//                throw new IllegalArgumentException("different type or qualificationId");
+//            }
+//        }
+//        if(!competitionLogic.checkAddons(addonsVOList,qualificationId,type)){
+//            return null;
+//        }
+//        return competitionLogic.updateAddons(addonsVOList, qualificationId, type);
+//    }
     @RequestMapping(value = UrlConstants.API + "competition/addons/{qualificationId}/{type}", method = RequestMethod.POST)
-    public List<AddonsVO> updateAddons(@PathVariable("qualificationId") Long qualificationId,
-                                       @PathVariable("type") Integer type,
-                                       @RequestBody List<AddonsVO> addonsVOList) {
+    public Map<String, Object> updateAddons(@PathVariable("qualificationId") Long qualificationId,
+                                            @PathVariable("type") Integer type,
+                                            @RequestBody List<AddonsVO> addonsVOList) {
         //TODO 校验addonsVOList的大小是否超过上限
-        for(int i=0;i<addonsVOList.size();i++){
-            if(!addonsVOList.get(i).getAddonsType().equals(type)
-                    || !addonsVOList.get(i).getQualificationId().equals(qualificationId)){
+        Map<String, Object> map = new HashMap<>();
+        for (int i = 0; i < addonsVOList.size(); i++) {
+            if (!addonsVOList.get(i).getAddonsType().equals(type)
+                    || !addonsVOList.get(i).getQualificationId().equals(qualificationId)) {
                 throw new IllegalArgumentException("different type or qualificationId");
             }
         }
-        if(!competitionLogic.checkAddons(addonsVOList,qualificationId,type)){
-            return null;
+        Map<String, Object> addOnCheck = competitionLogic.checkAddons(addonsVOList, qualificationId, type);
+        if (!addOnCheck.get("code").equals(0)) {
+            map.put("code", 1);
+            map.put("message", addOnCheck.get("message"));
+            return map;
         }
-        return competitionLogic.updateAddons(addonsVOList, qualificationId, type);
+        List<AddonsVO> addonsVOS = competitionLogic.updateAddons(addonsVOList, qualificationId, type);
+        map.put("code", 0);
+        map.put("data", addonsVOS);
+        map.put("message", "修改成功");
+        return map;
+    }
+
+    /**
+     * 单人赛学生名单
+     * @param competitionId
+     * @param teacherId
+     * @return userVO 单个学生名单
+     */
+    @RequiresRoles("manager")
+    @RequestMapping(value = UrlConstants.API +
+            "competition/singleCompetitionStudents/{competitionId}/{teacherId}")
+    public List<UserVO> getSingleCompetitionStudents(@PathVariable("competitionId") long competitionId,
+            @PathVariable("teacherId") long teacherId){
+        return competitionLogic.getSingleCompetitionStudents(competitionId, teacherId);
+    }
+
+    /**
+     * 团队赛学生名单
+     * @param competitionId
+     * @param teacherId
+     * @return List<UserVO> 一个团队的学生名单
+     */
+    @RequiresRoles("manager")
+    @RequestMapping(value = UrlConstants.API +
+            "competition/teamCompetitionStudents/{competitionId}/{teacherId}")
+    public List<List<UserVO>> getTeamCompetitionStudents(@PathVariable("competitionId") long
+            competitionId, @PathVariable("teacherId") long teacherId){
+        return competitionLogic.getTeamCompetitionStudents(competitionId, teacherId);
     }
 
 }

+ 20 - 6
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/ExamController.java

@@ -1,15 +1,13 @@
 package cn.iselab.mooctest.site.web.ctrl;
 
 import cn.iselab.mooctest.site.common.constant.UrlConstants;
+import cn.iselab.mooctest.site.dao.AnswerAnnexDao;
+import cn.iselab.mooctest.site.models.AnswerAnnex;
 import cn.iselab.mooctest.site.models.instancePermission.ExamPermission;
+import cn.iselab.mooctest.site.service.AnswerAnnexService;
 import cn.iselab.mooctest.site.web.data.*;
 import cn.iselab.mooctest.site.web.exception.HttpBadRequestException;
-import cn.iselab.mooctest.site.web.logic.ExamLogic;
-import cn.iselab.mooctest.site.web.logic.PaperLogic;
-import cn.iselab.mooctest.site.web.logic.StarCaseLogic;
-import cn.iselab.mooctest.site.web.logic.SimilarityLogic;
-import cn.iselab.mooctest.site.web.logic.UserLogic;
-import cn.iselab.mooctest.site.web.logic.VisitControlLogic;
+import cn.iselab.mooctest.site.web.logic.*;
 import cn.iselab.mooctest.site.common.enums.EntityTypeEnum;
 import com.google.gson.Gson;
 import org.apache.shiro.SecurityUtils;
@@ -23,9 +21,11 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
@@ -51,6 +51,10 @@ public class ExamController extends BaseSearchController {
     private VisitControlLogic visitControlLogic;
     @Autowired
     private StarCaseLogic starCaseLogic;
+    @Autowired
+    private AnswerAnnexDao answerAnnexDao;
+    @Autowired
+    private OSSLogic ossLogic;
 
     private Logger LOG = LoggerFactory.getLogger(getClass());
 
@@ -433,4 +437,14 @@ public class ExamController extends BaseSearchController {
         }
     }
 
+    @RequestMapping(value = "/api/upload_answer_annex/{examId}/{caseId}", method = RequestMethod.POST)
+    public void uploadAnswerAnnex(@RequestParam("file") MultipartFile file, @PathVariable("examId") Long examId, @PathVariable("caseId") Long caseId){
+        if (file==null)
+            throw new HttpBadRequestException("请勿上传空文件");
+        Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
+        LOG.info("filename: " + file.getOriginalFilename());
+        LOG.info("examId: "+ examId + ", caseId: "+caseId);
+        examLogic.uploadAnswerAnnex(userId, examId, caseId, file);
+    }
+
 }

+ 14 - 2
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/ScoreController.java

@@ -20,7 +20,9 @@ import cn.iselab.mooctest.site.web.data.response.ServerCode;
 import cn.iselab.mooctest.site.web.logic.CalculateSocreLogic;
 import cn.iselab.mooctest.site.web.logic.ExamLogic;
 import cn.iselab.mooctest.site.web.logic.GeneralCalculateScoreLogic;
+import cn.iselab.mooctest.site.web.logic.SpecialScoreLogic;
 import cn.iselab.mooctest.site.web.response.SuccessResult;
+import javax.annotation.Resource;
 import org.apache.shiro.authz.annotation.RequiresRoles;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -51,6 +53,9 @@ public class ScoreController extends BaseController {
     @Autowired
     ExamLogic examLogic;
 
+    @Resource
+    SpecialScoreLogic specialScoreLogic;
+
     //一次考试的一道题的所有人的分
     @RequestMapping(value = UrlConstants.API + "score/{examId}/{caseId}", method = RequestMethod.PUT)
     public void CalculateScore(@PathVariable("examId") long taskId, @PathVariable("caseId") long caseId) throws Exception {
@@ -139,7 +144,8 @@ public class ScoreController extends BaseController {
                 applyUploadRecord.getWorkerId(),
                 uploadTime,
                 source,
-                caughtNodeDTOs,applyUploadRecord.getOssUrl());
+                caughtNodeDTOs,applyUploadRecord.getOssUrl(),
+                uploadId);
         return new ResponseVO(ServerCode.SUCCESS);
     }
 
@@ -165,7 +171,8 @@ public class ScoreController extends BaseController {
                 uploadTime,
                 applyUploadRecord.getOssUrl(),
                 source,
-                typeScoreJsonList);
+                typeScoreJsonList,
+                uploadId);
 
         return new ResponseVO(ServerCode.SUCCESS);
     }
@@ -287,4 +294,9 @@ public class ScoreController extends BaseController {
         return calculateSocreLogic.getCompeteAnalysisByPage(null, null, caseId,
                 Integer.parseInt(activePage), Integer.parseInt(rowsOnPage), sort, competeAnalysisType);
     }
+
+    @RequestMapping(value = UrlConstants.API + "crowdScores/{examId}", method = RequestMethod.GET)
+    public void pullCrowdScores(@PathVariable("examId") long examId){
+        specialScoreLogic.pullCrowdScore(examId);
+    }
 }

+ 35 - 7
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/TestController.java

@@ -13,11 +13,13 @@ import cn.iselab.mooctest.site.service.RecordService;
 import cn.iselab.mooctest.site.service.User2RoleService;
 import cn.iselab.mooctest.site.util.data.EncryptionUtil;
 import cn.iselab.mooctest.site.web.SessionCounter;
+import cn.iselab.mooctest.site.web.data.OSSClientConfigVO;
 import cn.iselab.mooctest.site.web.data.UserVO;
 import cn.iselab.mooctest.site.web.data.wrapper.UserVOWrapper;
 import cn.iselab.mooctest.site.web.exception.HttpBadRequestException;
 import cn.iselab.mooctest.site.web.exception.HttpUnauthorizedException;
 import cn.iselab.mooctest.site.web.logic.MenuLogic;
+import cn.iselab.mooctest.site.web.logic.OSSLogic;
 import cn.iselab.mooctest.site.web.logic.PermissionLogic;
 import cn.iselab.mooctest.site.web.logic.UserLogic;
 import org.apache.shiro.SecurityUtils;
@@ -30,13 +32,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
+import java.util.Map;
 
 /**
  * Created by Liu on 2017/6/5.
@@ -76,12 +79,14 @@ public class TestController {
 
     @Autowired
     OSSClientConfig clientConfig;
+    @Autowired
+    private OSSLogic ossLogic;
 
     private Logger LOG = LoggerFactory.getLogger(getClass());
 
     @PointChange(value = "login")
     @RequestMapping(value = "/api/test/login", method = RequestMethod.POST)
-    public UserVO login(@RequestBody UserVO userVO, BindingResult bindingResult, HttpServletRequest request) {
+    public UserVO login(@RequestBody UserVO userVO, BindingResult bindingResult, HttpServletRequest request, HttpServletResponse response) {
         // LOG.info("\n\n\n\n\n\nSessionId: "+SecurityUtils.getSubject().getSession().getId()+"\n\n\n\n\n");
         if (bindingResult.hasErrors()) {
             throw new HttpUnauthorizedException("unauthorized");
@@ -154,6 +159,11 @@ public class TestController {
 //                ManagerProperty managerProperty = managerPropertyService.getManagerPropertyByUserId(userVO.getId());
 //                userVO.setExpireTime(Long.valueOf(managerProperty.getExpireTime().getTime()));
 //            }
+
+            Cookie cookie = new Cookie("sessionId", request.getSession().getId());
+            cookie.setPath("/");
+            cookie.setHttpOnly(false);
+            response.addCookie(cookie);
             return userVO;
         } else {
             token.clear();
@@ -212,11 +222,29 @@ public class TestController {
         return clientFeatures;
     }
 
+    @RequestMapping(value = "/api/ossConfiguration",method = RequestMethod.POST)
+    public OSSClientConfigVO getOSSConfiguration(){
+        OSSClientConfigVO ossClientConfigVO = ossLogic.getSTSToken();
+        ossClientConfigVO.setBucket(clientConfig.getBucket());
+        ossClientConfigVO.setEndpoint(clientConfig.getEndpoint());
+        ossClientConfigVO.setRegion(clientConfig.getRegion());
+        return ossClientConfigVO;
+    }
+
     @RequestMapping(value = "/api/ossConfig",method = RequestMethod.POST)
+    @Deprecated
     public OSSClientConfig getOSSConfig(){
         return clientConfig;
     }
 
-
-
+    @RequestMapping(value = "/api/cookie/set", method = RequestMethod.GET)
+    public String cookieTest(@RequestParam("sessionId") String sessionId, HttpServletResponse response){
+        LOG.info("\n\n\nsessionId: "+ sessionId+"\n\n");
+        Cookie cookie = new Cookie("SESSION", sessionId);
+        cookie.setHttpOnly(true);
+        cookie.setPath("/");
+        response.addCookie(cookie);
+        response.setHeader("P3P","CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");
+        return "sessionId: " + sessionId;
+    }
 }

+ 3 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/CaseExtendsVO.java

@@ -33,5 +33,8 @@ public class CaseExtendsVO extends CaseVO {
     //控制考试界面case模块按钮显示向量
     private List<Integer> showBtns;
 
+    //做题上传的答案附件
+    private List<String> annexList;
+
     private VisitControlAttr visitControlAttr;
 }

+ 1 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/CompetitionVO.java

@@ -19,6 +19,7 @@ public class CompetitionVO {
     private Boolean isQualified;
     private Long qualificationId;
     private Boolean allowEnter;
+    private Boolean allowQuit;
     private Integer rankWeight;
     private Boolean addOnsEditable;
     private Integer memberLimit;

+ 19 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/CrowdScoreResponse.java

@@ -0,0 +1,19 @@
+package cn.iselab.mooctest.site.web.data;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.json.JSONArray;
+
+/**
+ * Created on 2019/5/24
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class CrowdScoreResponse {
+    private String name;
+    private String report_id;
+    private double score;
+    private String worker_id;
+}

+ 17 - 3
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/EclipseCaseVO.java

@@ -1,6 +1,8 @@
 package cn.iselab.mooctest.site.web.data;
 
+import com.alibaba.dubbo.common.json.JSON;
 import lombok.Data;
+import org.json.JSONObject;
 
 /**
  * Created by HenryLee on 2017/8/10.
@@ -15,14 +17,26 @@ public class EclipseCaseVO extends PluginCaseVO {
         this.CaseId = c.getId() + "";
         this.setName(c.getName());
         this.setAnswerWay(c.getAnswerWay());
+        this.setTargetId(c.getAppId());
+        this.setTargetName(c.getTargetName());
         Long subjectId = c.getSubjectId();
         String case_type = "";
-        if(subjectId == 51)
-            case_type = "Java Programming";
-        else if(subjectId == 60)
+        if(subjectId == 51) {
+            JSONObject jsonObject = new JSONObject(c.getProperties());
+            int testType = (int)jsonObject.get("testType");
+            if (testType == 6)
+                case_type = "Java Debug";
+            else if (testType == 8)
+                case_type = "Java Programming";
+        }
+        else if(subjectId == 60){
             case_type = "Junit Testing";
+        }
         else if(subjectId == 61)
             case_type = "Debug Testing";
+        else if (subjectId == 70)
+            case_type = "CPPUnit Testing";
         this.case_type = case_type;
+        System.out.println(case_type);
     }
 }

+ 0 - 12
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/GroupVO.java

@@ -20,18 +20,6 @@ public class GroupVO extends CaptchaBaseVO {
     private Boolean isActive;
     private Boolean isDeleted;
 
-    @Override
-    public String getCaptcha() {
-        return captcha;
-    }
-
-    @Override
-    public void setCaptcha(String captcha) {
-        this.captcha = captcha;
-    }
-
-    private String captcha;
-
     public Boolean getAllowJoin() {
         return allowJoin;
     }

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/KibugPluginCaseVO.java

@@ -22,5 +22,7 @@ public class KibugPluginCaseVO extends PluginCaseVO {
         this.setAnswerWay(caseExtends.getAnswerWay());
         this.setTaken(true);
         this.setProperties(caseExtends.getProperties());
+        this.setTargetId(caseExtends.getAppId());
+        this.setTargetName(caseExtends.getTargetName());
     }
 }

+ 22 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/OSSClientConfigVO.java

@@ -0,0 +1,22 @@
+package cn.iselab.mooctest.site.web.data;
+
+import lombok.Data;
+
+/**
+ * @program: mooctest-site
+ * @mail: menduo96@gmail.com
+ * @author: menduo
+ * @create: 2019-11-07 16:33
+ **/
+@Data
+public class OSSClientConfigVO {
+    private String endpoint;
+    private String accessKeyId; //sts授权后的
+    private String accessKeySecret; //sts授权后的
+    private String securityToken; //安全令牌
+    private String expiration;
+    private String bucket; // == oss.bucket.main
+    private long expireTime;
+    private String roleArn;
+    private String region;
+}

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/data/PluginCaseVO.java

@@ -10,4 +10,6 @@ public class PluginCaseVO {
     private Long id;
     private String name;
     private Long answerWay;
+    private Long targetId;
+    private String targetName;
 }

+ 3 - 2
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/CalculateSocreLogic.java

@@ -42,13 +42,14 @@ public interface CalculateSocreLogic {
                                                          Sort sort, CompeteAnalysisType competeAnalysisType);
 
     void recordNode(Long examId, Long caseId, Long userId, String uploadTime, String source,
-            List<CaughtNodeDTO> caughtNodeDTOs, String ossUrl) throws Exception;
+            List<CaughtNodeDTO> caughtNodeDTOs, String ossUrl, long applyUploadId) throws
+            Exception;
 
     void addNode(Long examId, Long caseId, Long userId, String uploadTime,
             List<CaughtNodeDTO> caughtNodeDTOs, long uploadId) throws Exception;
 
     void recordTypeScoreDirectly(long examId, long caseId, long userId, String uploadTime, String
-            ossUrl,String source, List<TypeScoreJson> typeScoreList);
+            ossUrl,String source, List<TypeScoreJson> typeScoreList, long applyUploadId);
 
     ResponseVO<ApplyUploadRecord> validateSubmit(long uploadId);
 }

+ 9 - 2
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/CompetitionLogic.java

@@ -6,6 +6,7 @@ import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  *
@@ -15,7 +16,9 @@ import java.util.List;
 public interface CompetitionLogic {
     List<CompetitionVO> getCompetitionList(Long userId);
 
-    Qualification enterCompetition(Long competitionId, Long userId);
+    Map<String, Object> enterCompetition(Long competitionId, Long userId);
+
+    void quitCompetition(Long competitionId, Long userId);
 
     List<AddonsVO> updateAddons(List<AddonsVO> addonsVOList, Long qualificationId, Integer type);
 
@@ -55,5 +58,9 @@ public interface CompetitionLogic {
 
     String updateAnnouncement(String announcement);
 
-    boolean checkAddons(List<AddonsVO> addonsVOList, Long qualificationId, Integer type);
+    Map<String, Object> checkAddons(List<AddonsVO> addonsVOList, Long qualificationId, Integer type);
+
+    List<UserVO> getSingleCompetitionStudents(long competitionId, long teacherId);
+
+    List<List<UserVO>> getTeamCompetitionStudents(long competitionId, long teacherId);
 }

+ 3 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/ExamLogic.java

@@ -4,6 +4,7 @@ import cn.iselab.mooctest.site.web.data.*;
 import cn.iselab.mooctest.site.web.exception.AssignedTaskNotExistException;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.util.List;
@@ -73,4 +74,6 @@ public interface ExamLogic {
 
     ExamVO deleteExamById(Long examId);
 
+    void uploadAnswerAnnex(Long userId, Long examId, Long caseId, MultipartFile file);
+
 }

+ 6 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/OSSLogic.java

@@ -1,5 +1,6 @@
 package cn.iselab.mooctest.site.web.logic;
 
+import cn.iselab.mooctest.site.web.data.OSSClientConfigVO;
 import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -7,6 +8,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author sean
@@ -32,6 +34,8 @@ public interface OSSLogic {
 
     AssumeRoleResponse assumeRole();
 
+    OSSClientConfigVO getSTSToken();
+
     String getSubmitSiganature(String path,Long examId,Long caseId,Long workerId,String fileName);
 
     boolean downloadByUrl(String url,String file,String fileName) throws Exception;
@@ -42,6 +46,8 @@ public interface OSSLogic {
 
     String uploadByUrl(String bucketName,String ossfilenameWithPath, InputStream inputStream);
 
+    String uploadByUrl(String ossfilenameWithPath, InputStream inputStream);
+
     boolean upload2DevBySigUrl(String signedUrl, File localFilePath);
 
     List<String> listObjectsByPrefix(String prefix);

+ 14 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/SpecialScoreLogic.java

@@ -0,0 +1,14 @@
+package cn.iselab.mooctest.site.web.logic;
+
+/**
+ * Created on 2019/5/28
+ */
+public interface SpecialScoreLogic {
+
+    /**
+     * 拉取众测分数
+     * @param examId examId
+     */
+    void pullCrowdScore(long examId);
+
+}

+ 5 - 18
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/fromDev/impl/UpDownloadLogicImpl.java

@@ -35,6 +35,8 @@ public class UpDownloadLogicImpl extends BaseLogic implements UpDownloadLogic {
     private TargetService targetService;
     @Autowired
     private GeneralCalculateScoreService generalCalculateScoreService;
+    @Autowired
+    private OSSClient ossClient;
 
     @Value("${oss.endPoint}")
     private String endPoint;
@@ -61,22 +63,16 @@ public class UpDownloadLogicImpl extends BaseLogic implements UpDownloadLogic {
         //生成OSS的路径
         String path= "target/" + fileName;
 
-        //打开OSS连接
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
-
         //生成签名5分钟过期
         Date expiration = new Date(System.currentTimeMillis() + 5 * 1000 * 60);
         GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, path, HttpMethod.GET);
         request.setExpiration(expiration);
-        URL signedUrl = client.generatePresignedUrl(request);
+        URL signedUrl = ossClient.generatePresignedUrl(request);
 
         LOG.info("signed url for getObject: " + signedUrl.toString());
 
         //TODO 将行为记录至数据库
 
-        //关闭OSS连接
-        client.shutdown();
-
         return signedUrl.toString();
     }
 
@@ -89,8 +85,6 @@ public class UpDownloadLogicImpl extends BaseLogic implements UpDownloadLogic {
         }
         String path = "data/records/" + taskID + "/" + workerID + "/" + caseName + "_" + System.currentTimeMillis() + ".zip";
 
-        //打开OSS连接
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
 
         //生成签名5分钟过期
         Date expiration = new Date(System.currentTimeMillis() + 5 * 1000 * 60);
@@ -99,13 +93,11 @@ public class UpDownloadLogicImpl extends BaseLogic implements UpDownloadLogic {
         request.setContentType("application/octet-stream");
         // 添加user meta
         request.addUserMetadata("author", "aliy");
-        URL signedUrl = client.generatePresignedUrl(request);
+        URL signedUrl = ossClient.generatePresignedUrl(request);
 
         LOG.info("signed url for putObject: " + signedUrl.toString());
         //TODO 将行为记录至数据库
 
-        //关闭OSS连接
-        client.shutdown();
         return signedUrl.toString();
     }
 
@@ -118,9 +110,6 @@ public class UpDownloadLogicImpl extends BaseLogic implements UpDownloadLogic {
         }
         String path = "data/answers/" + taskID + "/" + workerID + "/" + caseName + "_" + System.currentTimeMillis() + ".zip";
 
-        //打开OSS连接
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
-
         //生成签名
         Date expiration = new Date(System.currentTimeMillis() + 5 * 1000 * 60);//签名5分钟过期
         GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketNameDev, path, HttpMethod.PUT);
@@ -128,13 +117,11 @@ public class UpDownloadLogicImpl extends BaseLogic implements UpDownloadLogic {
         request.setContentType("application/octet-stream");
         // 添加user meta
         request.addUserMetadata("author", "aliy");
-        URL signedUrl = client.generatePresignedUrl(request);
+        URL signedUrl = ossClient.generatePresignedUrl(request);
 
         LOG.info("signed url for getObject: " + signedUrl.toString());
         //TODO 将行为记录至数据库
 
-        //关闭OSS连接
-        client.shutdown();
         return signedUrl.toString();
     }
 

+ 10 - 8
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/CalculateScoreLogicImpl.java

@@ -506,13 +506,13 @@ public class CalculateScoreLogicImpl extends BaseLogic implements CalculateSocre
 
     @Override
     public void recordNode(Long examId, Long caseId, Long userId, String uploadTime,
-                           String source, List<CaughtNodeDTO> caughtNodeDTOs, String ossUrl) throws
-            Exception {
+                           String source, List<CaughtNodeDTO> caughtNodeDTOs, String ossUrl, long
+            applyUploadId) throws Exception {
         //上传caughtNode
         recordNodeOnly(examId,caseId,userId,uploadTime,caughtNodeDTOs);
         //存储上传记录
         UploadRecordDTO uploadRecordDTO = saveUploadRecord(examId,caseId, userId, uploadTime,
-                ossUrl, source);
+                ossUrl, source, applyUploadId);
         //调用算分
         generalCalculateScoreComponent.saveCaughtDetails(uploadRecordDTO.getId(),examId, caseId,
                 userId, caughtNodeDTOs);
@@ -536,10 +536,11 @@ public class CalculateScoreLogicImpl extends BaseLogic implements CalculateSocre
 
     @Override
     public void recordTypeScoreDirectly(long examId, long caseId, long userId,
-            String uploadTime, String ossUrl, String source, List<TypeScoreJson> typeScoreList) {
+            String uploadTime, String ossUrl, String source, List<TypeScoreJson> typeScoreList,
+            long applyUploadId) {
         //存储上传记录
         UploadRecordDTO uploadRecordDTO = saveUploadRecord(examId,caseId, userId, uploadTime,
-                ossUrl, source);
+                ossUrl, source, applyUploadId);
 
         List<GeneralGradeDTO> generalGradeDTOList = typeScoreList.stream()
                 .map(typeScore -> new GeneralGradeDTO(typeScore.getType(),typeScore.getScore(),
@@ -567,16 +568,17 @@ public class CalculateScoreLogicImpl extends BaseLogic implements CalculateSocre
     }
 
     private UploadRecordDTO saveUploadRecord(long examId, long caseId, long userId,
-            String uploadTime, String ossUrl, String source){
+            String uploadTime, String ossUrl, String source, long applyUploadId){
         //存储上传记录
-        UploadRecordDTO uploadRecordDTO = generalCalculateScoreService.getUploadRecord(userId,
-                examId,caseId,uploadTime);
+        UploadRecordDTO uploadRecordDTO = generalCalculateScoreService.getUploadRecordByApplyId
+                (applyUploadId);
         if(uploadRecordDTO == null){
             uploadRecordDTO = new UploadRecordDTO();
             uploadRecordDTO.setExamId(examId);
             uploadRecordDTO.setCaseId(caseId);
             uploadRecordDTO.setWorkerId(userId);
             uploadRecordDTO.setUploadTime(uploadTime);
+            uploadRecordDTO.setApplyUploadId(applyUploadId);
         }
         uploadRecordDTO.setOSSUrl(ossUrl);
         uploadRecordDTO.setSource(source);

+ 52 - 33
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/CaseLogicImpl.java

@@ -17,20 +17,7 @@ import cn.iselab.mooctest.site.models.Role;
 import cn.iselab.mooctest.site.models.Target;
 import cn.iselab.mooctest.site.models.WeightGeneral;
 import cn.iselab.mooctest.site.models.fromKibug.Report;
-import cn.iselab.mooctest.site.service.AnswerWay2CaseBlockService;
-import cn.iselab.mooctest.site.service.CaseGraphService;
-import cn.iselab.mooctest.site.service.CaseService;
-import cn.iselab.mooctest.site.service.Exam2CaseService;
-import cn.iselab.mooctest.site.service.ExamPythonCommunityService;
-import cn.iselab.mooctest.site.service.ExamService;
-import cn.iselab.mooctest.site.service.PaperService;
-import cn.iselab.mooctest.site.service.RoleService;
-import cn.iselab.mooctest.site.service.SubmitRecordService;
-import cn.iselab.mooctest.site.service.TargetGraphService;
-import cn.iselab.mooctest.site.service.TargetService;
-import cn.iselab.mooctest.site.service.UserService;
-import cn.iselab.mooctest.site.service.VisitControlService;
-import cn.iselab.mooctest.site.service.WeightGeneralService;
+import cn.iselab.mooctest.site.service.*;
 import cn.iselab.mooctest.site.service.fromDev.IndexService;
 import cn.iselab.mooctest.site.service.fromKibug.ReportService;
 import cn.iselab.mooctest.site.service.instancePermission.CasePermissionService;
@@ -53,7 +40,10 @@ import cn.iselab.mooctest.site.web.logic.Oauth2Logic;
 import cn.iselab.mooctest.site.web.logic.fromDev.UpDownloadLogic;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Paths;
 import java.sql.Timestamp;
 import java.util.ArrayList;
@@ -68,6 +58,12 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.io.FileSystemResource;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.StringHttpMessageConverter;
 import org.springframework.stereotype.Service;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
@@ -114,6 +110,9 @@ public class CaseLogicImpl implements CaseLogic {
     private PaperService paperService;
 
     @Autowired
+    private AnswerAnnexService answerAnnexService;
+
+    @Autowired
     EventUtil eventUtil;
 
     @Autowired
@@ -153,6 +152,8 @@ public class CaseLogicImpl implements CaseLogic {
     @Autowired
     private OSSLogic ossLogic;
 
+    private String bucketName = "mooctest-site";
+
     @Value("${crowd.address}")
     private String crowdAddress;
 
@@ -166,6 +167,7 @@ public class CaseLogicImpl implements CaseLogic {
             }
             long caseid = caseBlock.getCaseIds().get(0);
             CaseExtendsVO caseExtendsVO = Converter.convert(CaseExtendsVO.class, caseService.getCaseExtendsById(caseid));
+            caseExtendsVO.setTargetName(targetService.getTargetByCaseId(caseid).getName());
             if (caseExtendsVO.getAppId() != null) {
                 Target target = targetService.findById(caseExtendsVO.getAppId());
                 if (target.getTargetType() == TargetTypeConstants.KIBUG) {
@@ -278,7 +280,11 @@ public class CaseLogicImpl implements CaseLogic {
 
         //保存到众测
         if(savedCase.getSubjectId() == 48){
-            save2crowd(savedCase);
+            Map<String, String> properties = new Gson().fromJson(savedCase.getProperties(), new
+                    TypeToken<HashMap<String, String>>(){}.getType());
+            if(properties.get("testType").equals("13")){
+                save2crowd(savedCase);
+            }
         }
 
         //进行完整性验证
@@ -304,7 +310,11 @@ public class CaseLogicImpl implements CaseLogic {
         //保存到众测
         if(savedCase.getSubjectId() == 48){
             try {
-                save2crowd(savedCase);
+                Map<String, String> properties = new Gson().fromJson(savedCase.getProperties(), new
+                        TypeToken<HashMap<String, String>>(){}.getType());
+                if(properties.get("testType").equals("13")){
+                    save2crowd(savedCase);
+                }
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -322,8 +332,20 @@ public class CaseLogicImpl implements CaseLogic {
         if(excelUrl != null){
             String category = targetService.getTargetProperty(savedCase.getAppId(),
                     "category").getPropertyValue();
-            save2crowdPlatform(excelUrl, "", category, savedCase.getDescription(), savedCase.getId()
-                    , savedCase.getName());
+            String paperType = properties.get("paperType");
+            if(paperType == null){
+                paperType = "{"
+                        + "\"title\":\"测试报告名称\","
+                        + "\"subTitles\":[{\"name\":\"设备名称\", \"type\":\"text\"},{\"name\":\"设备品牌\",\"type\":\"text\"},{\"name\":\"操作系统\",\"type\":\"enum\",\"value\":[\"windows\",\"linux\",\"macos\"]}],"
+                        + "\"caseList\":true,"
+                        + "\"bugList\": true,"
+                        + "\"testScript\":false,"
+                        + "\"suppleReport\":false,"
+                        + "\"testLog\":false"
+                        + "}";
+            }
+            save2crowdPlatform(excelUrl, paperType, category, savedCase.getDescription(),
+                    savedCase.getId(), savedCase.getName());
         }else{
             throw new ServerException(60000, "未上传excel文件!");
         }
@@ -341,19 +363,9 @@ public class CaseLogicImpl implements CaseLogic {
      */
     private void save2crowdPlatform(String fileUrl, String paper_type, String test_type, String
             description, long caseId, String caseName) throws Exception {
-        String tmpPath = System.getProperty("java.io.tmpdir");
-        String crowdSavePath = Constants.CROWD_SAVE_PATH;
-        String tmpCrowdDir = Paths.get(tmpPath, crowdSavePath).toString();
         String filename = fileUrl.split("/")[fileUrl.split("/").length-1];
-        boolean success = ossLogic.downloadByUrl(fileUrl,tmpCrowdDir, filename);
-        if(!success){
-            throw new ServerException(60000, "保存到众测时,从oss下载文件失败");
-        }
-
-        FileSystemResource excelFile = new FileSystemResource(new File(Paths.get
-                (tmpCrowdDir, filename).toString()));
-        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
-        params.add("file", excelFile);
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("file", fileUrl);
         params.add("file_name", filename);
         params.add("paper_type", paper_type);
         params.add("case_id", caseId+"");
@@ -362,9 +374,13 @@ public class CaseLogicImpl implements CaseLogic {
         params.add("app_name", caseName);
 
         RestTemplate restTemplate = new RestTemplate();
-        String resultStatus = restTemplate.postForObject
-                (crowdAddress+"/Bug/api/extra/uploadExam", params, String.class);
-        if(!resultStatus.equals("200")){
+        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+        ResponseEntity<String> responseEntity = restTemplate.postForEntity
+                (crowdAddress+"/Bug/api/extra/uploadExamUrl", params, String.class);
+        if(responseEntity.getStatusCode().equals(HttpStatus.OK)){
+            InputStream jsonInputStream = new ByteArrayInputStream(responseEntity.getBody().getBytes());
+            ossLogic.uploadByUrl(bucketName, "json/"+caseId+".json", jsonInputStream);
+        }else{
             throw new ServerException(60000, "保存到众测接口失败");
         }
 
@@ -482,6 +498,9 @@ public class CaseLogicImpl implements CaseLogic {
                     caseExtendsVO.setCaseReportUrl("/report/judgeGrade/" + examId + "/" + caseid);
                 }
             }
+            if (showTags.size() > 7 && showTags.get(CaseBlockConstants.UPLOAD_FILE)==1){
+                    caseExtendsVO.setAnnexList(answerAnnexService.getUrls(userId, examId, caseid));
+            }
             if(isWorker==true){
                 caseExtendsVO.setSubmitted(submitRecordService.isSubmitted(examId, userId, caseExtendsVO.getId(), caseExtendsVO.getCaseId()));
             }

+ 41 - 4
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/CompetitionLogicImpl.java

@@ -3,6 +3,7 @@ package cn.iselab.mooctest.site.web.logic.impl;
 import cn.iselab.mooctest.site.common.event.AddTask2CompetitionEvent;
 import cn.iselab.mooctest.site.common.event.EnterCompetitionEvent;
 import cn.iselab.mooctest.site.common.event.EventUtil;
+import cn.iselab.mooctest.site.common.event.QuitCompetitionEvent;
 import cn.iselab.mooctest.site.dao.ConfigDao;
 import cn.iselab.mooctest.site.dao.ContestMentorSubmitRecordDao;
 import cn.iselab.mooctest.site.models.*;
@@ -23,6 +24,7 @@ import org.springframework.stereotype.Service;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -64,9 +66,13 @@ public class CompetitionLogicImpl implements CompetitionLogic {
     }
 
     @Override
-    public Qualification enterCompetition(Long competitionId, Long userId) {
+    public Map<String, Object> enterCompetition(Long competitionId, Long userId) {
         Competition competition = competitionService.getCompetiton(competitionId);
         Qualification qualification = competitionService.getQualification(competitionId, userId);
+        Map<String, Object> res = competitionService.checkEnterCompetition(competitionId, userId);
+        if (res == null || !res.get("code").equals(0)){
+            return res;
+        }
         if (qualification == null) {
             qualification = new Qualification();
             qualification.setCompetitionId(competitionId);
@@ -75,14 +81,35 @@ public class CompetitionLogicImpl implements CompetitionLogic {
         qualification.setStatus(competition.getStatus());
         Qualification savedQualification = competitionService.createOrUpdateQualification(qualification);
         eventUtil.post(new EnterCompetitionEvent(userId,competitionId));
-        return savedQualification;
+        //return savedQualification;
+        res.put("code",0);
+        res.put("data",savedQualification);
+        res.put("message","报名成功");
+        return res;
     }
 
     @Override
+    public void quitCompetition(Long competitionId, Long userId) {
+        System.out.println("userId: " + userId + ", competitionId: " + competitionId);
+        Competition competition = competitionService.getCompetiton(competitionId);
+        Qualification qualification = competitionService.getQualification(competitionId, userId);
+        if (!competition.getAllowQuit())
+            throw new HttpBadRequestException("该比赛不可退出");
+        if (qualification == null)
+            throw new HttpBadRequestException("未参加比赛,不可退出");
+        List<AddOns2Qualification> addons2Qualification = competitionService.getAddons2Qualification(qualification.getId());
+        if (addons2Qualification.size()>0)
+            throw new HttpBadRequestException("请删除所有队友和指导教师");
+        competitionService.deleteQualification(qualification.getId());
+        eventUtil.post(new QuitCompetitionEvent(userId, competitionId));
+    }
+
+
+    @Override
     public List<AddonsVO> updateAddons(List<AddonsVO> addonsVOList, Long qualificationId, Integer type) {
         List<AddOns2Qualification> addOns2Qualifications = addonsVOWrapper.unwrap(addonsVOList);
         List<AddOns2Qualification> addons = competitionService.updateAddons(addOns2Qualifications, qualificationId, type);
-        
+
         return addonsVOWrapper.wrap(addons);
     }
 
@@ -272,8 +299,18 @@ public class CompetitionLogicImpl implements CompetitionLogic {
     }
 
     @Override
-    public boolean checkAddons(List<AddonsVO> addonsVOList, Long qualificationId, Integer type) {
+    public Map<String, Object> checkAddons(List<AddonsVO> addonsVOList, Long qualificationId, Integer type) {
         return competitionService.checkAddons(addonsVOList,qualificationId,type);
     }
 
+    @Override
+    public List<UserVO> getSingleCompetitionStudents(long competitionId, long teacherId) {
+        return competitionService.getSingleCompetitionStudents(competitionId, teacherId);
+    }
+
+    @Override
+    public List<List<UserVO>> getTeamCompetitionStudents(long competitionId, long teacherId) {
+        return competitionService.getTeamCompetitionStudents(competitionId, teacherId);
+    }
+
 }

+ 21 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/ExamLogicImpl.java

@@ -14,6 +14,7 @@ import cn.iselab.mooctest.site.web.data.*;
 import cn.iselab.mooctest.site.web.data.wrapper.*;
 import cn.iselab.mooctest.site.web.exception.AssignedTaskNotExistException;
 import cn.iselab.mooctest.site.web.exception.HttpBadRequestException;
+import cn.iselab.mooctest.site.web.exception.HttpInternalServerError;
 import cn.iselab.mooctest.site.web.exception.HttpNotFoundException;
 import cn.iselab.mooctest.site.web.logic.*;
 import cn.iselab.mooctest.site.common.enums.EntityTypeEnum;
@@ -27,6 +28,7 @@ import org.springframework.core.convert.converter.Converter;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -108,6 +110,9 @@ public class ExamLogicImpl extends BaseLogic implements ExamLogic {
     @Autowired
     UserStarCaseService userStarCaseService;
 
+    @Autowired
+    AnswerAnnexService answerAnnexService;
+
     @Override
     public ExamVO getExamById(long examId) {
         Exam exam = examService.getTask(examId);
@@ -468,6 +473,22 @@ public class ExamLogicImpl extends BaseLogic implements ExamLogic {
         return examVOWrapper.wrap(examService.deleteExamById(examId));
     }
 
+    @Override
+    public void uploadAnswerAnnex(Long userId, Long examId, Long caseId, MultipartFile file) {
+        String pathName = "answerAnnex/"+examId+"/"+caseId+"/"+userId+"/"
+                + file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."))+"_"
+                +System.currentTimeMillis()+""+file.getOriginalFilename()
+                .substring(file.getOriginalFilename().lastIndexOf("."), file.getOriginalFilename().length());
+        try {
+            String url = ossLogic.uploadByUrl(pathName, file.getInputStream());
+            LOG.info("url: "+url);
+            answerAnnexService.recordUpload(examId, caseId, userId, url);
+        } catch (IOException e) {
+            LOG.info("上传出错!",e);
+            throw new HttpInternalServerError("后台上传出错,请稍后再试");
+        }
+    }
+
 
     @Override
     public void exportExcelByOwner(HttpServletResponse response, Long examId) throws Exception {

+ 72 - 39
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/OSSLogicImpl.java

@@ -5,11 +5,16 @@ import cn.iselab.mooctest.site.data.ExamPDF;
 import cn.iselab.mooctest.site.data.ReportPDF;
 import cn.iselab.mooctest.site.data.UserDTOForMT;
 import cn.iselab.mooctest.site.data.config.OSSClientConfig;
+import cn.iselab.mooctest.site.data.config.STSConfig;
 import cn.iselab.mooctest.site.models.Exam;
 import cn.iselab.mooctest.site.models.User;
-import cn.iselab.mooctest.site.service.*;
+import cn.iselab.mooctest.site.service.EmailService;
+import cn.iselab.mooctest.site.service.ExamService;
+import cn.iselab.mooctest.site.service.GroupService;
+import cn.iselab.mooctest.site.service.UserService;
 import cn.iselab.mooctest.site.service.common.PdfService;
 import cn.iselab.mooctest.site.service.common.ZipService;
+import cn.iselab.mooctest.site.web.data.OSSClientConfigVO;
 import cn.iselab.mooctest.site.web.exception.HttpBadRequestException;
 import cn.iselab.mooctest.site.web.logic.OSSLogic;
 import com.aliyun.oss.HttpMethod;
@@ -19,8 +24,12 @@ import com.aliyuncs.DefaultAcsClient;
 import com.aliyuncs.exceptions.ClientException;
 import com.aliyuncs.http.MethodType;
 import com.aliyuncs.http.ProtocolType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
 import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
 import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
+import com.google.common.collect.Maps;
+import lombok.extern.slf4j.Slf4j;
 import net.lingala.zip4j.core.ZipFile;
 import net.lingala.zip4j.model.ZipParameters;
 import net.lingala.zip4j.util.Zip4jConstants;
@@ -32,7 +41,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.*;
-import java.net.InetAddress;
 import java.net.URL;
 import java.util.Date;
 import java.util.HashMap;
@@ -45,6 +53,7 @@ import java.util.stream.Collectors;
  * @date 2017-03-27.
  */
 @Service
+@Slf4j
 public class OSSLogicImpl implements OSSLogic {
 
     @Autowired
@@ -52,6 +61,8 @@ public class OSSLogicImpl implements OSSLogic {
 
     @Autowired
     private OSSClientConfig ossClientConfig;
+    @Autowired
+    private STSConfig stsConfig;
 
     @Autowired
     private DefaultAcsClient acsClient;
@@ -112,8 +123,6 @@ public class OSSLogicImpl implements OSSLogic {
 
     @Override
     public boolean verificationCertificate(String userId) {
-        //打开OSS连接
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
         return ossClient.doesObjectExist(bucketName, getCertificateKey(userId));
     }
 
@@ -134,8 +143,7 @@ public class OSSLogicImpl implements OSSLogic {
 
     @Override
     public String verificationHeadImageKey(String userId) {
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
-        if (client.doesObjectExist(bucketName, getHeadImageKey(userId))) {
+        if (ossClient.doesObjectExist(bucketName, getHeadImageKey(userId))) {
             return getHeadImageKey(userId);
         }
         String fail = "未上传照片";
@@ -175,15 +183,45 @@ public class OSSLogicImpl implements OSSLogic {
     }
 
     @Override
+    public OSSClientConfigVO getSTSToken() {
+        String endpoint = stsConfig.getEndpoint();
+        String accessKeyId = stsConfig.getAccessKeyId();
+        String accessKeySecret = stsConfig.getAccessKeySecret();
+        String roleArn = stsConfig.getRoleArn();
+        String roleSessionName = stsConfig.getRoleSessionName();
+        String policy = stsConfig.getPolicy();
+        OSSClientConfigVO ossClientConfigVO = new OSSClientConfigVO();
+        try {
+            // 添加endpoint(直接使用STS endpoint,前两个参数留空,无需添加region ID)
+            DefaultProfile.addEndpoint("", "", "Sts", endpoint);
+            // 构造default profile(参数留空,无需添加region ID)
+            IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
+            // 用profile构造client
+            DefaultAcsClient client = new DefaultAcsClient(profile);
+            final AssumeRoleRequest request = new AssumeRoleRequest();
+            request.setMethod(MethodType.POST);
+            request.setRoleArn(roleArn);
+            request.setRoleSessionName(roleSessionName);
+            request.setPolicy(policy); // 若policy为空,则用户将获得该角色下所有权限
+            request.setDurationSeconds(1000L); // 设置凭证有效时间
+            final AssumeRoleResponse response = client.getAcsResponse(request);
+            ossClientConfigVO.setAccessKeyId(response.getCredentials().getAccessKeyId());
+            ossClientConfigVO.setAccessKeySecret(response.getCredentials().getAccessKeySecret());
+            ossClientConfigVO.setExpiration(response.getCredentials().getExpiration());
+            ossClientConfigVO.setSecurityToken(response.getCredentials().getSecurityToken());
+        } catch (ClientException e) {
+            log.error("获取STS权限失败",e);
+        }
+        return ossClientConfigVO;
+    }
+
+    @Override
     public String getSubmitSiganature(String path, Long examId, Long caseId, Long workerId, String fileName) {
         if (examId == null || caseId == null || workerId == null) {
             return null;
         }
         String url = path + "/" + examId + "/" + caseId + "/" + workerId + "/" + System.currentTimeMillis() + "_" + fileName;
 
-        //打开OSS连接
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
-
         //生成签名
         Date expiration = new Date(System.currentTimeMillis() + 5 * 1000 * 60);//签名5分钟过期
         GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketNameDev, url, HttpMethod.PUT);
@@ -191,10 +229,8 @@ public class OSSLogicImpl implements OSSLogic {
         request.setContentType("application/octet-stream");
         // 添加user meta
         request.addUserMetadata("author", "aliy");
-        URL signedUrl = client.generatePresignedUrl(request);
+        URL signedUrl = ossClient.generatePresignedUrl(request);
 
-        //关闭OSS连接
-        client.shutdown();
         return signedUrl.toString();
     }
 
@@ -208,8 +244,6 @@ public class OSSLogicImpl implements OSSLogic {
         }
         String downloadPath = FilenameUtils.concat(filePath, fileName);
 
-//        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
-//        OSSObject ossObj = client.getObject(bucketName, url);
         URL url1 = new URL(url);
         try {
             File file = new File(downloadPath);
@@ -223,7 +257,7 @@ public class OSSLogicImpl implements OSSLogic {
 
     @Override
     public String downloadContentByUrlToString(String url) throws IOException {
-        OSSClient ossClient = new OSSClient(endPoint,accessKeyId,accessKeySecret);
+
         OSSObject ossObject = ossClient.getObject(bucketName,url);
         BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
         StringBuilder sb = new StringBuilder();
@@ -234,7 +268,6 @@ public class OSSLogicImpl implements OSSLogic {
         }
 
         reader.close();
-        ossClient.shutdown();
         return sb.toString();
     }
 
@@ -259,7 +292,6 @@ public class OSSLogicImpl implements OSSLogic {
                 System.out.println("编程社区代码上传出错");
                 e.printStackTrace();
             }
-            System.out.println("url: "+host+UPLOADED_PATH+ossfilenameWithPath);
             return host+UPLOADED_PATH+ossfilenameWithPath;
 
         }
@@ -276,15 +308,19 @@ public class OSSLogicImpl implements OSSLogic {
      */
     @Override
     public String uploadByUrl(String bucketName, String ossfilenameWithPath, InputStream inputStream) {
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
-        PutObjectResult result = client.putObject(bucketName, ossfilenameWithPath , inputStream);
-        client.shutdown();
+        PutObjectResult result = ossClient.putObject(bucketName, ossfilenameWithPath , inputStream);
+
         StringBuilder sb = new StringBuilder("http://");
         String nohttpEndPoint = endPoint.replace("http://","");
         sb.append(bucketName).append(".").append(nohttpEndPoint).append("/").append(ossfilenameWithPath);
         return sb.toString();
     }
 
+    @Override
+    public String uploadByUrl(String ossfilenameWithPath, InputStream inputStream) {
+        return uploadByUrl(bucketName, ossfilenameWithPath, inputStream);
+    }
+
     /**
      * 根据签名上传文件
      * @param signedUrl oss上传许可签名
@@ -294,16 +330,12 @@ public class OSSLogicImpl implements OSSLogic {
     @Override
     public boolean upload2DevBySigUrl(String signedUrl, File localFilePath) {
         // 使用签名URL发送请求。
-        OSSClient client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
         try(FileInputStream fin = new FileInputStream(localFilePath)) {
             // 添加PutObject请求头。
             Map<String, String> customHeaders = new HashMap<String, String>();
             customHeaders.put("Content-Type", "application/octet-stream");
             customHeaders.put("x-oss-meta-author", "aliy");
-
-            PutObjectResult result = client.putObject(new URL(signedUrl), fin, localFilePath.length(), customHeaders);
-            // 关闭OSSClient。
-            client.shutdown();
+            PutObjectResult result = ossClient.putObject(new URL(signedUrl), fin, localFilePath.length(), customHeaders);
             return true;
         } catch (IOException e) {
             e.printStackTrace();
@@ -315,9 +347,7 @@ public class OSSLogicImpl implements OSSLogic {
 
     @Override
     public List<String> listObjectsByPrefix(String prefix) {
-        OSSClient client = new OSSClient(endPoint,accessKeyId,accessKeySecret);
-        ObjectListing objectListing = client.listObjects(bucketName,prefix);
-        client.shutdown();
+        ObjectListing objectListing = ossClient.listObjects(bucketName,prefix);
         List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
         return sums.stream().map(OSSObjectSummary::getKey).collect(Collectors.toList());
     }
@@ -333,8 +363,8 @@ public class OSSLogicImpl implements OSSLogic {
         }
         String fileName = UPLOADED_PATH + path;
         File saveFile = new File("/var/www" + fileName);
+
         //判断文件父目录是否存在
-        System.out.println(saveFile.getParentFile());
         if (!saveFile.getParentFile().exists()) {
             saveFile.getParentFile().mkdirs();
         }
@@ -344,21 +374,20 @@ public class OSSLogicImpl implements OSSLogic {
 
     @Override
     public String saveFileTemp(MultipartFile file, String filePath) throws IOException {
-        Long size = file.getSize ();
-        if (file.isEmpty ()) {
+        Long size = file.getSize();
+        if (file.isEmpty()) {
             throw new HttpBadRequestException ("please select a file to upload");
         }
         if (size > maxUploadSizeInMb) {
             throw new HttpBadRequestException ("file size is over limit");
         }
 
-        File saveFile = new File (filePath);
+        File saveFile = new File(filePath);
         //判断文件父目录是否存在
-        System.out.println (saveFile.getParentFile ());
-        if (!saveFile.getParentFile ().exists ()) {
-            saveFile.getParentFile ().mkdirs ();
+        if (!saveFile.getParentFile().exists()) {
+            saveFile.getParentFile().mkdirs();
         }
-        file.transferTo (saveFile);
+        file.transferTo(saveFile);
         return filePath;
     }
 
@@ -380,9 +409,10 @@ public class OSSLogicImpl implements OSSLogic {
         File file = new File(SAVE_PATH + ZIP_PATH + fileName + ".zip");
         if (!file.exists()) {
             File folder = new File(FileUtils.getUserDirectory() + "/" + fileName);
-            if (!folder.exists())
+            if (!folder.exists()) {
                 folder.mkdirs();
-            ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
+            }
+
             ObjectListing listing = ossClient.listObjects(bucketNameDev, "data/answers" + "/" + examId + "/" + workerId + "/");
             List<OSSObjectSummary> sums = listing.getObjectSummaries();
             for (OSSObjectSummary s : sums) {
@@ -390,7 +420,7 @@ public class OSSLogicImpl implements OSSLogic {
                 String name = key.split("/")[key.split("/").length - 1];
                 ossClient.getObject(new GetObjectRequest(bucketNameDev, key), new File(FileUtils.getUserDirectory() + "/" + fileName + "/" + name));
             }
-            ossClient.shutdown();
+
             zipService.zipForReport(examId, workerId, FileUtils.getUserDirectory() + "/" + fileName);
             ZipFile zipFile = new ZipFile(file);
             ZipParameters parameters = new ZipParameters();
@@ -527,9 +557,12 @@ public class OSSLogicImpl implements OSSLogic {
         return null;
     }
 
+
+
     private String getStatisticalDiagramKey(String s) {
         return null;
     }
 
 
+
 }

+ 65 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/SpecialScoreLogicImpl.java

@@ -0,0 +1,65 @@
+package cn.iselab.mooctest.site.web.logic.impl;
+
+import cn.iselab.mooctest.site.service.CaseService;
+import cn.iselab.mooctest.site.service.Exam2CaseService;
+import cn.iselab.mooctest.site.web.data.CrowdScoreResponse;
+import cn.iselab.mooctest.site.web.exception.ServerException;
+import cn.iselab.mooctest.site.web.logic.SpecialScoreLogic;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Resource;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Created on 2019/5/28
+ */
+@Service
+public class SpecialScoreLogicImpl implements SpecialScoreLogic {
+
+    @Resource
+    private Exam2CaseService exam2CaseService;
+    @Resource
+    private CaseService caseService;
+    @Resource
+    private GeneralCalculateScoreComponent generalCalculateScoreComponent;
+    @Value("${crowd.address}")
+    private String crowdAddress;
+
+    @Override
+    public void pullCrowdScore(long examId) {
+        List<Long> caseIds = exam2CaseService.getCaseIdsByExamId(examId);
+        caseIds.forEach(cid -> {
+            Map<String, String> properties = caseService.getCaseProperties(cid);
+            String testType = properties.get("testType");
+            if(testType!=null && testType.equals("13")){ //手工测试-推荐
+                List<CrowdScoreResponse> scoreList = pullScoreFromPlatform(examId, cid);
+                scoreList.forEach(crowdScore -> generalCalculateScoreComponent.saveGrade
+                        (Long.parseLong(crowdScore.getWorker_id()),examId, cid, crowdScore.getScore()));
+            }
+        });
+    }
+
+    private List<CrowdScoreResponse> pullScoreFromPlatform(long examId, long caseId){
+        Map<String, String> params = new HashMap<>();
+        params.put("caseTakeId", caseId+"-"+examId);
+        RestTemplate restTemplate = new RestTemplate();
+        String url = crowdAddress+"/Bug/api/analyze/newScores?case_take_id={caseTakeId}";
+        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url,
+                String.class, params);
+        if(!responseEntity.getStatusCode().equals(HttpStatus.OK)){
+            throw new ServerException(60000, "case "+caseId+" 分数拉取失败");
+        }else{
+            List<CrowdScoreResponse> responseList = new Gson().fromJson(responseEntity.getBody(), new
+                    TypeToken<List<CrowdScoreResponse>>(){}.getType());
+            return responseList;
+        }
+
+    }
+}

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/TargetLogicImpl.java

@@ -518,6 +518,8 @@ public class TargetLogicImpl extends BaseLogic implements TargetLogic {
                     mcNodeProgressLogic.trigegrTargetAnalysis(appId, targetCreateVO.getUrl());
                 } else if (DevLanguageConstants.PYTHON.equals(language)) {
                     pythonNodeProgressLogic.triggerTargetAnalysis(appId, targetCreateVO.getUrl());
+                } else if (DevLanguageConstants.CPP.equals(language)) {
+                    //TODO: CPP Unit Test
                 }
             }
         }

+ 1 - 3
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/UserLogicImpl.java

@@ -723,7 +723,7 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
         List<UserDTOForMT> checkedTeachers = new ArrayList<>();
         for (Long id : teacherIds) {
             UserDTOForMT user = userService.findByUserId(id);
-            if (user.getManualCheckValid()!=null && user.getManualCheckValid().equals(Boolean.TRUE)) {
+            if (user != null && user.getManualCheckValid()!=null && user.getManualCheckValid().equals(Boolean.TRUE)) {
                 checkedTeachers.add(user);
             }
         }
@@ -768,8 +768,6 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
             if (integralDTO!=null) {
                 userVO.setIntegral(integralDTO.getTotal());
             }
-        }else {
-            LOG.info("私有云不进行积分初始化");
         }
 
         if (managerPropertyService.getManagerPropertyByUserId(userVO.getId()) != null) {

+ 2 - 1
mooctest-site-server/src/main/resources/log4j2.online.yaml

@@ -6,7 +6,8 @@ Configuration:
       - name: filename
         value: mooctest-site.log
       - name: pattern
-        value: "%d{yyyy-MM-dd HH:mm:ss} [%p] [%t] [%c] %m%n"
+        value: "%d{yyyy-MM-dd HH:mm:ss} [%X{X-B3-TraceId},%X{X-B3-SpanId},%X{X-B3-ParentSpanId},%X{X-Span-Export}] 
+        [%p] [%t] [%c] %m%n"
       - name: httpRequestPattern
         value: "%-d{yyyy-MM-dd HH:mm:ss} %m%n"
 

+ 2 - 1
mooctest-site-server/src/main/resources/log4j2.test.yaml

@@ -6,7 +6,8 @@ Configuration:
       - name: filename
         value: mooctest-site.log
       - name: pattern
-        value: "%d{yyyy-MM-dd HH:mm:ss} [%p] [%t] [%c] %m%n"
+        value: "%d{yyyy-MM-dd HH:mm:ss} [%X{X-B3-TraceId},%X{X-B3-SpanId},%X{X-B3-ParentSpanId},%X{X-Span-Export}]
+        [%p] [%t] [%c] %m%n"
       - name: httpRequestPattern
         value: "%-d{yyyy-MM-dd HH:mm:ss} %m%n"
 

+ 1 - 1
mooctest-site-server/src/main/resources/log4j2.yaml

@@ -5,7 +5,7 @@ Configuration:
       name: console
       target: SYSTEM_OUT
       PatternLayout:
-        pattern: "%d{yyyy-MM-dd HH:mm:ss} [%p] [%t] [%c] %m%n"
+        pattern: "%d{yyyy-MM-dd HH:mm:ss} [%X{X-B3-TraceId},%X{X-B3-SpanId},%X{X-B3-ParentSpanId},%X{X-Span-Export}] [%p] [%t] [%c] %m%n"
   Loggers:
     AsyncRoot:
       level: info

+ 6 - 1
mooctest-site-server/src/test/java/cn/iselab/mooctest/site/service/impl/CaseServiceImplTest.java

@@ -30,6 +30,9 @@ public class CaseServiceImplTest {
     @Mock
     private CaseExtendsDao caseExtendsDao;
 
+    @Mock
+    private CaseExtendsDao caseDao;
+
     private CaseExtends caseExtends;
     private List<CaseExtends> caseExtendsList = new ArrayList<>();
     private Page<CaseExtends> caseExtendsPage;
@@ -41,6 +44,7 @@ public class CaseServiceImplTest {
 
         caseExtends = new CaseExtends();
         caseExtends.setId(1L);
+
         caseExtendsList.add(caseExtends);
         caseExtendsPage = new PageImpl<>(caseExtendsList);
 
@@ -51,6 +55,7 @@ public class CaseServiceImplTest {
     public void should_returnCaseExtends_when_givenCaseId(){
         //arrange
         when(caseExtendsDao.findOne(1L)).thenReturn(caseExtends);
+        when(caseDao.findOne(1L)).thenReturn(caseExtends);
         //action
         CaseExtends result1 = caseService.getCaseById(1L);
         CaseExtends result2 = caseService.getCaseExtendsById(1L);
@@ -84,7 +89,7 @@ public class CaseServiceImplTest {
     @Test
     public void should_returnCaseExtendsPage_when_givenTargetId(){
         //arrange
-        when(caseExtendsDao.findAll(any(),any(Pageable.class))).thenReturn(caseExtendsPage);
+        when(caseDao.findAll(any(),any(Pageable.class))).thenReturn(caseExtendsPage);
         //action
         Page<CaseExtends> result = caseService.getCasesByTargetId(1L,"",pageable);
         //assert

+ 2 - 0
mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/CaseLogicImplTest.java

@@ -166,9 +166,11 @@ public class CaseLogicImplTest {
         Target target = new Target();
         target.setTargetType((long)TargetTypeConstants.KIBUG);
         target.setUrl("url");
+        target.setName("TEST");
         when(examService.getCaseBlocks(1L)).thenReturn(caseBlocks);
         when(caseService.getCaseExtendsById(11L)).thenReturn(caseExtends);
         when(targetService.findById(123L)).thenReturn(target);
+        when(targetService.getTargetByCaseId(anyInt())).thenReturn(target);
         //action
         List<CaseExtendsVO> result = caseLogic.getCasesByTaskId(1L);
         //assert

+ 7 - 5
mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/CompetitionLogicImplTest.java

@@ -14,6 +14,7 @@ import cn.iselab.mooctest.site.web.data.wrapper.CompetitionVOWrapper;
 import cn.iselab.mooctest.site.web.data.wrapper.QualificationVOWrapper;
 import cn.iselab.mooctest.site.web.exception.HttpBadRequestException;
 import cn.iselab.mooctest.site.web.logic.ExamLogic;
+import cn.iselab.mooctest.site.web.logic.Oauth2Logic;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -29,9 +30,7 @@ import org.springframework.data.domain.PageImpl;
 import org.springframework.data.geo.GeoPage;
 import org.springframework.test.context.web.WebAppConfiguration;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+import java.util.*;
 
 import static org.junit.Assert.*;
 import static org.mockito.Matchers.*;
@@ -170,11 +169,14 @@ public class CompetitionLogicImplTest {
 
     @Test
     public void should_returnQualification_when_enterCometitionWithCIdUserId(){
+        Map<String, Object> map = new HashMap<>();
+        map.put("code", 0);
         when(competitionService.getCompetiton(30L)).thenReturn(competition);
         when(competitionService.getQualification(30L,1L)).thenReturn(null);
         when(competitionService.createOrUpdateQualification(any())).thenReturn(qualification);
-        Qualification result = competitionLogic.enterCompetition(30L, 1L);
-        Assert.assertEquals(30L, result.getCompetitionId(), 0);
+        when(competitionService.checkEnterCompetition(anyLong(), anyLong())).thenReturn(map);
+        Map<String,Object> result = competitionLogic.enterCompetition(30L, 1L);
+        Assert.assertEquals(30L, ((Qualification)result.get("data")).getCompetitionId(), 0);
     }
 
     @Test

+ 1 - 1
mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/GeneralCalculateScoreComponentTest.java

@@ -158,7 +158,7 @@ public class GeneralCalculateScoreComponentTest {
                         "5b2fc1dcd7fa0b6acb62816"), "5b2fdac0d7fa0b6acb628193");
         userCatchDTOList.add(userCatchDTO);
 
-        uploadRecordDTO = new UploadRecordDTO(1L,1105L,1804L,824L,"xxx","xx","1234567");
+        uploadRecordDTO = new UploadRecordDTO(1L,1105L,1804L,824L,"xxx","xx","1234567",1L);
 
 
 //    UserCatchDTO userCatchDTO = new UserCatchDTO("1",1L,1L,1L,Arrays.asList(catchDTO1,

+ 96 - 0
mooctest-site-server/src/test/java/cn/iselab/mooctest/site/web/logic/impl/VerficationLogicImplTest.java

@@ -0,0 +1,96 @@
+package cn.iselab.mooctest.site.web.logic.impl;
+
+import cn.iselab.mooctest.site.models.MobileVerification;
+import cn.iselab.mooctest.site.service.EmailService;
+import cn.iselab.mooctest.site.service.MobileVerificationService;
+import cn.iselab.mooctest.site.util.sms.SMSUtil;
+import cn.iselab.mooctest.site.web.exception.HttpBadRequestException;
+import cn.iselab.mooctest.site.web.exception.HttpServiceUnavailableException;
+import cn.iselab.mooctest.site.web.logic.VerificationLogic;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+/**
+ * @program: mooctest-site
+ * @mail: menduo96@gmail.com
+ * @author: menduo
+ * @create: 2019-11-08 15:56
+ **/
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(SMSUtil.class)
+@PowerMockIgnore({"javax.management.*"})
+@WebAppConfiguration
+@SpringApplicationConfiguration(classes = cn.iselab.mooctest.site.Application.class)
+public class VerficationLogicImplTest {
+    @InjectMocks
+    private VerficationLogicImpl verficationLogic = new VerficationLogicImpl();
+    @Mock
+    private MobileVerificationService mobileVerificationService;
+    @Mock
+    private EmailService emailService;
+    private MobileVerification mobileVerification;
+
+    @Before
+    public void before() {
+        mobileVerification = new MobileVerification();
+        mobileVerification.setId(111L);
+        mobileVerification.setCode("menduosb");
+        mobileVerification.setMobile("17666666666");
+
+    }
+
+    @Test(expected = HttpBadRequestException.class)
+    public void sendMobileVerfication_when_send_is_too_quick() {
+        when(mobileVerificationService.getLatestVerification("17666666666")).thenReturn(mobileVerification);
+        mobileVerification.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
+        verficationLogic.sendMobileVerfication("17666666666");
+
+    }
+
+    @Test
+    public void sendMobileVerfication_success() {
+        when(mobileVerificationService.getLatestVerification("17666666666")).thenReturn(mobileVerification);
+        PowerMockito.mockStatic(SMSUtil.class);
+        PowerMockito.when(SMSUtil.generateRandomVeriCode()).thenReturn("1111");
+        String successCode = "000000";
+        PowerMockito.when(SMSUtil.sendSmsVerification("17666666666","1111")).thenReturn(successCode);
+        when(mobileVerificationService.saveVerfication(any())).thenReturn(any());
+        mobileVerification.setCreateTime(Timestamp.valueOf(LocalDateTime.of(2018,1,1,1,1)));
+        verficationLogic.sendMobileVerfication("17666666666");
+
+
+    }
+
+    @Test(expected = HttpServiceUnavailableException.class)
+    public void sendMobileVerfication_false() {
+        when(mobileVerificationService.getLatestVerification("17666666666")).thenReturn(mobileVerification);
+        PowerMockito.mockStatic(SMSUtil.class);
+        PowerMockito.when(SMSUtil.generateRandomVeriCode()).thenReturn("1111");
+        String failedCode = "121002";
+        PowerMockito.when(SMSUtil.sendSmsVerification("17666666666","1111")).thenReturn(failedCode);
+        mobileVerification.setCreateTime(Timestamp.valueOf(LocalDateTime.of(2018,1,1,1,1)));
+        when(emailService.sendArrearsEmail()).thenReturn(true);
+        verficationLogic.sendMobileVerfication("17666666666");
+
+
+    }
+}