Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/ChosenGrouper.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/ChosenGrouper.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/ChosenGrouper.java (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.learningdesign; + +import java.util.List; + +import org.lamsfoundation.lams.usermanagement.User; + + +/** + * + * @author Jacky Fang + * @since 2005-3-24 + * @version + * + */ +public class ChosenGrouper implements Grouper +{ + + /** + * + */ + public ChosenGrouper() + { + super(); + // TODO Auto-generated constructor stub + } + + /** + * @see org.lamsfoundation.lams.learningdesign.Grouper#doGrouping(org.lamsfoundation.lams.learningdesign.Grouping, java.util.List) + */ + public void doGrouping(Grouping grouping, List learners) + { + // TODO Auto-generated method stub + + } + + /** + * @see org.lamsfoundation.lams.learningdesign.Grouper#doGrouping(org.lamsfoundation.lams.learningdesign.Grouping, org.lamsfoundation.lams.usermanagement.User) + */ + public void doGrouping(Grouping grouping, User learner) + { + // TODO Auto-generated method stub + + } + +} Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/ChosenGrouping.java =================================================================== diff -u -r91523738e69ab3ad209d6a8dfb25114cdfcfb719 -rdfed139a7289e34015731c0b41b2435a0b902b6f --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/ChosenGrouping.java (.../ChosenGrouping.java) (revision 91523738e69ab3ad209d6a8dfb25114cdfcfb719) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/ChosenGrouping.java (.../ChosenGrouping.java) (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -17,12 +17,13 @@ /** Creates a new instance of ChosenGrouping */ public ChosenGrouping() { + super.grouper = new ChosenGrouper(); } /** full constructor */ public ChosenGrouping(Long groupingId, Set groups, Set activities) { - super(groupingId, groups, activities); + super(groupingId, groups, activities,new ChosenGrouper()); } /** Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/Group.java =================================================================== diff -u -rd6e24451f694815d6138e6189fa8ba2294ee6944 -rdfed139a7289e34015731c0b41b2435a0b902b6f --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/Group.java (.../Group.java) (revision d6e24451f694815d6138e6189fa8ba2294ee6944) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/Group.java (.../Group.java) (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -16,7 +16,7 @@ * table="lams_group" * */ -public class Group implements Serializable,Nullable { +public class Group implements Serializable,Nullable,Comparable { public final static int STAFF_GROUP_ORDER_ID = 1; @@ -194,7 +194,21 @@ .append(getOrderId()) .toHashCode(); } + + /** + * Sort the groups using order id. + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object o) + { + Group group = (Group)o; + + return this.orderId - group.orderId; + } + //--------------------------------------------------------------------- + // Field Access Methods + //--------------------------------------------------------------------- /** * Return whether the target user is in this group or not. * @param learner the target user Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/Grouper.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/Grouper.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/Grouper.java (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.learningdesign; + +import java.util.List; + +import org.lamsfoundation.lams.usermanagement.User; + + + + +/** + * This is interface that defines the contract for performing grouping + * algorithm. + * + * @author Jacky Fang + * @since 2005-3-24 + * @version 1.1 + * + */ +public interface Grouper +{ + + public void doGrouping(Grouping grouping, List learners); + + public void doGrouping(Grouping grouping, User learner); + +} Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/Grouping.java =================================================================== diff -u -r0055799135c002681cf6504a386e061e318df494 -rdfed139a7289e34015731c0b41b2435a0b902b6f --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/Grouping.java (.../Grouping.java) (revision 0055799135c002681cf6504a386e061e318df494) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/Grouping.java (.../Grouping.java) (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -1,20 +1,24 @@ package org.lamsfoundation.lams.learningdesign; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Set; +import java.util.TreeSet; + import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.lamsfoundation.lams.lesson.LessonClass; import org.lamsfoundation.lams.usermanagement.User; - /** - * @hibernate.class - * table="lams_grouping" - * + * + * @hibernate.class table="lams_grouping" + * + * @author Jacky Fang */ public abstract class Grouping implements Serializable { @@ -31,7 +35,11 @@ /** identifier field */ private Long groupingId; - /** nullable persistent field */ + /** nullable persistent field + * TODO It make sense only if we want to setup some limits for the number + * of groups the author can setup in the authoring GUI. It might need + * to be deleted if the end user doesn't like this limits. + */ private Integer maxNumberOfGroups; /** nullable persistent field */ @@ -47,6 +55,7 @@ /** non-persistent field */ protected Set learners; + protected Grouper grouper; /** * static final variables indicating the grouping_support of activities *******************************************************************/ @@ -58,11 +67,12 @@ /******************************************************************/ /** full constructor */ - public Grouping(Long groupingId, Set groups, Set activities) + public Grouping(Long groupingId, Set groups, Set activities,Grouper grouper) { this.groupingId = groupingId; this.groups = groups; this.activities = activities; + this.grouper = grouper; } /** default constructor */ @@ -112,6 +122,8 @@ */ public Set getGroups() { + if(this.groups==null) + setGroups(new TreeSet()); return this.groups; } @@ -126,6 +138,8 @@ */ public Set getActivities() { + if(this.activities==null) + setActivities(new TreeSet(new ActivityOrderComparator())); return this.activities; } @@ -164,14 +178,23 @@ { return maxNumberOfGroups; } + /** * @param maxNumberOfGroups The maxNumberOfGroups to set. */ public void setMaxNumberOfGroups(Integer maxNumberOfGroups) { this.maxNumberOfGroups = maxNumberOfGroups; } - + public Integer getGroupingUIID() { + return groupingUIID; + } + public void setGroupingUIID(Integer groupingUIID) { + this.groupingUIID = groupingUIID; + } + //--------------------------------------------------------------------- + // Service methods + //--------------------------------------------------------------------- /** * Return the next group order id. * @return the next order id. @@ -193,10 +216,6 @@ */ public Set getLearners() { - //verify pre-condition - if(getGroups()==null) - throw new IllegalArgumentException("Fail to get learnings from" + - "a grouping without groups"); learners = new HashSet(); for(Iterator i = getGroups().iterator();i.hasNext();) @@ -225,16 +244,47 @@ } /** + * Iterate through all the groups in this grouping and figure out the group + * with the least members in it. + * @return the group with the least member. + */ + public Group getGroupWithLeastMember() + { + List groups = new ArrayList(this.getGroups()); + + Group minGroup = (Group) groups.get(0); + + for (int i = 1; i < groups.size(); i++) + { + Group tempGroup = (Group) groups.get(i); + if (tempGroup.getUsers().size() < minGroup.getUsers().size()) + minGroup = tempGroup; + } + return minGroup; + } + + /** * Is this group a learner group. It is also possible that the group is a * staff group. * @return whether the group is learner group or not. */ public abstract boolean isLearnerGroup(Group group); - - public Integer getGroupingUIID() { - return groupingUIID; + + /** + * Create or update groups for this grouping with a list of new learners. + * @param learners the list of learners need to be grouped. + */ + public void doGrouping(List learners) + { + this.grouper.doGrouping(this,learners); } - public void setGroupingUIID(Integer groupingUIID) { - this.groupingUIID = groupingUIID; + + /** + * Create or updates groups for this grouping with a single new learner. + * @param learner the new learner needs to be grouped. + */ + public void doGrouping(User learner) + { + this.grouper.doGrouping(this,learner); } } Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/RandomGrouper.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/RandomGrouper.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/RandomGrouper.java (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -0,0 +1,214 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.learningdesign; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +import org.lamsfoundation.lams.usermanagement.User; + + +/** + *

The random grouping algorithm implementation. It allocates user into the + * groups according to the attributes acceptted from user interface: + * numberOfGroups and learnersPerGroup. If any of + * these two attribute has be set, the random grouping will be done + * correspondently.

+ * + *

In the case of random grouping by number of groups, the number of groups + * will be fixed, and learners are evenly allocated into the groups. For + * example, there are 10 users and numberOfGroups=3, the number + * of learners in three groups will 4,3,3. And if there are 1 user and + * numberOfGroups=3, all three groups still will be created + * with learner number 1,0,0.

+ * + *

In the case of random grouping by learners per group, groups are only + * created if the total learner number exceeds the existing group capacity. + * Learners are also evenly allocated into the groups.For example, if there is + * 5 users and learnerPerGroup=3, only 2 groups will be created. + *

+ * + * @author Jacky Fang + * @since 2005-3-24 + * @version 1.1 + * + */ +public class RandomGrouper implements Grouper +{ + //--------------------------------------------------------------------- + // Grouping algorithm Implementation Method + //--------------------------------------------------------------------- + /** + * Do the grouping for single new learner. + * @see org.lamsfoundation.lams.learningdesign.Grouper#doGrouping(org.lamsfoundation.lams.learningdesign.Grouping, org.lamsfoundation.lams.usermanagement.User) + */ + public void doGrouping(Grouping randomGrouping, User learner) + { + //convert the single user into a list. + List learners = new ArrayList(); + learners.add(learner); + //delegate to do grouping for a list of learners. + doGrouping(randomGrouping,learners); + } + + /** + * Do the grouping for a list of new learners. + * @see org.lamsfoundation.lams.learningdesign.Grouper#doGrouping(org.lamsfoundation.lams.learningdesign.Grouping, java.util.List) + */ + public void doGrouping(Grouping randomGrouping, List learners) + { + //calculate how many new groups needs to be created. + int numOfGroupsTobeCreated =0; + if(randomGrouping.getGroups().size()==0) + numOfGroupsTobeCreated = calculateNumOfNewGroups((RandomGrouping)randomGrouping, + learners, + true); + else + numOfGroupsTobeCreated = calculateNumOfNewGroups((RandomGrouping)randomGrouping, + learners, + false); + //create new groups + createGroups((RandomGrouping)randomGrouping,numOfGroupsTobeCreated); + //join the new learners into these groups. + joinGroups(randomGrouping, learners); + } + //--------------------------------------------------------------------- + // Helper Methods - doGrouping + //--------------------------------------------------------------------- + /** + * Compute the number of new groups needs to be created based on passed + * in grouping. It figure out group by number of groups or group by + * learner per group automatically. + * + * @param randomGrouping the grouping we used to group learner + * @param learners the list of learners need to be grouped + * @return the number required new group. + */ + private int calculateNumOfNewGroups(RandomGrouping randomGrouping, + List learners, + boolean isInitialization) + { + if(randomGrouping.getNumberOfGroups()!=null) + return getNewGroupsByNumberOfGroups(randomGrouping, isInitialization); + else if(randomGrouping.getLearnersPerGroup()!=null) + return getNewGroupsByLearnerPerGroup(randomGrouping,learners); + + throw new RuntimeException("At least one random grouping algorithm" + + "needs to be defined."); + } + + /** + * Create new groups and insert them into the grouping. + * @param randomGrouping the requested grouping. + * @param numOfGroupsTobeCreated the number new groups need to be created. + */ + private void createGroups(RandomGrouping randomGrouping, + int numOfGroupsTobeCreated) + { + for(int i=0;iGrouping formed by random assignment. The random grouping can done in two + * ways:

+ *
  • 1. Randomly group learners by the number of groups set by author.
  • + *
  • 2. Randomly group learners by the number of learners in a group.
  • + * + *

    Note: Only one way can be chosen by the author to carry out the + * random grouping.

    + * * @author chris + * @author Jacky Fang */ public class RandomGrouping extends Grouping { @@ -51,12 +59,13 @@ /** Creates a new instance of RandomGrouping */ public RandomGrouping() { + super.grouper = new RandomGrouper(); } /** full constructor */ public RandomGrouping(Long groupingId, Set groups, Set activities, Integer numberOfGroups, Integer learnersPerGroup) { - super(groupingId, groups, activities); + super(groupingId, groups, activities,new RandomGrouper()); this.learnersPerGroup = learnersPerGroup; this.numberOfGroups = numberOfGroups; } Index: lams_common/src/java/org/lamsfoundation/lams/lesson/LessonClass.java =================================================================== diff -u -rd6e24451f694815d6138e6189fa8ba2294ee6944 -rdfed139a7289e34015731c0b41b2435a0b902b6f --- lams_common/src/java/org/lamsfoundation/lams/lesson/LessonClass.java (.../LessonClass.java) (revision d6e24451f694815d6138e6189fa8ba2294ee6944) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/LessonClass.java (.../LessonClass.java) (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -29,7 +29,8 @@ /** full constructor */ public LessonClass(Long groupingId, Set groups, Set activities, Group staffGroup, Lesson lesson) { - super(groupingId, groups, activities); + //don't think lesson class need perform doGrouping. set grouper to null. + super(groupingId, groups, activities,null); this.staffGroup = staffGroup; this.lesson = lesson; } Index: lams_common/test/java/org/lamsfoundation/lams/learningdesign/TestGrouping.java =================================================================== diff -u -r8bbaae4777d25bac513a7adc0b42b2d8480e05cc -rdfed139a7289e34015731c0b41b2435a0b902b6f --- lams_common/test/java/org/lamsfoundation/lams/learningdesign/TestGrouping.java (.../TestGrouping.java) (revision 8bbaae4777d25bac513a7adc0b42b2d8480e05cc) +++ lams_common/test/java/org/lamsfoundation/lams/learningdesign/TestGrouping.java (.../TestGrouping.java) (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -80,13 +80,13 @@ User user1 = new User(); user1.setUserId(new Integer(1)); Group group1 = new Group(); - insertUserIntoGroup(user1, group1); + insertUserIntoGroup(user1, group1,grouping.getNextGroupOrderId()); User user2 = new User(); user2.setUserId(new Integer(2)); Group group2 = new Group(); - insertUserIntoGroup(user2, group2); + insertUserIntoGroup(user2, group2,grouping.getNextGroupOrderId()); assertEquals("verify number of learners",2,grouping.getLearners().size()); } @@ -97,12 +97,12 @@ User user1 = new User(); user1.setUserId(new Integer(1)); Group group1 = new Group(); - insertUserIntoGroup(user1, group1); + insertUserIntoGroup(user1, group1,grouping.getNextGroupOrderId()); User user2 = new User(); user2.setUserId(new Integer(2)); Group group2 = new Group(); - insertUserIntoGroup(user2, group2); + insertUserIntoGroup(user2, group2,grouping.getNextGroupOrderId()); Group group = grouping.getGroupBy(user2); assertEquals("verify group retrieved",group2.getOrderId(),group.getOrderId()); @@ -114,7 +114,7 @@ User user1 = new User(); user1.setUserId(new Integer(1)); Group group1 = new Group(); - insertUserIntoGroup(user1, group1); + insertUserIntoGroup(user1, group1,grouping.getNextGroupOrderId()); User user2 = new User(); user2.setUserId(new Integer(2)); @@ -123,15 +123,38 @@ assertTrue("verify group retrieved",group.isNull()); } + + public void testGetGroupWithLeastMember() + { + int group1_orderId=grouping.getNextGroupOrderId(); + grouping.setGroups(new HashSet()); + User user1 = new User(); + user1.setUserId(new Integer(1)); + Group group1 = new Group(); + insertUserIntoGroup(user1,group1,group1_orderId ); + + User user3 = new User(); + user3.setUserId(new Integer(3)); + group1.getUsers().add(user3); + + User user2 = new User(); + user2.setUserId(new Integer(2)); + Group group2 = new Group(); + insertUserIntoGroup(user2, group2,grouping.getNextGroupOrderId()); + + Group group = grouping.getGroupWithLeastMember(); + assertEquals("verify group",2,group.getOrderId()); + + } /** * @param user1 * @param group1 */ - private void insertUserIntoGroup(User user, Group group) + private void insertUserIntoGroup(User user, Group group,int orderId) { group.setUsers(new HashSet()); group.getUsers().add(user); - group.setOrderId(grouping.getNextGroupOrderId()); + group.setOrderId(orderId); grouping.getGroups().add(group); } } Index: lams_common/test/java/org/lamsfoundation/lams/learningdesign/TestRandomGrouper.java =================================================================== diff -u --- lams_common/test/java/org/lamsfoundation/lams/learningdesign/TestRandomGrouper.java (revision 0) +++ lams_common/test/java/org/lamsfoundation/lams/learningdesign/TestRandomGrouper.java (revision dfed139a7289e34015731c0b41b2435a0b902b6f) @@ -0,0 +1,224 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.learningdesign; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.TreeSet; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.usermanagement.User; + +import junit.framework.TestCase; + + +/** + * + * @author Jacky Fang + * @since 2005-3-24 + * @version + * + */ +public class TestRandomGrouper extends TestCase +{ + //--------------------------------------------------------------------- + // Instance variables + //--------------------------------------------------------------------- + private static Logger log = Logger.getLogger(TestRandomGrouper.class); + + private RandomGrouping groupingByNumofGroups; + private RandomGrouping groupingByLearnerPerGroups; + private List userList = new ArrayList(); + private int testerUser = 10; + + + /** + * Constructor for TestRandomGrouper. + * @param arg0 + */ + public TestRandomGrouper(String testName) + { + super(testName); + } + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception + { + super.setUp(); + //initialize grouping + groupingByNumofGroups = new RandomGrouping(new Long(1), + new TreeSet(), + new TreeSet(), + new Integer(3),//number of groups + null); + groupingByLearnerPerGroups = new RandomGrouping(new Long(1), + new TreeSet(), + new TreeSet(), + null, + new Integer(4));//learner per groups + //initialize users + for(int i =0; i