From 206a5f21433802b1679a351f4b3b957fab44c868 Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Sat, 21 Jan 2017 09:50:24 +0800 Subject: [PATCH] fix close challenge immediately logic --- .../uploads/impl/DefaultUploadServices.java | 49 ++++++- .../contest/ejb/ContestServiceFacadeBean.java | 129 +++++++++++++++--- 2 files changed, 153 insertions(+), 25 deletions(-) diff --git a/components/online_review_upload_services/src/java/main/com/cronos/onlinereview/services/uploads/impl/DefaultUploadServices.java b/components/online_review_upload_services/src/java/main/com/cronos/onlinereview/services/uploads/impl/DefaultUploadServices.java index ca64a0136..bb2d8a700 100644 --- a/components/online_review_upload_services/src/java/main/com/cronos/onlinereview/services/uploads/impl/DefaultUploadServices.java +++ b/components/online_review_upload_services/src/java/main/com/cronos/onlinereview/services/uploads/impl/DefaultUploadServices.java @@ -113,8 +113,17 @@ * change the other variables. *

* + * Version 1.1.4 (TOPCODER DIRECT - FIXES FOR CLOSE PRIVATE CHALLENGE IMMEDIATELY): + *
    + *
  1. Added {@link #isProjectResultCategory(long)} method
  2. + *
+ *

+ *

+ * Thread safety: the thread safety is completely relied to the managers implementations because it's impossible to + * change the other variables. + *

* @author fabrizyo, saarixx, cyberjag, TCSDEVELOPER - * @version 1.1.3 + * @version 1.1.4 */ public class DefaultUploadServices implements UploadServices { @@ -1627,6 +1636,39 @@ public Resource addPrimaryScreener(long projectId, long userId) throws UploadSer } } + /** + * Lookup function for project categories that should have a project_result row. These rows are used + * for ratings, reliability, and the Digital Run. + * + * Copied from online_review: com/cronos/onlinereview/util/ActionsHelper.java#L205 + * + * @param categoryId the category id to look up. + * @return whether the provided category id should have a project_result row. + * @since 1.1.4 + */ + private static boolean isProjectResultCategory(long categoryId) { + return (categoryId == 1 // Component Design + || categoryId == 2 // Component Development + || categoryId == 5 // Component Testing + || categoryId == 6 // Application Specification + || categoryId == 7 // Application Architecture + || categoryId == 9 // Bug Hunt + || categoryId == 13 // Test Scenarios + || categoryId == 26 // Test Suites + || categoryId == 14 // Application Assembly + || categoryId == 23 // Application Conceptualization + || categoryId == 19 // UI Prototype + || categoryId == 24 // RIA Build + || categoryId == 25 // RIA Component + || categoryId == 29 // Copilot Posting + || categoryId == 35 // Content Creation + || categoryId == 36 // Reporting + || categoryId == 38 // First2Finish + || categoryId == 39 // Code + || categoryId == 40 // Design F2F (NEW) + ); + } + /** * Populate project_result and component_inquiry for new submitters. * @@ -1644,9 +1686,8 @@ private void populateProjectResult(Project project, Collection newSubmitters) th PreparedStatement ratingStmt = null; PreparedStatement componentInquiryStmt = null; long categoryId = project.getProjectCategory().getId(); - // Only design/development/assembly will modify the project result table. - if (categoryId != 1 && categoryId != 2 && categoryId != 14) { - // design/development/assembly project need project_result + + if (!isProjectResultCategory(categoryId)) { return; } LOG.log(Level.INFO, "Populating the project result table."); diff --git a/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java b/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java index 6774b22de..7a13c7586 100644 --- a/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java +++ b/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java @@ -862,9 +862,14 @@ *
  • Add {@link #cancelSoftwareContestByUser(TCSubject, long)}
  • * * + * Version 3.6 (TOPCODER DIRECT - FIXES FOR CLOSE PRIVATE CHALLENGE IMMEDIATELY) + * * @author snow01, pulky, murphydog, waits, BeBetter, hohosky, isv, tangzx, GreatKevin, lmmortal, minhu, GreatKevin, tangzx * @author isv, GreatKevin, Veve, deedee, TCSCODER, TCSASSEMBLER - * @version 3.5 + * @version 3.6 */ @Stateless @TransactionManagement(TransactionManagementType.CONTAINER) @@ -963,6 +968,18 @@ public class ContestServiceFacadeBean implements ContestServiceFacadeLocal, Cont */ private static final String RESOURCE_INFO_PAYMENT_NA = "N/A"; + /** + * Resource info attribute for Manual payment + * @since 3.6 + */ + private static final String RESOURCE_INFO_MANUAL_PAYMENT = "Manual Payments"; + + /** + * Scorecard ID attibute + * @since 3.6 + */ + private static final String SCORECARD_ID_ATTRIBUTE = "Scorecard ID"; + /** * Email file template source key that is used by email generator. */ @@ -1011,6 +1028,13 @@ public class ContestServiceFacadeBean implements ContestServiceFacadeLocal, Cont */ private static final String ADMIN_ROLE = "Cockpit Administrator"; + /** + * Private constant specifying project registration phase name. + * + * @since 3.6 + */ + private static final String PROJECT_REGISTRATION_PHASE_NAME = "Registration"; + /** * Private constant specifying project submission phase name. * @@ -4098,13 +4122,35 @@ private com.topcoder.management.resource.Resource createIterativeReviewerResourc * @throws UserServiceException if error when getting resource handle. * @since 2.5 */ - private com.topcoder.management.resource.Resource createReviewerResource(long userId, long contestId, long phaseId, boolean hasPayment) throws UserServiceException { + private com.topcoder.management.resource.Resource createReviewerResource(long userId, long contestId, long phaseId, + boolean hasPayment) throws UserServiceException { + return createReviewerResource(userId, contestId, phaseId, hasPayment, false); + } + + /** + * Creates a Reviewer Resource to add to the contest + * + * @param userId the user id + * @param contestId the contest id. + * @param phaseId the phase the resource adds to, 0 for not add + * @param hasPayment whether this resource should be paid. + * @param iterativeReviewer whether this iterative review + * @return the created Reviewer resource to add. + * @throws UserServiceException if error when getting resource handle. + * @since 3.6 + */ + private com.topcoder.management.resource.Resource createReviewerResource(long userId, long contestId, long phaseId, + boolean hasPayment, boolean iterativeReviewer) throws UserServiceException { com.topcoder.management.resource.Resource resource = new com.topcoder.management.resource.Resource(); // unset id resource.setId(-1); // set resource to reviewer - resource.setResourceRole(new ResourceRole(ResourceRole.RESOURCE_ROLE_REVIEWER_ID)); + if (iterativeReviewer){ + resource.setResourceRole(new ResourceRole(ResourceRole.RESOURCE_ROLE_ITERATIVE_REVIEWER_ID)); + }else { + resource.setResourceRole(new ResourceRole(ResourceRole.RESOURCE_ROLE_REVIEWER_ID)); + } resource.setProperty(RESOURCE_INFO_HANDLE, userService.getUserHandle(userId)); resource.setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, String.valueOf(userId)); @@ -4121,6 +4167,7 @@ private com.topcoder.management.resource.Resource createReviewerResource(long us if(!hasPayment) { resource.setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); resource.setProperty(RESOURCE_INFO_PAYMENT, RESOURCE_INFO_PAYMENT_NA); + resource.setProperty(RESOURCE_INFO_MANUAL_PAYMENT, "true"); } // set registration date to now @@ -9083,28 +9130,45 @@ public void closeSoftwareContest(TCSubject tcSubject, long projectId, long winne //close submission and review phase com.topcoder.project.phases.Phase submissionPhase = null; + com.topcoder.project.phases.Phase reviewPhase = null; for (com.topcoder.project.phases.Phase phase : phases) { - if (PROJECT_SUBMISSION_PHASE_NAME.equals(phase.getPhaseType().getName()) || - PROJECT_ITERATIVE_REVIEW_PHASE_NAME.equals(phase.getPhaseType().getName()) || - PROJECT_REVIEW_PHASE_NAME.equals(phase.getPhaseType().getName())) { - Date scheduleStartDate = phase.getScheduledStartDate(); + if (PROJECT_REGISTRATION_PHASE_NAME.equals(phase.getPhaseType().getName()) || + PROJECT_SUBMISSION_PHASE_NAME.equals(phase.getPhaseType().getName()) || + PROJECT_REVIEW_PHASE_NAME.equals(phase.getPhaseType().getName()) || + PROJECT_ITERATIVE_REVIEW_PHASE_NAME.equals(phase.getPhaseType().getName())) { Date currentDate = new Date(); - Date actualStartDate = null; - long length = 0L; - if (currentDate.before(scheduleStartDate)){ - //set length to 5 minutes - length = 5 * MINUTE_IN_MILIS; - actualStartDate = new Date(currentDate.getTime() - length); - } else{ - actualStartDate = scheduleStartDate; - length = currentDate.getTime() - scheduleStartDate.getTime(); - } - phase.setActualStartDate(actualStartDate); - phase.setActualEndDate(currentDate); - phase.setLength(length); - phase.setPhaseStatus(PhaseStatus.CLOSED); + //length 1 hour + long length = 60 * MINUTE_IN_MILIS; + //submision start 3h before + Date regStartDate = new Date(currentDate.getTime() - 180 * MINUTE_IN_MILIS); + //submision start 2h before + Date submissionStartDate = new Date(currentDate.getTime() - 120 * MINUTE_IN_MILIS); + //submission end / review start 1h before + Date submissionEndDate = new Date(currentDate.getTime() - 60 * MINUTE_IN_MILIS); + if (PROJECT_SUBMISSION_PHASE_NAME.equals(phase.getPhaseType().getName())) { + phase.setScheduledStartDate(submissionStartDate); + phase.setActualStartDate(submissionStartDate); + phase.setScheduledEndDate(submissionEndDate); + phase.setActualEndDate(submissionEndDate); + phase.setLength(length); + phase.setPhaseStatus(PhaseStatus.CLOSED); submissionPhase = phase; + } else if (PROJECT_REGISTRATION_PHASE_NAME.equals(phase.getPhaseType().getName())) { + phase.setScheduledStartDate(regStartDate); + phase.setFixedStartDate(regStartDate); + phase.setActualStartDate(regStartDate); + phase.setScheduledEndDate(submissionEndDate); + phase.setActualEndDate(submissionEndDate); + phase.setLength(2 * length); + phase.setPhaseStatus(PhaseStatus.CLOSED); + } else { + phase.setScheduledStartDate(submissionEndDate); + phase.setActualStartDate(submissionEndDate); + phase.setScheduledEndDate(currentDate); + phase.setLength(length); + phase.setPhaseStatus(PhaseStatus.OPEN); + reviewPhase = phase; } } } @@ -9115,14 +9179,37 @@ public void closeSoftwareContest(TCSubject tcSubject, long projectId, long winne Submission submission = uploadManager.getSubmission(submissionId); submission.setInitialScore(100.0); submission.setFinalScore(100.0); + submission.setPlacement(1L); + submission.setPrize(contest.getPrizes().get(0)); uploadManager.updateSubmission(submission, String.valueOf(tcSubject.getUserId())); + //create reviewer, remove if there is + com.topcoder.management.resource.Resource[] reviewers = this.projectServices.searchResources(contest.getId(), + ResourceRole.RESOURCE_ROLE_ITERATIVE_REVIEWER_ID); + for (com.topcoder.management.resource.Resource r : reviewers) { + this.projectServices.removeResource(r, String.valueOf(tcSubject.getUserId())); + } + com.topcoder.management.resource.Resource reviewer = createReviewerResource(winnerId, contest.getId(), + reviewPhase.getId(), false, ProjectCategory.FIRST2FINISH.getName().equals(contest.getProjectCategory().getName())); + + reviewer = projectServices.updateResource(reviewer, String.valueOf(tcSubject.getUserId())); + + //create review + Scorecard scorecard = projectServices.getScorecard(Long.parseLong((String) reviewPhase.getAttribute(SCORECARD_ID_ATTRIBUTE))); + createReview(reviewer, submissionId, 1, scorecard, reviewPhase.getId()); + Upload upload = submission.getUpload(); upload.setProjectPhase(submissionPhase.getId()); uploadManager.updateUpload(upload, String.valueOf(tcSubject.getUserId())); } catch (IOException e) { logger.error("Failed to create submission file"); throw new ContestServiceException("Failed to create submission file", e); + } catch (UserServiceException e) { + logger.error("User not found: " + String.valueOf(winnerId)); + throw new ContestServiceException("User not found: " + String.valueOf(winnerId), e); + } catch (ReviewManagementException e) { + logger.error("Failed to create review"); + throw new ContestServiceException("Failed to create review", e); } catch (ProjectServicesException e) { logger.error("Failed to update phase"); throw new ContestServiceException("Failed to update phase", e);