Premade Groups Filter

Premade Groups Filter

9M Downloads

[Feature Request] Filter dungeons by personal rating

Thamakil opened this issue · 16 comments

commented

It would be great if we could filter dungeons based on our own rating.

Let's say for the current affix (fortified or tyrannical) I already have a good rating in Plaguefall, De Other Side, and Halls of Atonement, so I just want to do the other dungeons.
Currently I can achieve this by setting a filter like '... and not (pf or dos or hoa)'.
Then after I successfully completed a Mists of Tirna Scithe, I have to adjust my filter for the next search and add 'mots' to the list of excluded dungeons.
So I have to adjust my filter after each run and of course redo everything every week after the affix changed.

It would be nicer to be able to set a filter once such as: '... and myrating < 250'.
Now only dungeons for which I have a rating below 125 in the current affix (total rating divided by 2 affixes) will be shown to me.
This way, the list of dungeons displayed automatically adjusts when my ratings or the affixes change.

It is somewhat similar to the change request #75 but without the need to look at key levels and therefore making this doable in my opinion.
I could set the filter proposed by me here (myrating < 250) and combine that with entering something like +15 in the standard ui search field and that would basically give me something that comes close enough to "show me all offered keys that will improve my rating".

commented

I decided to do the matching manually by providing a map from challenge mode mapID to activityID. This means more for when a new mythic plus dungeon is added, but that does not happen too often. Also, I changed the code so that the rating is only calculated one per search instead of 50 times for each seach result.

I still implemented your suggestion for IsMostLikelySameInstance for the lockout matching.

Please have another test. I also did run a mythic plus dungeon meanwhile and could fix some more bugs with the mean and median ratings.

commented

Got a lua exception when testing the code.
Wrote a comment directly here (hope that was correct, I am not so familiar in working with github).

commented

Plesae have a look at the code. It would be great if one of you could check the branch out and test the code.

commented

Oh yes that's fine. I fixed the nil pointer exception, please have another try.

commented

I already suspected that, thank you for investigating. I really hate Blizzard for Tazavesh: Wundersame Straßen vs. Tazavesh: Straßen (Mythischer Schlüsselstein). Also I was not aware that %w (represents all alphanumeric characters) does not match Umlaute. I assume I never had a problem because the function was previously only used for matching lockout information and raids only have German suffixes Normal, Heroisch, Mythisch without Umlaute. But I might have broken some other languages. We also should have another look at languages using logograms like Chinese, I found that they are sometimes using different braces. Also it might not always be the case that the difficulty is at the end of the string and/or in braces.

I will think about your solution for IsMostLikelySameInstance and I will also have another look if there is any way to get the dungeon name from the activity info.

commented

Seems to be working with one exception: the new Tazavesh dungeons.
My current ratings for those are as follows:

Dump: value=C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(391) --Tazavesh: Streets of Wonder
[1]={
  [1]={
    name="Tyrannical",
    overTime=true,
    level=12,
    durationSec=3038,
    score=101
  },
  [2]={
    name="Fortified",
    overTime=true,
    level=11,
    durationSec=2727,
    score=98
  }
},
[2]=201
Dump: value=C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(392) --Tazavesh: So'leah's Gambit
[1]={
  [1]={
    name="Fortified",
    overTime=true,
    level=11,
    durationSec=2565,
    score=0
  }
},
[2]=0

When setting the filter to myaffixrating < 10 I should only see Gambit but i do see both (Gambit and Streets).

commented

I did the last tests with the WoW client set to english language.
Now I switched to german and there we seem to have more problems.
As far as I can see the problem lies in your PGF.IsMostLikelySameInstance(instanceName, activityName) function.
I have added the following line to get some debug output:
print(instanceName.. " == " .. activityName .. " ? " .. tostring(PGF.IsMostLikelySameInstance(instanceName, activityName)))
And here are some results where it does not seem to work correctly:

Die Blutigen Tiefen == Blutige Tiefen (Mythischer Schlüsselstein) ? false
Tazavesh: Wundersame Straßen == Tazavesh: Straßen (Mythischer Schlüsselstein) ? false
Die Nekrotische Schneise == Nekrotische Schneise (Mythischer Schlüsselstein) ? false
Tazavesh: So'leahs Schachzug == Tazavesh: Schachzug (Mythischer Schlüsselstein) ? false

I hope that helps you.

commented

Possible fix for the IsMostLikelySameInstance function:

function PGF.IsMostLikelySameInstance(instanceName, activityName)
    -- instanceName is just the dungeon's name used in the lockout and challenge mode APIs, e.g. 'The Emerald Nightmare'
    local instanceNameLower = instanceName:lower()
    -- activityName has the difficulty in parens at the end, e.g. 'Emerald Nightmare (Heroic)'
    local activityNameWithoutDifficulty = string.gsub(activityName, "%s%([^()]+%)", ""):lower()
	
	for token in string.gmatch(activityNameWithoutDifficulty, "[^%s]+") do
		if not string.find(instanceNameLower, token) then return false end
	end
	
	return true
end

Note the change in how the activityNameWithoutDifficulty is created.
With your pattern (%w+) %(%w+%) it did not work because %w seems not be matching the ü in the german word Schlüsselstein.
The other change I made is that I do not try to find the whole activityNameWithoutDifficulty sting inside instanceNameLower but instead split it up and check it word by word.
If one of the words from activityNameWithoutDifficulty is missing in instanceNameLower then I return false.
If all words are found the function returns true.
This way also Sanguine Depths in german are working:
Die Blutigen Tiefen == Blutige Tiefen (Mythischer Schlüsselstein) ? true

commented

IsMostLikelySameInstance currently always returns false :)
But apart from that everything seems to be working fine.

commented

It will be a huge work to collect all different score for each key level.

OJNYMB19UL2MESCFPO`}V

What I do for now, is to right click the refresh button to open a dropdown menu, which can filter specific dungeon I need.

commented

The dropdown menu comes from another addon, this is not default behavior.

As I currently do not have a M+ rating on any char, could someone help me with and get the result of the following commands? Just enter them in the char window and take a screenshot or copy them if you have an addon that allows that.

/dump C_ChallengeMode.GetMapScoreInfo()
/dump C_MythicPlus.GetSeasonBestForMap(375)
/dump C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(375)

If you do not have a rating on that dungeon, you may also use 375-382, 391, 392.
Depending on the values returned from these functions, we can see if we can add the requested feature.

commented

I meant I create that dropdown myself. Anyway here are the dump.

Dump: value=C_ChallengeMode.GetMapScoreInfo()
[1]={
  [1]={
    name="",
    level=16,
    mapChallengeModeID=375,
    completedInTime=1,
    dungeonScore=132
  },
  [2]={
    name="",
    level=17,
    mapChallengeModeID=376,
    completedInTime=1,
    dungeonScore=136
  },
  [3]={
    name="",
    level=17,
    mapChallengeModeID=377,
    completedInTime=0,
    dungeonScore=130
  },
  [4]={
    name="",
    level=16,
    mapChallengeModeID=378,
    completedInTime=1,
    dungeonScore=130
  },
  [5]={
    name="",
    level=17,
    mapChallengeModeID=379,
    completedInTime=1,
    dungeonScore=135
  },
  [6]={
    name="",
    level=0,
    mapChallengeModeID=380,
    completedInTime=0,
    dungeonScore=0
  },
  [7]={
    name="",
    level=16,
    mapChallengeModeID=381,
    completedInTime=0,
    dungeonScore=123
  },
  [8]={
    name="",
    level=16,
    mapChallengeModeID=382,
    completedInTime=1,
    dungeonScore=132
  },
  [9]={
    name="",
    level=0,
    mapChallengeModeID=391,
    completedInTime=0,
    dungeonScore=0
  },
  [10]={
    name="",
    level=17,
    mapChallengeModeID=392,
    completedInTime=0,
    dungeonScore=0
  }
}

Dump: value=C_MythicPlus.GetSeasonBestForMap(375)
[1]={
  durationSec=1580,
  completionDate={
    year=22,
    month=2,
    minute=43,
    hour=14,
    day=12
  },
  affixIDs={
    [1]=10,
    [2]=11,
    [3]=124,
    [4]=130
  },
  level=16,
  members={
    [1]={
      specID=257,
      name="Wayneway",
      classID=5
    },
    [2]={
      specID=260,
      name="Gardisra",
      classID=4
    },
    [3]={
      specID=66,
      name="羅洛菲蒙",
      classID=2
    },
    [4]={
      specID=254,
      name="寧德",
      classID=3
    },
    [5]={
      specID=63,
      name="鐘蘭珠",
      classID=8
    }
  },
  dungeonScore=132
},
[2]={
  durationSec=2139,
  completionDate={
    year=22,
    month=2,
    minute=3,
    hour=14,
    day=3
  },
  affixIDs={
    [1]=9,
    [2]=7,
    [3]=13,
    [4]=130
  },
  level=17,
  members={
    [1]={
      specID=63,
      name="鐘蘭珠",
      classID=8
    },
    [2]={
      specID=254,
      name="寧德",
      classID=3
    },
    [3]={
      specID=257,
      name="Wayneway",
      classID=5
    },
    [4]={
      specID=66,
      name="羅洛菲蒙",
      classID=2
    },
    [5]={
      specID=260,
      name="Gardisra",
      classID=4
    }
  },
  dungeonScore=128
}

Dump: value=C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(375)
[1]={
  [1]={
    name="残暴", -- tyran
    overTime=true,
    level=17,
    durationSec=2139,
    score=128
  },
  [2]={
    name="强韧", --  Forti
    overTime=false,
    level=16,
    durationSec=1580,
    score=132
  }
},
[2]=261
commented

I had already looked at these before opening the issue.
Sorry, I could have thought of including some dump into the ticket.
My Idea was basically using the data coming from C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(mapChallengeModeID).

In siweia's example we see that he has an overall rating of 261 (that is the value Blizz shows us in the standard ui) for dungeon 375 (which is Mists of Tirna Scithe).
It also shows that he has a rating of 128 for the tyrannical affix and 132 for fortified - these values are not shown to the players but could of course be used.
As you can see 128 + 132 = 260 and not 261 ... Blizz does some strange additional maths here but I think for the purpose of the proposed filter we could just take the value entered by the user and half it.
Or we let the user enter a per affix value but that would be somewhat difficult to explain as the user at least in the default ui can not see the per affix ratings.

Also consider the following dumps:

Dump: value=C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(375)
[1]={
  [1]={
    name="Verstärkt", --fortified
    overTime=false,
    level=12,
    durationSec=1564,
    score=112
  }
},
[2]=167
Dump: value=C_MythicPlus.GetSeasonBestAffixScoreInfoForMap(382)
[1]={
  [1]={
    name="Tyrannisch", --tyrannical
    overTime=true,
    level=11,
    durationSec=3113,
    score=95
  }
},
[2]=143

We can see three things here:

  • If someone has not done a dungeon entirely for one of the two affixes than the corresponding entry is missing entirely.
  • The difference between the sum of the per affix ratings and the overall rating is even bigger (e.g. 112 + 0 = 167?).
  • We probably have to look at the 'name' field to identify to which affix a rating belongs which means that unfortunately i18n might come into play here.

My idea for the proposed filter basically was if I enter myrating < 200 as a filter than in a tyrannical week it would include MoTS (375) as well as ToP (382) as my ratings are 0 and 95 wich are both lower than 100.
In a fortified week it would only include ToP (with rating 0) and not MoTS (rating of 112 > 100).

I do admit that the maths here are not entirely clean.
If siweia with his example of MoTS entered myrating < 260 as a filter the dungeon would still be shown in a tyrannical week as 128 < 130 even though his overall rating is 261.
This could be solved by also checking the overall rating before checking the per affix ratings but I think there would still be room for errors.
But in my opinion that would be tolerable - or maybe you have some better ideas how to handle that :)

commented

I do not have enough data to prove it, but it looks like the better rating out of tyrannical and fortified is multiplied with 1.5 and the worse by 0.5.

Thamakil: 112*1.5 + 0*0.5 = 168
Siweia: 132*1.5 + 128*0.5 = 262

Both numbers are off by 1, not sure why (could be a rounding issue or maybe they ceil after floating point operation).

Your base intention was to find out if a dungeon (group) could improve your rating. We can only find that indirectly if we ask to show only groups where my rating is less than some number.

I think we should take the current affix into account and provide two keywords: one for this weeks affix score and one for the combined score. And yes it gets ugly because we have to compare the i18n value. Also this means that the two numbers are very different in scale.

I'm not sure if the combined value really helps anyone, but at least that visible in the UI.

Also I'm not completely satisfied with the myaffixscore value. How do I find out what value I should compare it to? myaffixscore < 60 or myaffixscore < 120?

Maybe it makes more sense to compare it with my other scores and have something like scoreupgrade to show only dungeons where my affix score is less than the median or average of all affix scores? This would be a simple boolean keyword which is easier to handle. Of course every dungeon could improve your score if you do good enough, so maybe we just need to get clearer with the keyword. My not-yet-good ideas: scoreworsethanavg, scoreup, scoreimprovement, scorechance, scoringchance.

Or we could stick with your idea and add keywords myavgaffixscore, mymedianaffixscore, myavgscore, mymedianscore. This way you can do something like myaffixscore < myavgaffixscore

commented

Maybe I should give you some context to my suggestion.

While it's true that you can always improve your score with high enough keys, I think most people try to reach certain thresholds with the least amount of effort possible.

The most prominent example is probably the keystone master achievement, which gets you a mount.
To get this, you need a total score of 2500 points in the current season.
Since there are currently 10 dungeons, this means you need a rating of 250 per dungeon or 125 per affix per dungeon (btw: 125 * 1.5 + 125 * 0.5 = 250 so your math seems to work).

Of course, you could achieve a rating of 250 for a particular dungeon by "simply" completing it once at +24 in time, but for many players that is far beyond their capabilities, and as I said, the goal is to reach the threshold with as little effort as possible.
That means in this case completing each dungeon in each of the two affixes once at +15 in time to get a rating of at least 125.

So for this I could set the filter suggested here to myaffixscore < 125 and enter +16 in the search field of the standard UI and as a result I would only get groups displayed that are in a range I feel comfortable with (15 to 17) and where I do not yet have the necessary rating for the keystone master achievement for the currently active affix.

This filter will obviously not be very relevant for M+ Pros who do keys far beyond +20 regulary but as I said I do believe that the majority of players is perfectly fine with reaching thresholds like the keystone master oder keystone conqueror (1850 points) or keystone hero (3000 points).

Also have a look at icy-veins (especially "8. Valor Upgrade Ranks and Requirements") for other important thresholds that people might try to reach because they unlock the ability to upgrade gear to certain levels using valor points.

commented

Thanks for the heads up on IsMostLikelySameInstance !
New version is out, have fun!