#100DaysOfCode - Day 44: Friends don't let friends write Algorithms late at night!

#100DaysOfCode - Day 44: Friends don't let friends write Algorithms late at night!

7 mins

Yesterday, a bug was reported with my Secret Santa application, where we had mistakenly assigned two people to the same person for Secret Santa. The brunt of the application was written through-out a day, in a new back-end framework based in C#/.NET called Blazor Server. It’s a great technology and I’m super glad I picked it, but the fact that it was something new made it (just slightly) more complex (but also very interesting). I hadn’t done an authentication application in C#/.NET, so it’s ultimately that authentication/login piece that made the application take a bit longer to create than I’d expected.

Overall, I got the brunt of the application done by about 1 AM (on a weekday, unfortunately), but I still had the algorithm left to assign people their anonymous “Secret Santas”.

It didn’t seem like a particularly hard task, but the fact that we needed to disallow specific individuals (couples) from having eachother had made it a bit tough. That, and well, it’s not exactly an easy task to begin with. At the end, I wound up with this embarassment of an “algorithm”, ran it successfully (atleast it seemed to be at 2 AM) on an empty database, and pushed to production to run it, then disabled the call to this function.

Currently, I haven’t logged onto my personal computer to retest it, but it seems that this algorithm DEFINITELY fails when it’s running on an already assigned users in the database. My hunch is that I accidentally ran it twice in production, but I’ll need to follow-up on this post to confirm :smiley:

public void PointSecretSantas()
{
		var users = new List<User>();
		var usedUsers = new List<int>();
		var rand = new Random();
		using (var c = new SecretSantaContext(new DbContextOptions<SecretSantaContext>()))
		{
				Console.WriteLine("Starting the Secret Santa Selection");
				users = c.Users.ToList();

				var couple1 = users.Where(u => (u.UserId == 50 || u.UserId == 53)).ToList();
				Console.WriteLine(couple1.Count);
				var couple2 = users.Where(u => (u.UserId == 57 || u.UserId == 60)).ToList();
				Console.WriteLine(couple2.Count);
				var couple3 = users.Where(u => (u.UserId == 51 || u.UserId == 52)).ToList();
				Console.WriteLine(couple3.Count);

				// Couple 1
				while (new[]{-1,0,50,53}.Any(x => x == couple1[0].RecipientId)
								|| usedUsers.Any(x=> x == couple1[0].RecipientId))
				{
						if (couple1[0].RecipientId == 0)
								couple1[0].RecipientId = rand.Next(50, 61);
				}
				usedUsers.Add(couple1[0].RecipientId);
				while (new List<int>(){-1,0,50,53}.Any(x => x == couple1[1].RecipientId)
								|| usedUsers.Any(x=> x == couple1[1].RecipientId))
				{
						if (couple1[1].RecipientId == 0)
								couple1[1].RecipientId = rand.Next(50, 61);
				}
				usedUsers.Add(couple1[1].RecipientId);

				
				// Couple 2
				while (new[]{-1,0,57,60}.Any(x => x == couple2[0].RecipientId)
								|| usedUsers.Any(x=> x == couple2[0].RecipientId))
				{
						if (couple2[0].RecipientId == 0)
								couple2[0].RecipientId = rand.Next(50, 61);
				}
				usedUsers.Add(couple2[0].RecipientId);

				while (new[]{-1,0,57,60}.Any(x => x == couple2[1].RecipientId) 
								|| usedUsers.Any(x=> x == couple2[1].RecipientId))
				{
						if (couple2[1].RecipientId == 0)
								couple2[1].RecipientId = rand.Next(50, 61);
				}
				usedUsers.Add(couple2[1].RecipientId);

				
				// Couple 3
				while (new[]{-1,0,51,52}.Any(x => x == couple3[0].RecipientId)
								&& usedUsers.Any(x=> x == couple3[0].RecipientId))
				{
						if (couple3[0].RecipientId == 0)
								couple3[0].RecipientId = rand.Next(50, 61);
				}
				usedUsers.Add(couple3[0].RecipientId);

				while (new[]{-1,0,51,52}.Any(x => x == couple3[1].RecipientId)
								&& usedUsers.Any(x=> x == couple3[1].RecipientId))
				{
						if (couple3[1].RecipientId == 0)
								couple3[1].RecipientId = rand.Next(50, 61);
				}
				usedUsers.Add(couple3[1].RecipientId);


				var singleUsersLeft = c.Users.Where(u => u.RecipientId == 0);
				Console.WriteLine("Single users left");
				foreach (var user in singleUsersLeft)
				{
						while (new[] {-1, 0}.Any(x => x == user.RecipientId)
										&& usedUsers.Any(x => x == user.RecipientId))
						{
								if (user.RecipientId == 0)
										user.RecipientId = rand.Next(50, 61);
						}
				}

				// 50 != 53
				// 57 != 60
				// 51 != 52
				Console.WriteLine(users.Count);
				Console.WriteLine(users[0].Email);

				Console.WriteLine("End Results");
				foreach (var user in users)
				{
						Console.WriteLine(user.UserId + " " + user.RecipientId + " " + user.Email);
				}

				c.SaveChanges();
		}
}

At the end, I’m definitely very disappointed in that I messed up Secret Santa, but ultimately we were able to resolve the issues and have everyone receiving presents this year. So, we can consider this a growing pain of sorts, and make SURE that we don’t have the same issue next year (Ann-Marie, my wife, has offered to QA the final product / assignments, without knowing who the “people” are of course).

Happy coding!

~ Moxnr

Written on December 5, 2020