Skip to content

Commit

Permalink
Merge pull request #909 from johnbrvc/i_900_multiple_groups_per_team
Browse files Browse the repository at this point in the history
i_900: add support for multiple groups per team
  • Loading branch information
johnbrvc authored Feb 9, 2024
2 parents db9f8c5 + 377a925 commit 11aa59a
Show file tree
Hide file tree
Showing 84 changed files with 7,206 additions and 5,266 deletions.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,23 @@
/profiles.properties
/profiles/
/testout/
/html/
/public_html/
/results/
/reports/
/log/
passwords.txt
pc2export.dat
results.xml
results_*.xml

/.classes
/realm.properties
/VERSION
/pc2ws.properties
cacerts.pc2

projects/*.gz
projects/*.zip
projects/WTI-UI/package-lock.json
projects/WTI-UI/.angular/
Binary file modified projects/EWTeam/lib/pc2.jar
Binary file not shown.
Binary file modified projects/WTI-API/WebContent/WEB-INF/lib/pc2.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
/**
* Contains various tests to insure proper operation of {@link ContestController} methods which
* fetch contest clarifications from the PC2 Contest.
*
*
* The setup() prior to running the JUnit tests injects into the ContestController a "mock" PC2 server
* connection, so that the test can be run without actually having a PC2 server/contest running.
*
* Each test method is responsible for configuring the "mock contest" values located as protected fields in
* in the {@link ContestControllerInjection} superclass (and therefore accessible by this class).
* (This is a somewhat poor use of inheritance, but it does provide a convenient way give all JUnit tests
*
* Each test method is responsible for configuring the "mock contest" values located as protected fields in
* in the {@link ContestControllerInjection} superclass (and therefore accessible by this class).
* (This is a somewhat poor use of inheritance, but it does provide a convenient way give all JUnit tests
* access to the mock PC2 server connection.)
*
*
* @author EWU WebTeamClient project team, with updates by John Clevenger, PC2 Development Team (pc2.ecs.csus.edu)
*
*/
Expand All @@ -36,7 +36,7 @@ public class Test_Contest_Get_Clarifications extends ContestControllerInjection{

private Response response;
private ContestController controller;

//a (mock) clarification
private String teamName = "Team1";
private String problem = "A. Dogzilla";
Expand All @@ -45,7 +45,7 @@ public class Test_Contest_Get_Clarifications extends ContestControllerInjection{

@Before
public void setUp() throws Exception {

//inject a Mock PC2 server connection into the ContestController
this.contestControllerInjection();
this.controller = new ContestController();
Expand All @@ -62,20 +62,20 @@ public void Test_Get_Clarifications_401_Unauthorized_User(){
this.response = this.controller.clarifications("inValidId");
assertEquals(401, this.response.getStatus());
}

/**
* Test that under normal circumstances (logged in, contest properly configured and running), requesting clarifications
* returns "200" (OK).
*
*
* @throws Exception
*/
@Test
public void Test_Get_Clarifications_200() throws Exception{
public void Test_Get_Clarifications_200() throws Exception{

Mockito.when(connection.getContest().getClarifications()).thenReturn(new IClarification[] {mockedClarification});
Mockito.when(mockedClarification.getTeam()).thenReturn(mockedTeam);
Mockito.when(mockedClarification.getTeam().getGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getGroup().getName()).thenReturn(teamName);
Mockito.when(mockedClarification.getTeam().getPrimaryGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getPrimaryGroup().getName()).thenReturn(teamName);
Mockito.when(mockedClarification.getTeam().getDisplayName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getTeam().getLoginName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getProblem()).thenReturn(mockedProblem);
Expand All @@ -85,44 +85,44 @@ public void Test_Get_Clarifications_200() throws Exception{
Mockito.when(mockedClarification.getSubmissionTime()).thenReturn(12345678L);
Mockito.when(mockedClarification.isAnswered()).thenReturn(true);
Mockito.when(connection.getMyClient().getLoginName()).thenReturn("Team1");

//make sure the mock says that the contest is running for this test
Mockito.when(connection.getContest().isContestClockRunning()).thenReturn(true);

this.response = this.controller.clarifications(testKey);
assertEquals(200, this.response.getStatus());
}

/**
* Test that, while properly logged in and the contest is running, when requesting a list of the clarifications submitted by a team
* but there is a clarification that has no problem associated with it,
* Test that, while properly logged in and the contest is running, when requesting a list of the clarifications submitted by a team
* but there is a clarification that has no problem associated with it,
* "500" (INTERNAL_SERVER_ERROR) is returned -- because the server should never have accepted a
* clarification that doesn't have a valid problem associated with it.
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void Test_Get_Clarifications_500_Clar_Has_No_Associated_Problem() throws Exception {
public void Test_Get_Clarifications_500_Clar_Has_No_Associated_Problem() throws Exception {

Mockito.when(connection.getContest().getClarifications()).thenReturn(new IClarification[] {mockedClarification});

Mockito.when(mockedClarification.getTeam()).thenReturn(mockedTeam);
Mockito.when(mockedClarification.getTeam().getGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getGroup().getName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getTeam().getPrimaryGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getPrimaryGroup().getName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getTeam().getDisplayName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getTeam().getLoginName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getProblem()).thenThrow(NullPointerException.class);

Mockito.when(connection.getMyClient().getLoginName()).thenReturn(teamName);
Mockito.when(connection.getContest().getProblems()).thenThrow(NullPointerException.class);

//make sure the mock says that the contest is running for this test
Mockito.when(connection.getContest().isContestClockRunning()).thenReturn(true);

this.response = this.controller.clarifications(testKey);
assertEquals(500, this.response.getStatus());
}

/**
* Test that an attempt to fetch clarifications when properly logged in but the contest is not running returns
* "401" (Unauthorized).
Expand All @@ -131,33 +131,33 @@ public void Test_Get_Clarifications_500_Clar_Has_No_Associated_Problem() throws
@SuppressWarnings("unchecked")
@Test
public void Test_Get_Clarifications_401_Contest_Not_Running() throws Exception{

//define some (mock) clarifications, even though we shouldn't be able to access them
Mockito.when(connection.getContest().getClarifications()).thenReturn(new IClarification[] {mockedClarification});

Mockito.when(mockedClarification.getTeam()).thenReturn(mockedTeam);
Mockito.when(mockedClarification.getTeam().getGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getGroup().getName()).thenReturn("Team1");
Mockito.when(mockedClarification.getTeam().getPrimaryGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getPrimaryGroup().getName()).thenReturn("Team1");
Mockito.when(mockedClarification.getTeam().getDisplayName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getTeam().getLoginName()).thenReturn(teamName.toLowerCase());

Mockito.when(connection.getMyClient().getLoginName()).thenReturn(teamName);
Mockito.when(connection.getContest().getProblems()).thenThrow(NotLoggedInException.class);
//make sure the mock says that the contest is not running for this test

//make sure the mock says that the contest is not running for this test
Mockito.when(connection.getContest().isContestClockRunning()).thenReturn(false);

this.response = this.controller.clarifications(testKey);
assertEquals(401, this.response.getStatus());
}

/**
* Test that requesting the first clarification from Site 1 returns a clarification with is "1-1"
* Test that requesting the first clarification from Site 1 returns a clarification with is "1-1"
* and a response code of "200" (OK).
* @throws Exception
*/
@Test public void Test_Get_Clarifications_200_Id_Received() throws Exception{

//return Mocked Clarification info when the server (via the userconnection) asks the contest for clarifications
Mockito.when(connection.getContest().getClarifications()).thenReturn(new IClarification[] {mockedClarification});
Mockito.when(mockedClarification.getQuestion()).thenReturn(question);
Expand All @@ -166,36 +166,36 @@ public void Test_Get_Clarifications_401_Contest_Not_Running() throws Exception{
Mockito.when(mockedClarification.isAnswered()).thenReturn(true);
Mockito.when(mockedClarification.getSiteNumber()).thenReturn(1);
Mockito.when(mockedClarification.getNumber()).thenReturn(1);
//return Mocked Team info when the server (via the userconnection) asks the Clarification for Team info

//return Mocked Team info when the server (via the userconnection) asks the Clarification for Team info
Mockito.when(mockedClarification.getTeam()).thenReturn(mockedTeam);
Mockito.when(mockedClarification.getTeam().getGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getGroup().getName()).thenReturn(teamName);
Mockito.when(mockedClarification.getTeam().getPrimaryGroup()).thenReturn(mockedGroup);
Mockito.when(mockedClarification.getTeam().getPrimaryGroup().getName()).thenReturn(teamName);
Mockito.when(mockedClarification.getTeam().getDisplayName()).thenReturn(teamName.toLowerCase());
Mockito.when(mockedClarification.getTeam().getLoginName()).thenReturn(teamName.toLowerCase());

//return Mocked Problem info when the server (via the userconnection) asks the Clarification for Problem info
Mockito.when(mockedClarification.getProblem()).thenReturn(mockedProblem);
Mockito.when(mockedClarification.getProblem().getName()).thenReturn(problem);

Mockito.when(connection.getMyClient().getLoginName()).thenReturn(teamName);

//make sure the mock says that the contest is running for this test
//make sure the mock says that the contest is running for this test
Mockito.when(connection.getContest().isContestClockRunning()).thenReturn(true);

this.response = this.controller.clarifications(testKey);
assertEquals(200, this.response.getStatus());

@SuppressWarnings("unchecked")
List<ClarificationModel> clars = (List<ClarificationModel>) this.response.getEntity();
assertEquals("1-1", clars.get(0).id);

}

@After
public void tearDown() throws Exception {
if(response != null)
this.response.close();
}

}
19 changes: 15 additions & 4 deletions src/edu/csus/ecs/pc2/api/ITeam.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
// Copyright (C) 1989-2019 PC2 Development Team: John Clevenger, Douglas Lane, Samir Ashoo, and Troy Boudreau.
package edu.csus.ecs.pc2.api;

import java.util.HashMap;

import edu.csus.ecs.pc2.core.model.ElementId;

/**
* This interface describes the PC<sup>2</sup> API view of a contest <I>Team</i>.
* Note that every <I>Team</i> in the API view is a subclass of {@link IClient},
* so a &quot;team view&quot; also contains the general information described by
* {@link IClient}.
*
*
* <p>
* This documentation describes the current <I>draft</i> of the PC<sup>2</sup> API, which is subject to change.
*
*
* @author [email protected]
* @version $Id$
*/
Expand All @@ -19,9 +23,16 @@ public interface ITeam extends IClient {

/**
* Get the group associate with this team.
*
*
* @see IGroup
* @return group information.
*/
IGroup getGroup();
public HashMap<ElementId, IGroup> getGroups();

/**
* Get the primary (cms) group for a team
*
* @return id of the CMS supplied group (so-called primary group)
*/
public IGroup getPrimaryGroup();
}
39 changes: 30 additions & 9 deletions src/edu/csus/ecs/pc2/api/implementation/TeamImplementation.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// Copyright (C) 1989-2019 PC2 Development Team: John Clevenger, Douglas Lane, Samir Ashoo, and Troy Boudreau.
package edu.csus.ecs.pc2.api.implementation;

import java.util.HashMap;

import edu.csus.ecs.pc2.api.IGroup;
import edu.csus.ecs.pc2.api.ITeam;
import edu.csus.ecs.pc2.core.model.Account;
import edu.csus.ecs.pc2.core.model.ClientId;
import edu.csus.ecs.pc2.core.model.ElementId;
import edu.csus.ecs.pc2.core.model.IInternalContest;

/**
* Implementation for ITeam.
*
*
* @author [email protected]
* @version $Id$
*/
Expand All @@ -21,7 +24,8 @@ public class TeamImplementation extends ClientImplementation implements ITeam {

private String shortName;

private IGroup group = null;
private HashMap<ElementId, IGroup> groups = null;
private IGroup primaryGroup = null;

public TeamImplementation(ClientId submitter, IInternalContest internalContest) {
super(submitter, internalContest);
Expand All @@ -38,12 +42,21 @@ public TeamImplementation(ClientId submitter, IInternalContest internalContest)
private void setAccountValues(Account account, IInternalContest contest) {
displayName = account.getDisplayName();
shortName = account.getClientId().getName();
if (account.getGroupId() != null) {
// SOMEDAY ensure that groupId is not null
// this happened on load of teams.tsv and groups.tsv
if (contest.getGroup(account.getGroupId()) != null){
group = new GroupImplementation(account.getGroupId(), contest);
if (account.getGroupIds() != null) {
for(ElementId elementId: account.getGroupIds()) {
if (contest.getGroup(elementId) != null){
if(groups == null) {
groups = new HashMap<ElementId, IGroup>();
}
GroupImplementation group = new GroupImplementation(elementId, contest);
groups.put(elementId, group);
if(primaryGroup == null && account.getPrimaryGroupId() == elementId) {
primaryGroup = group;
}
}
}
} else {
groups = null;
}
}

Expand All @@ -52,16 +65,24 @@ public TeamImplementation(Account account, IInternalContest contest) {
setAccountValues(account, contest);
}

@Override
public String getDisplayName() {
return displayName;
}

public IGroup getGroup() {
return group;
@Override
public HashMap<ElementId, IGroup> getGroups() {
return groups;
}

@Override
public String getLoginName() {
return shortName;
}

@Override
public IGroup getPrimaryGroup() {
return primaryGroup;
}

}
Loading

0 comments on commit 11aa59a

Please sign in to comment.