Index: ps/trunk/binaries/data/config/default.cfg =================================================================== --- ps/trunk/binaries/data/config/default.cfg +++ ps/trunk/binaries/data/config/default.cfg @@ -377,6 +377,9 @@ xpartamupp = "wfgbot22" ; Name of the server-side xmpp client that manage games buddies = "," ; Comma separated list of playernames that the current user has marked as buddies +[lobby.columns] +gamerating = false ; Show the average rating of the participating players in a column of the gamelist + [mod] enabledmods = "mod public" Index: ps/trunk/binaries/data/mods/public/gui/common/functions_utility.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/common/functions_utility.js +++ ps/trunk/binaries/data/mods/public/gui/common/functions_utility.js @@ -158,15 +158,6 @@ return Engine.ConfigDB_GetValue("user", "playername.multiplayer") || Engine.GetSystemUsername(); } -/** - * Returns the nickname without the lobby rating. - */ -function removeRatingFromNick(playerName) -{ - let result = /^(\S+)\ \(\d+\)$/g.exec(playerName); - return result ? result[1] : playerName; -} - function tryAutoComplete(text, autoCompleteList) { if (!text.length) Index: ps/trunk/binaries/data/mods/public/gui/common/gamedescription.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/common/gamedescription.js +++ ps/trunk/binaries/data/mods/public/gui/common/gamedescription.js @@ -4,11 +4,30 @@ var g_DescriptionHighlight = "orange"; /** + * The rating assigned to lobby players who didn't complete a ranked 1v1 yet. + */ +var g_DefaultLobbyRating = 1200; + +/** * XEP-0172 doesn't restrict nicknames, but our lobby policy does. * So use this human readable delimiter to separate buddy names in the config file. */ var g_BuddyListDelimiter = ","; + +/** + * Returns the nickname without the lobby rating. + */ +function splitRatingFromNick(playerName) +{ + let result = /^(\S+)\ \((\d+)\)$/g.exec(playerName); + + if (!result) + return [playerName, g_DefaultLobbyRating]; + + return [result[1], +result[2]]; +} + /** * Array of playernames that the current user has marked as buddies. */ @@ -140,7 +159,7 @@ (isAI ? "white" : getPlayerColor(playerData.Name)) : rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color)) + '"]' + - (g_Buddies.indexOf(removeRatingFromNick(playerData.Name)) != -1 ? g_BuddySymbol + " " : "") + + (g_Buddies.indexOf(splitRatingFromNick(playerData.Name)[0]) != -1 ? g_BuddySymbol + " " : "") + escapeText(playerData.Name) + "[/color]", Index: ps/trunk/binaries/data/mods/public/gui/lobby/lobby.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/lobby/lobby.js +++ ps/trunk/binaries/data/mods/public/gui/lobby/lobby.js @@ -360,10 +360,34 @@ Engine.LobbyClearPresenceUpdates(); updatePlayerList(); updateSubject(Engine.LobbyGetRoomSubject()); + updateLobbyColumns(); Engine.GetGUIObjectByName("chatInput").tooltip = colorizeAutocompleteHotkey(); } +function updateLobbyColumns() +{ + let gameRating = Engine.ConfigDB_GetValue("user", "lobby.columns.gamerating") == "true"; + + // Only show the selected columns + let gamesBox = Engine.GetGUIObjectByName("gamesBox"); + gamesBox.hidden_mapType = gameRating; + gamesBox.hidden_gameRating = !gameRating; + + // Only show the filters of selected columns + let mapTypeFilter = Engine.GetGUIObjectByName("mapTypeFilter"); + mapTypeFilter.hidden = gameRating; + let gameRatingFilter = Engine.GetGUIObjectByName("gameRatingFilter"); + gameRatingFilter.hidden = !gameRating; + + // Keep filters right above the according column + let playersNumberFilter = Engine.GetGUIObjectByName("playersNumberFilter"); + let size = playersNumberFilter.size; + size.rleft = gameRating ? 74: 90; + size.rright = gameRating ? 84: 100; + playersNumberFilter.size = size; +} + function returnToMainMenu() { Engine.StopXmppClient(); @@ -385,6 +409,20 @@ mapTypeFilter.list = [translateWithContext("map", "Any")].concat(g_MapTypes.Title); mapTypeFilter.list_data = [""].concat(g_MapTypes.Name); + let gameRatingOptions = ["<1000", "<1100","<1200",">1200",">1300",">1400",">1500"].reverse(); + gameRatingOptions = prepareForDropdown(gameRatingOptions.map(r => ({ + "value": r, + "label": sprintf( + r[0] == ">" ? + translateWithContext("gamelist filter", "> %(rating)s") : + translateWithContext("gamelist filter", "< %(rating)s"), + { "rating": r.substr(1) }) + }))) + + let gameRatingFilter = Engine.GetGUIObjectByName("gameRatingFilter"); + gameRatingFilter.list = [translateWithContext("map", "Any")].concat(gameRatingOptions.label); + gameRatingFilter.list_data = [""].concat(gameRatingOptions.value); + resetFilters(); } @@ -393,6 +431,7 @@ Engine.GetGUIObjectByName("mapSizeFilter").selected = 0; Engine.GetGUIObjectByName("playersNumberFilter").selected = 0; Engine.GetGUIObjectByName("mapTypeFilter").selected = g_MapTypes.Default; + Engine.GetGUIObjectByName("gameRatingFilter").selected = 0; Engine.GetGUIObjectByName("showFullFilter").checked = false; applyFilters(); @@ -415,6 +454,7 @@ let mapSizeFilter = Engine.GetGUIObjectByName("mapSizeFilter"); let playersNumberFilter = Engine.GetGUIObjectByName("playersNumberFilter"); let mapTypeFilter = Engine.GetGUIObjectByName("mapTypeFilter"); + let gameRatingFilter = Engine.GetGUIObjectByName("gameRatingFilter"); let showFullFilter = Engine.GetGUIObjectByName("showFullFilter"); // We assume index 0 means display all for any given filter. @@ -433,6 +473,14 @@ if (!showFullFilter.checked && game.maxnbp <= game.nbp) return true; + if (gameRatingFilter.selected > 0) + { + let selected = gameRatingFilter.list_data[gameRatingFilter.selected]; + if (selected.startsWith(">") && +selected.substr(1) >= game.gameRating || + selected.startsWith("<") && +selected.substr(1) <= game.gameRating) + return true; + } + return false; } @@ -630,7 +678,7 @@ for (let i = 0; i < g_GameList.length; ++i) for (let player of stringifiedTeamListToPlayerData(g_GameList[i].players)) { - let nick = removeRatingFromNick(player.Name); + let [nick, rating] = splitRatingFromNick(player.Name); if (playerName != nick) continue; @@ -810,15 +858,28 @@ } g_GameList = Engine.GetGameList().map(game => { + game.hasBuddies = 0; + + // Compute average rating of participating players + let playerRatings = []; + for (let player of stringifiedTeamListToPlayerData(game.players)) { - let nick = removeRatingFromNick(player.Name); + let [nick, rating] = splitRatingFromNick(player.Name); + + if (player.Team != "observer") + playerRatings.push(rating); // Sort games with playing buddies above games with spectating buddies if (game.hasBuddies < 2 && g_Buddies.indexOf(nick) != -1) game.hasBuddies = player.Team == "observer" ? 1 : 2; } + game.gameRating = + playerRatings.length ? + Math.round(playerRatings.reduce((sum, current) => sum + current) / playerRatings.length) : + g_DefaultLobbyRating; + return game; }).filter(game => !filterGame(game)).sort((a, b) => { let sortA, sortB; @@ -828,6 +889,7 @@ sortA = g_GameStatusOrder.indexOf(a.state) + a.name.toLowerCase(); sortB = g_GameStatusOrder.indexOf(b.state) + b.name.toLowerCase(); break; + case 'gameRating': case 'mapSize': case 'mapType': sortA = a[sortBy]; @@ -857,6 +919,7 @@ let list_mapSize = []; let list_mapType = []; let list_nPlayers = []; + let list_gameRating = []; let list = []; let list_data = []; let selectedGameIndex = -1; @@ -876,6 +939,7 @@ list_mapSize.push(translateMapSize(game.mapSize)); list_mapType.push(g_MapTypes.Title[mapTypeIdx] || ""); list_nPlayers.push(game.nbp + "/" + game.maxnbp); + list_gameRating.push(game.gameRating); list.push(gameName); list_data.push(i); } @@ -886,6 +950,8 @@ gamesBox.list_mapSize = list_mapSize; gamesBox.list_mapType = list_mapType; gamesBox.list_nPlayers = list_nPlayers; + gamesBox.list_gameRating = list_gameRating; + // Change these last, otherwise crash gamesBox.list = list; gamesBox.list_data = list_data; Index: ps/trunk/binaries/data/mods/public/gui/lobby/lobby.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/lobby/lobby.xml +++ ps/trunk/binaries/data/mods/public/gui/lobby/lobby.xml @@ -204,7 +204,7 @@ applyFilters(); joinButton(); - + Name @@ -216,16 +216,20 @@ Type - + Players + + Rating + + applyFilters(); @@ -233,7 +237,7 @@ applyFilters(); @@ -241,7 +245,15 @@ + applyFilters(); + + + applyFilters(); Index: ps/trunk/binaries/data/mods/public/gui/options/options.json =================================================================== --- ps/trunk/binaries/data/mods/public/gui/options/options.json +++ ps/trunk/binaries/data/mods/public/gui/options/options.json @@ -269,6 +269,12 @@ "label": "Chat Backlog", "tooltip": "Number of backlogged messages to load when joining the lobby", "parameters": { "config": "lobby.history", "min": "0" } + }, + { + "type": "boolean", + "label": "Game Rating Column", + "tooltip": "Show the average rating of the participating players in a column of the gamelist.", + "parameters": { "config": "lobby.columns.gamerating" } } ], "notificationSetting":