Click here to Skip to main content
15,911,141 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi guys, I have these two tables to create groups of students based on preferences added by students.
Students_Table
-------------------
Stud_Name  Group_ID 
-------------------
Stud A    
Stud B      
Stud C    
Stud D    
Stud E
Stud F
Stud G
Stud H
Stud I
Stud J
Stud K
--------------------


Preference Tables
---------------------------------------------------------------------
Stud_Name  Pref 1   Pref 2   Pref 3   Pref 4   Pref 5   Pref 6  Pref 7
---------------------------------------------------------------------
Stud A    Stud B   Stud C   Stud D   Stud E   Stud F   Stud G  Stud H
Stud B    Stud A   Stud H   Stud K   Stud F   Stud J   Stud N  
Stud C    Stud I   Stud A
Stud D    Stud H   Stud K
Stud E
Stud F
Stud G
Stud H
Stud I
Stud J
Stud K
---------------------------------------------------------------------


The rules i am following is:
Each group can have minimum 5 and maximum 8 students. Following is the code i have for now,
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;

namespace InsertTeamIdIntoTable
{
    class Program
    {
        const string str = @"Data Source=localhost;Initial Catalog=Items;Integrated Security=True";
        static void Main(string[] args)
        {

            InsertItemData(str);
           
        }

        private static void InsertItemData(string connectionString)
        {
            string queryString =
                "Use Items Select Pref1,Pref2,Pref3,Pref4, Pref5,Pref6,Pref7 FROM dbo.Preference_Table;";

            using (SqlConnection connection =
                       new SqlConnection(connectionString))
            {
                SqlCommand command =
                    new SqlCommand(queryString, connection);
                connection.Open();

                SqlDataReader reader = command.ExecuteReader();
                int Group_ID = 1;
                while (reader.Read())
                {
                 // This function Checks each row and returns where 5 columns or more have values including stud_name column, so we can add them to group
				 bool flag = CheckValueNumber((IDataRecord)reader);
                    if (flag)
                    {

                        for (int i = 0; i < ((IDataRecord)reader).FieldCount; i++)
                        {
                            string StudentName = ((IDataRecord)reader)[i].ToString();
                            if (string.IsNullOrWhiteSpace(StudentName) == false)
                            {
							//This function checks if student exist in student_table
                                if (CheckStudentExists(str, StudentName))
                                {
								//This function checks if Group_ID already exist for student in student_table(because if there is already group_ID than we are not fgoing to modify that)
                                    if (CheckGroupIdExists(str, StudentName) == false)
                                    {
									
                                        UpdateTableStudents(str, Group_ID, StudentName);
                                    }
                                }
                                else
                                {
								//This i might have to remove because i don't want to insert any new records in students_table 
                                    InsertTableStudents(str, Group_ID, StudentName);
                                }
                            }
                            Console.WriteLine(StudentName);
                            Console.WriteLine();
                        }
                        Group_ID++;

                    }
                }
                Console.ReadLine();
                reader.Close();

            }
        }

        public static void UpdateTableStudents(string connectionString, int Group_ID, string StudentName)
        {
            string updateString = string.Format("Update dbo.Students_Table set item_id ={0} WHERE Stud_Name ='{1}';", Group_ID, StudentName);

            using (SqlConnection connection =
                       new SqlConnection(connectionString))
            {
                SqlCommand command =
                    new SqlCommand(updateString, connection);
                connection.Open();

                command.ExecuteNonQuery();

            }
        }

        public static void InsertTableStudents(string connectionString, int Group_ID, string StudentName)
        {
            string updateString = string.Format("use Items Update dbo.Students_Table Set Stud_ID = '{0}' where Stud_Name = '{1}';", Group_ID, StudentName);

            using (SqlConnection connection =
                       new SqlConnection(connectionString))
            {
                SqlCommand command =
                    new SqlCommand(updateString, connection);
                connection.Open();

                command.ExecuteNonQuery();

            }
        }


        public static bool CheckStudentExists(string connectionString, string StudentName)
        {
            string updateString = string.Format("Use Items Select count(Stud_ID) From dbo.Students_Table WHERE Stud_Name ='{0}';", StudentName);

            using (SqlConnection connection =
                       new SqlConnection(connectionString))
            {
                SqlCommand command =
                    new SqlCommand(updateString, connection);
                connection.Open();
                    return (Int32)command.ExecuteScalar() > 0;
                
                
            }
        }

        public static bool CheckGroupIdExists(string connectionString, string StudentName)
        {
            string updateString = string.Format("Use Items Select Group_Id From dbo.Students_Table WHERE Stud_Name ='{0}';", StudentName);

            using (SqlConnection connection =
                       new SqlConnection(connectionString))
            {
                SqlCommand command =
                    new SqlCommand(updateString, connection);
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();

                while (reader.Read())
                {
                    if (string.IsNullOrWhiteSpace(((IDataRecord)reader)[0].ToString()) == false)
                    {
                        return true;
                    }
                }

                reader.Close();
                return false;

            }
        }

        public static bool CheckValueNumber(IDataRecord record)
        {
            int count = 0;
            for (int i = 0; i < record.FieldCount; i++)
            {
                if (string.IsNullOrWhiteSpace(record[i].ToString()) == false)
                {
                    count++;
                }
            }
            return count >= 5;
        }

    }            

}

This is what I am actually doing. Check for each row in Preferences_table, where student has added at least 4 preferences and create a group_ID starting from 1 and insert it for all the students in that row to Students_Table in Group_ID column.
It is working, but there are some issues with code.
Problem 1: Not all students are getting a group ID because of return count >= 4; but i can't think of another way to implement this. Many students will not add preferences and they can't pass this condition (return count >= 4;) but they are still need to be added to a group.
Problem 2: If row one has "Stud B" and the row met condition (return count >= 4;)than i assign Group_ID fro row 1, but if any other row also has "Stud B" and the row passes condition (return count >= 4;) than i have a problem because "Stud B"already has a Group_ID and i will not insert new ID for it, which will make my group less than 5.
I have added comments in code.
Any suggestions are welcome.
Please no database suggestions, unless you have some code to solve the problem.
Posted
Updated 14-Oct-13 10:23am
v3
Comments
Sergey Alexandrovich Kryukov 14-Oct-13 13:06pm    
You probably need to start with ultimate goal of all this activity. Do you want to create a group which are optimized according to student's personal preferences? Then you should formulate exact criteria for that. In practice, this problem may have no acceptable solutions.
—SA
Mubshir 14-Oct-13 13:13pm    
Well, this activity is actually a project i am trying to implement, for my school. I had formulated the criteria before, which was something like this: Find two sided preferences (a prefers b and b prefers a) and add them to group. Than one sided and than create groups for students without preferences, and if any groups need changing than edit groups manually using the forms in application. It was difficult to implement, so i end up doing this.
Sergey Alexandrovich Kryukov 14-Oct-13 13:20pm    
These are incomplete criteria. You can have the set of data with contradicting preferences, so what should be done in such cases? One simple case: no preferences at all. You did not describe how to form groups in this case. Another example: you can have reciprocal preferences A-B, C-D and E-F and no more. You can put all 6 in one group, three pairs in separate groups, one pair in one group and two pairs in a separate groups, etc.

Generally, the consistency of such complex criteria is something which needs a formal proof.
—SA
Mubshir 14-Oct-13 13:32pm    
I am just starting to group from top row working towards last row, so in cases of contradicting preferences, first come first serve, so whoever is in top that will win(this is not an issue). This is why in my code i have implemented a function, which checks if student already has a group_id or not, if there is already a gorup_id than i skip that student.(Which is causing me a problem for maintaining 5-8 students/group rule in my code)
In case, there are no preferences than what there can be couple of things which can be done. I can first create groups of students where there are preferences and create there groups. Than use the students without preferences to fill up either existing groups (5-8) or create random groups, but i can't figure out how can i achieve this.
Sergey Alexandrovich Kryukov 14-Oct-13 14:04pm    
You can achieve this by starting with strict and formal description of the criteria we discussed. It will be about a half of the solution.
—SA

1 solution

I understand your code as such:
C#
groupId = FirstGroupId();
foreach (row in studentsTable)
{
  if (row.Matches(predicate))
  {
     foreach (related in row.RelatedFrom(studentsTable))
     {
         related.SetGroupId(groupId);
     }
     groupId = NextGroupId();
  }
}

You might need to adjust as follows:
C#
// Group students that are related.
// Greedy approach: the first one found that fulfils the predicate (e.g. more than three relations)
// grabs its relations into one group.
// Already grouped students are not regrouped.
// The remaining students are grouped into arbirtary sized groups as given by the NeedsNewGroup() predicate.
groupId = FirstGroupId();
foreach (row in studentsTable)
{
   if (not row.IsGroupIdSet())
   {
      if (row.Matches(predicate))
      {
         row.SetGroupId(groupId);
         foreach (related in row.RelatedFrom(studentsTable))
         {
            related.SetGroupId(groupId);
         }
         groupId = NextGroupId();
      }
   }
}
count = 0;
forwach (row in studentTable where not row.IsGroupIsSet())
{
    if (NeedsNewGroup(groupId, count))
    {
        groupId = NextGroupId();
    }
    count++;
    row.SetGroupId(groupId);
}


HTH
Andi

PS: I don't see in your code where you decide on the group size. You just select based on the number of references.
 
Share this answer
 
v3
Comments
Mubshir 14-Oct-13 23:29pm    
Thanks Andi. I am actually checking if there are values in 5 or more columns than this is the minimum number required for group in CheckValueNumber() which returns true if size is 5 or more. But my logic there has flaws because when i am checking i check for :
for (int i = 0; i < record.FieldCount; i++)
{
if (string.IsNullOrWhiteSpace(record[i].ToString()) == false)
{
count++;
}
}
return count >= 5;
}
but i am also counting values which are processed before already. Thanks

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900