From 7cac59f3ec12e3440341bb561ab3c8e6c3fe80e0 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 22 Oct 2010 17:26:11 +0100
Subject: Be smarter about combining JoinParts in MUCs.

Resolves: 620
Release-Notes: Joins and parts in MUCs will now be merged in a more natural way.

diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 8b9f3fa..ff102e7 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -382,7 +382,7 @@ void MUCController::appendToJoinParts(std::vector<NickJoinPart>& joinParts, cons
 	}
 }
 
-String MUCController::generateJoinPartString(std::vector<NickJoinPart> joinParts) {
+String MUCController::concatenateListOfNames(const std::vector<NickJoinPart>& joinParts) {
 	String result;
 	for (size_t i = 0; i < joinParts.size(); i++) {
 		if (i > 0) {
@@ -394,15 +394,43 @@ String MUCController::generateJoinPartString(std::vector<NickJoinPart> joinParts
 		}
 		NickJoinPart event = joinParts[i];
 		result += event.nick;
-		switch (event.type) {
-			case Join: result += " has joined";break;
-			case Part: result += " has left";break;
-			case JoinThenPart: result += " joined then left";break;
-			case PartThenJoin: result += " left then rejoined";break;
+	}
+	return result;
+}
+
+String MUCController::generateJoinPartString(const std::vector<NickJoinPart>& joinParts) {
+	std::vector<NickJoinPart> sorted[4];
+	String eventStrings[4];
+	foreach (NickJoinPart event, joinParts) {
+		sorted[event.type].push_back(event);
+	}
+	String result;
+	std::vector<JoinPart> populatedEvents;
+	for (size_t i = 0; i < 4; i++) {
+		String eventString = concatenateListOfNames(sorted[i]);
+		if (!eventString.isEmpty()) {
+			String haveHas = sorted[i].size() > 1 ? " have" : " has";
+			switch (i) {
+				case Join: eventString += haveHas + " joined";break;
+				case Part: eventString += haveHas + " left";break;
+				case JoinThenPart: eventString += " joined then left";break;
+				case PartThenJoin: eventString += " left then rejoined";break;
+			}
+			populatedEvents.push_back(static_cast<JoinPart>(i));
+			eventStrings[i] = eventString;
+		}
+	}
+	for (size_t i = 0; i < populatedEvents.size(); i++) {
+		if (i > 0) {
+			if (i < populatedEvents.size() - 1) {
+				result += ", ";
+			} else {
+				result += " and ";
+			}
 		}
-		result += " the room";
+		result += eventStrings[populatedEvents[i]];
 	}
-	result += ".";
+	result += " the room.";
 	return result;
 }
 
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 6924b48..2a6536c 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -47,7 +47,8 @@ namespace Swift {
 			virtual void setOnline(bool online);
 			void rejoin();
 			static void appendToJoinParts(std::vector<NickJoinPart>& joinParts, const NickJoinPart& newEvent);
-			static String generateJoinPartString(std::vector<NickJoinPart> joinParts);
+			static String generateJoinPartString(const std::vector<NickJoinPart>& joinParts);
+			static String concatenateListOfNames(const std::vector<NickJoinPart>& joinParts);
 		
 		protected:
 			void preSendMessageRequest(boost::shared_ptr<Message> message);
@@ -77,6 +78,7 @@ namespace Swift {
 			bool shouldUpdateJoinParts();
 			void dayTicked() {lastWasPresence_ = false;}
 			void processUserPart();
+
 		private:
 			MUC* muc_;
 			UIEventStream* events_;
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index aeae562..19e5c36 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -179,11 +179,11 @@ public:
 		list.push_back(NickJoinPart("Kev", Join));
 		CPPUNIT_ASSERT_EQUAL(String("Kev has joined the room."), MUCController::generateJoinPartString(list));
 		list.push_back(NickJoinPart("Remko", Part));
-		CPPUNIT_ASSERT_EQUAL(String("Kev has joined the room and Remko has left the room."), MUCController::generateJoinPartString(list));
+		CPPUNIT_ASSERT_EQUAL(String("Kev has joined and Remko has left the room."), MUCController::generateJoinPartString(list));
 		list.push_back(NickJoinPart("Bert", Join));
-		CPPUNIT_ASSERT_EQUAL(String("Kev has joined the room, Remko has left the room and Bert has joined the room."), MUCController::generateJoinPartString(list));
+		CPPUNIT_ASSERT_EQUAL(String("Kev and Bert have joined and Remko has left the room."), MUCController::generateJoinPartString(list));
 		list.push_back(NickJoinPart("Ernie", Join));
-		CPPUNIT_ASSERT_EQUAL(String("Kev has joined the room, Remko has left the room, Bert has joined the room and Ernie has joined the room."), MUCController::generateJoinPartString(list));
+		CPPUNIT_ASSERT_EQUAL(String("Kev, Bert and Ernie have joined and Remko has left the room."), MUCController::generateJoinPartString(list));
 	}
 
 	void testJoinPartStringContructionMixed() {
@@ -191,11 +191,11 @@ public:
 		list.push_back(NickJoinPart("Kev", JoinThenPart));
 		CPPUNIT_ASSERT_EQUAL(String("Kev joined then left the room."), MUCController::generateJoinPartString(list));
 		list.push_back(NickJoinPart("Remko", Part));
-		CPPUNIT_ASSERT_EQUAL(String("Kev joined then left the room and Remko has left the room."), MUCController::generateJoinPartString(list));
+		CPPUNIT_ASSERT_EQUAL(String("Remko has left and Kev joined then left the room."), MUCController::generateJoinPartString(list));
 		list.push_back(NickJoinPart("Bert", PartThenJoin));
-		CPPUNIT_ASSERT_EQUAL(String("Kev joined then left the room, Remko has left the room and Bert left then rejoined the room."), MUCController::generateJoinPartString(list));
+		CPPUNIT_ASSERT_EQUAL(String("Remko has left, Kev joined then left and Bert left then rejoined the room."), MUCController::generateJoinPartString(list));
 		list.push_back(NickJoinPart("Ernie", JoinThenPart));
-		CPPUNIT_ASSERT_EQUAL(String("Kev joined then left the room, Remko has left the room, Bert left then rejoined the room and Ernie joined then left the room."), MUCController::generateJoinPartString(list));
+		CPPUNIT_ASSERT_EQUAL(String("Remko has left, Kev and Ernie joined then left and Bert left then rejoined the room."), MUCController::generateJoinPartString(list));
 	}
 
 private:
-- 
cgit v0.10.2-6-g49f6