<commit_before>function UserList(){
	this.users = {};
}

UserList.prototype = new EventEmitter();

UserList.prototype.newMessage = function(msg){
	var a = msg.action,
	me = this;
	
	if(a == "join"){
		$.extend(me.users, msg.users);
		me.emit('join', msg.users);
		
	} else if(a == "part"){
		var users = me.users;
		$.each(msg.users, function(id, user){if(users[id]) delete users[id]});
		me.emit('part', msg.users);
		
	} else if(a == "who"){
		me.users = msg.users || {};
		me.emit('who', me.users);
		
	} else if(a == "batch"){
		$.each(msg.messages, function(msg){
			me.newMessage(msg);
		});
	}
}

// iteration must halt when f returns false
UserList.prototype.each = function(f){
	$.each(this.users,f);	
}

function UserListUI(ul, container){
	if(!ul) return;
	var user_divs = {},
	sorted = [];
	
	ul.on('join', function(users){
		var names=[];
		$.each(users, function(id, user){
			user.id = id;
			addUser(user);
			names.push(user.name);
		});
		updateUserCount();
	});

	ul.on('part', function(users){
		var names=[];
		$.each(users, function(id, user){
			user.id = id;
			removeUser(user);
			names.push(user.name);
		});
		updateUserCount();
	});
	
	ul.on('who', function(users){
		clearUserList();
		$.each(users, function(id, user){
			user.id = id;
			addUser(user);
		});
		updateUserCount();
	});
	
	function addUser(user){
		if(user_divs[user.id]) return;
		
		var name_div = user.el = $('<a>');
		name_div.attr({
			id:'user_' + user.id,
			title: user.name,
			href: '/users/' + user.id,
			target: "_blank",
			style: 'color:' + UI.Colors.forUser(user.id) + ';',
			'class': 'user'
		});
		name_div.text(user.name);

		var insert_after = addToSortedList(user);
		if(insert_after)
			insert_after.el.after(name_div);
		else
			container.prepend(name_div);
		user_divs[user.id] = name_div;
	}
	
	function addToSortedList(user){
		sorted.push(user);
		sorted.sort(function(a,b){
			return a.name.localeCompare(b.name);
		});
		var i=sorted.indexOf(user);
		return i > 0 ? sorted[i-1] : null;
	}
	
	function removeUser(user){
		if(user_divs[user.id]){
			user_divs[user.id].remove();
			sorted = sorted.filter(function(each){
				return user.id != each.id;
			});
			delete user_divs[user.id];
		}
	}
	
	function clearUserList(){
		for(var i in user_divs){
			user_divs[i].remove();
		}
		user_divs = {};
		sorted = [];
	}
	
	function updateUserCount(){
		$('#user_count').text('(' + sorted.length + ')');
	}
}
<commit_msg>Add client-side js to deal with anonymous users in the userlist<commit_after>function UserList(){
	this.users = {};
}

UserList.prototype = new EventEmitter();

UserList.prototype.newMessage = function(msg){
	var a = msg.action,
	me = this;
	
	if(a == "join"){
		$.extend(me.users, msg.users);
		me.emit('join', msg.users);
		
	} else if(a == "part"){
		var users = me.users;
		$.each(msg.users, function(id, user){if(users[id]) delete users[id]});
		me.emit('part', msg.users);
		
	} else if(a == "who"){
		me.users = msg.users || {};
		me.emit('who', me.users);
		
	} else if(a == "batch"){
		$.each(msg.messages, function(msg){
			me.newMessage(msg);
		});
	}
}

// iteration must halt when f returns false
UserList.prototype.each = function(f){
	$.each(this.users,f);	
}

function UserListUI(ul, container, top){
	if(!ul) return;
	var user_divs = {},
	// Single Anonymous user for the userlist
	anonymous = {el: null, count:0},
	sorted = [];
	
	ul.on('join', function(users){
		$.each(users, function(id, user){
			user.id = id;
			addUser(user);
		});
		updateUserCount();
	});

	ul.on('part', function(users){
		$.each(users, function(id, user){
			user.id = id;
			if(id == 'anonymous')
				removeAnonymous(user);
			else
				removeUser(user);
		});
		updateUserCount();
	});
	
	ul.on('who', function(users){
		clearUserList();
		$.each(users, function(id, user){
			user.id = id;
			addUser(user);
		});
		updateUserCount();
	});
	
	function addUser(user){
		if(user.id == 'anonymous') return addAnonymous(user);
		
		if(user_divs[user.id]) return;
		
		var name_div = user.el = $('<a>');
		name_div.attr({
			id:'user_' + user.id,
			title: user.name,
			href: '/users/' + user.id,
			target: "_blank",
			style: 'color:' + UI.Colors.forUser(user.id) + ';',
			'class': 'user'
		});
		name_div.text(user.name);

		var insert_after = addToSortedList(user);
		if(insert_after)
			insert_after.el.after(name_div);
		else
			container.prepend(name_div);
		user_divs[user.id] = name_div;
	}
	
	function addAnonymous(user){
		var a = anonymous;
		if(!a.el){
			a.el = $('<div>');
			a.id = user.id;
			user_divs[a.id] = a.el;
			a.el.attr({
				'class': 'user anon'
			});
			a.count = 0;
			top.prepend(a.el);
		}
		
		a.count += user.count;
		
		a.el.text("Anonymous ("+ a.count +")");
	}
	
	function removeAnonymous(user){
		var a = anonymous;
		if(!a.el) return;

		a.count -= user.count;
	
		if(a.count <= 0){
			removeUser(a);
			a.el = null;
			a.count = 0;
		}else{
			a.el.text("Anonymous ("+ a.count +")");
		}
	}
	
	function addToSortedList(user){
		sorted.push(user);
		sorted.sort(function(a,b){
			return a.name.localeCompare(b.name);
		});
		var i=sorted.indexOf(user);
		return i > 0 ? sorted[i-1] : null;
	}
	
	function removeUser(user){
		if(user_divs[user.id]){
			user_divs[user.id].remove();
			sorted = sorted.filter(function(each){
				return user.id != each.id;
			});
			delete user_divs[user.id];
		}
	}
	
	function clearUserList(){
		for(var i in user_divs){
			user_divs[i].remove();
		}
		anonymous.el = null;
		user_divs = {};
		sorted = [];
	}
	
	function updateUserCount(){
		$('#user_count').text('(' + (sorted.length + anonymous.count) + ')');
	}
}

{'fraction_non_alphanumeric': 0.19968022739385327, 'fraction_numerical': 0.0014212115828744004, 'mean_word_length': 3.4295830055074745, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6586886', 'n_tokens_mistral': 2481, 'n_tokens_neox': 2175, 'n_words': 402}