-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow customized ranking statistics and sorting #68
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will break anything, left a bunch of comments regarding readability but up to you if you want to fix them
I didn't do a manual test or anything though
@@ -18,7 +18,13 @@ export default { | |||
return standardizePlayerStatistics(format, Players.findOne(criteria)); | |||
}, | |||
|
|||
getPlayers(format, sort) { | |||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wow nice automated docs
return formatPlayer; | ||
} | ||
|
||
let gamesPlayed = player[format + "GamesPlayed"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works but I bet you could really simplify it with a more suited data structure here. I'm not super familiar with the code base so I can't tell you the optimal solution, but off the top of my head I think that the following structure would lead to more readable and resilient code:
{
japanese: {
...
},
hongKong: {
...
,
}
Resilient because string manipulation like this is prone to breaking during refactors, and since we're not using any typing here JS is gonna fail this silently and we might not notice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do think this is better than before though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this, I was thinking of making this change. Should I do that in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
follow-up PR is fine, this is pretty big already
<select name="sortStatistic" class="sortStatisticSelect"> | ||
<option disabled selected>Sort by: ELO</option> | ||
<option value="elo">ELO</option> | ||
{{ #each statistic in (getRankingStatistics format sortRankingExclusion) }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh my god I hate that this line is even allowed to work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Welcome to Meteor.js
<th class="players">Player</th> | ||
<th class="sortStat"> | ||
<select name="sortStatistic" class="sortStatisticSelect"> | ||
<option disabled selected>Sort by: ELO</option> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why disabled? Why are there two ELO options actually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't think of a good UX solution to indicate that the sortStatistic column is where sorting comes from. How do you indicate that changing this option will re-sort?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh huh, idk it seems pretty intuitive to me but if it's not obvious enough this is fine, maybe change the wording to Sort by ...
or something
imports/ui/ranking/Ranking.js
Outdated
{value: "averageHandSize", format: "Avg Hand Size"}, | ||
{value: "averagePosition", format: "Avg Position"}, | ||
{value: "flyRate", format: "Bankrupt %"}, | ||
{value: "chomboTotal", format: "Chombos"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kinda confusing that statisticsList[0].format
is the format for the stat, but format
is the type of game
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair.
imports/ui/ranking/Ranking.js
Outdated
{value: "riichiRate", format: "Riichi %"}, | ||
{value: "riichiWinRate", format: "Riichi Win %"} | ||
]; | ||
statisticsList = statisticsList.concat(japaneseStatisticsList); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can simplify this as
statisticsList = [
{value: "averageHandDora", format: "Avg Hand Dora"},
{value: "riichiRate", format: "Riichi %"},
{value: "riichiWinRate", format: "Riichi Win %"},
...statisticsList,
];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or even
statisticsList = format === Constants.GAME_TYPE.JAPANESE ? [
{value: "averageHandDora", format: "Avg Hand Dora"},
{value: "riichiRate", format: "Riichi %"},
{value: "riichiWinRate", format: "Riichi Win %"},
...statisticsList,
] : statisticsList;
but maybe this is too clever
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your Javascript powers are too strong for me
imports/ui/ranking/Ranking.js
Outdated
statisticsList = statisticsList.concat(japaneseStatisticsList); | ||
} | ||
|
||
for (let stat of exclusions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are you one of those people that use for loops in js? I thought you were better than this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway this can be simplified to
statisticsList.filter((statistic) => !excusions.includes(statistic));
Combined with the previous simplification this function becomes something like
function getRankingStatistics(format, exclusions) {
let standardStatisticsList = [
{value: "elo", format: "ELO"},
{value: "gamesPlayed", format: "Games"},
{value: "handWinRate", format: "Hand Win %"},
{value: "dealinRate", format: "Deal-in %"},
{value: "averageHandSize", format: "Avg Hand Size"},
{value: "averagePosition", format: "Avg Position"},
{value: "flyRate", format: "Bankrupt %"},
{value: "chomboTotal", format: "Chombos"}
];
const japaneseStatisticsList = [
{value: "averageHandDora", format: "Avg Hand Dora"},
{value: "riichiRate", format: "Riichi %"},
{value: "riichiWinRate", format: "Riichi Win %"}
];
return [...standardStatisticsList, japaneseStatisticsList].filter(
(statistic) => (
!exclusions.find((exclusion) => exclusion.value === statistic.value) &&
(japaneseStatisticsList.includes(statistic) && format === Constants.GAME_TYPE.JAPANESE)
);
}
I think it reads easier, up to you though
did not test this code btw make sure I didn't fuck up somewhere if you use it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need time to process this comment. You're probably right though. I thought Javascript was all about that list comprehension though? Are for loops actually discouraged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some people like for...each
, but generally the React community tend to favor the functional approach with map
etc. and I work with React everyday so I don't like for loops.
List comprehension might be a thing more recently, but generally the JIT compiler is so good now that performance is gonna be roughly the same no matter what you use
* Exclusion lists for statistics options. Allows for manual entries | ||
* @returns a list of statistics to exclude | ||
*/ | ||
sortRankingExclusion() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these the only places where exclusions
can come from?
In that case I recommend having a list of possible statistics, and then picking items from it like so
const STATISTICS_LIST = [...];
additionalRankingExclusion() {
return STATISTICS_LIST[2];
}
or something like this, it'll make the comparisons easier to read since you'll be able to just compare references to objects instead of the inner content of these objects. It's also more performant but that's whatever.
It's kind of a big change and this is fine though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to leave this for now.
* Event handler for modifying ranking sort statistic | ||
* @param[in] event The event to handle | ||
*/ | ||
'change select[name="sortStatistic"]'(event) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea what's going on here lmao
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently this is the syntax
'change -> Detect a "change event"
select -> on an HTML select field
[name="sortStatistic"]' -> with the name "sortStatistic"
(event) -> capture the event
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm like, super confused how this is calling a function with a string name? Or I guess this is a function definition. JS is weird
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JS is the worst
} | ||
}); | ||
|
||
function getStatisticUnit(statistic) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can simplify this as
return ["handWinRate", "dealinRate", "flyRate", "riichiRate", "riichiWinRate"].includes(statistic) ? '%' : '';
41a37dd
to
a321445
Compare
a321445
to
0b4cdf6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good stuff
Possible implementation of #15
Implemented dropdown menus for choosing a stat to sort by and compare against any other stat
Moved some calculations out of UI code and into API code
Slightly improved test code, but it can be removed