Beta
Hearts (Card Game) Kata 3 of 3
Loading description...
Puzzles
Games
View
This comment has been reported as {{ abuseKindText }}.
Show
This comment has been hidden. You can view it now .
This comment can not be viewed.
- |
- Reply
- Edit
- View Solution
- Expand 1 Reply Expand {{ comments?.length }} replies
- Collapse
- Spoiler
- Remove
- Remove comment & replies
- Report
{{ fetchSolutionsError }}
-
-
Your rendered github-flavored markdown will appear here.
-
Label this discussion...
-
No Label
Keep the comment unlabeled if none of the below applies.
-
Issue
Use the issue label when reporting problems with the kata.
Be sure to explain the problem clearly and include the steps to reproduce. -
Suggestion
Use the suggestion label if you have feedback on how this kata can be improved.
-
Question
Use the question label if you have questions and/or need help solving the kata.
Don't forget to mention the language you're using, and mark as having spoiler if you include your solution.
-
No Label
- Cancel
Commenting is not allowed on this discussion
You cannot view this solution
There is no solution to show
Please sign in or sign up to leave a comment.
The reference solution is still incorrect, it determines the wrong person when someone shoots the moon.
This comment has been hidden.
I can't see the spoilers. But I do know that the reference solution is taking the leader of the first hand as the person who shot the moon, instead of the actual person shooting the moon.
Okay, my solution passes the kata now, so this should be fixed.
Great! Sorry that my comment didn't make it to you, I'm still learning how this side of codewars works. My mistake was a typo. Let me know if you have any other issues!
This is an incorrect usage of Python classes.
_
is meant to be weak "internal use" indicator; it's not meant to be used by outside API as a field directly. The tests shouldn't even know the existence of such "internal use" fields, let alone testing their behaviours.More importantly, if scores are intended to be modified, then creating this hurdle is pointless. Python is not Java after all. But if scores aren't intended to be modified, as what this interface would infer, then this shouldn't even be tested, as then the tests would also need to test score validation (what if I set someone's score to
-100
?), and whether games break if scores are set to different values during a game, etc. (Besides, these_
fields aren't use anywhere else other than this part anyway, so these tests do not contribute to anything about the behaviour of the class, aka they're unhelpful as unit tests.)Also, the part about the name of these getters/fields aren't mentioned anywhere, and can only be inferred by the tests.
p.s The tests also swallow exceptions, which is bad practice. You'll at least need to do something like
Thanks for the great explanation of what's going wrong here. I just want to make sure that I'm hearing you right, because my instinct is to delete these tests based off of your explanation.
It sounds like if I've described the goal well enough, these tests are only effective in testing if the user has written something that uses a getter method, which sounds unneccesary based on the rest of your description. Especially since I've allowed the posibility of exceptions in the testing, (which is bad practice, as you informed me). I just want to make sure that the way I describe the class methods is easy enough to understand. I don't use classes, so a lot of the specifics of what I need to test is a little forign to me.
Testing for exceptions isn't the problem, swallowing the exception is the problem. When the tests hit that spot instead of the actual exception message like
we get
As you can see, crucial debugging information is lost. In general tests shouldn't be unhelpful to users for no particular reasons.
The problem here is that these tests are testing implementation details unrelated to the desired behaviours of the class, which goes against what unit tests are about. What a
Hearts
object really need to tell are the scores of each player; so the public-facing API ofHearts
only needs to give a getter. There are no requirements that it should allow setting the scores directly as well (as can be seen by the tests).The previous API of returning every player score as a
dict
works perfectly fine. Why is it changed to the current version?The second test group isn't testing the getter, it's testing the setter. And
property
defines a getter only. So at least there is a hidden requirement of "oh, also you need to define a setter of the same name but with_
prepended"; but then there are further questions of why a setter needs to exist if test code isn't using it anyway, and why the setter can't just have the same name as the getter.Thanks for your clarification. I see now that my idea of python classes was wrong. Where I thought that the prefixed underscore and getter was mandatory for correct class functionality (although, this might be needed for the testing class to prevent cheating), I see now that there are many ways to write correct code for the problem. The old tests were confusing because I was forcing code to be written in one style, where ultimately, I only wanted to test the side effects. You've taught me a lot about classes through this conversation, so thank you for your patience!
These tests for the confusing methods have been removed.
I understand now the difference of allowing errors in testing, and swallowing errors. I have modified the section of testing that will be prone to errors, and have fixed the way it will return error messages. Once again, I will republish so you can see the changes, and if there's anything else that needs to be done, just let me know!
Thanks again for your help!
winner
/loser
does not specify what happens if multiple players tie for the lowest score/highest score, or if multiple players loses in the same round.This part of the kata has been removed.
I added this because initially I thought that including this method would be simple, and it fit the theme of the class overall. However, after looking into how to clarify your point, I realize that fully explaining this would just add more complexity that isn't related to the inital goal of the kata. Hence the removal of this requirement.
I have also reverted the requirement to simply return a python dictionary containing the players scores, once a method is called. I agree that this is the simplest and best way to finish this kata.
Thanks again for your keen eye!
Reference solution has incorrect logic in determining whether someone has shot the moon, and when it happens, who shot the moon. Hence causing all the discrepency between reference solution and our solutions.
Thanks for looking into this even more! I'm just about to start re-writing this after a good night's sleep, so I'll keep an eye out for this in particular.
Hello again! I am marking this particular issue as resolved. I would still love it if you reviewed the rest of the new code, but for this particular issue, I am confident in the new logic for determining when someone has shot the moon.
The current kata design is insane with the functions having to use external states but no available anywhere, hence using a global state
SCORE
. The tests are deeply coupled with it, and the users can do various things to break the tests by using other objects asSCORE
.This anti-pattern has a simple cure, which is known as "using a class".
To actually run games that need to keep track of states, it should belong to a class (something named
Hearts
), with methods that run games, and finally a method that returns scores. Tests are only resettingSCORE
each time anyway, which equals to creating a new instance of said class.Your suggestion of using a class does sound like the simplest solution to my problems. I've been re-writing the code for this kata anyway, so I will un-publish for now, and I'll let you know once I have something less crazy up and running! Thanks for your feedback.
I've just about got a working class fixed up, and upon re-reading this a few times, I think I'm on the right track, but I want to make sure I'm fully understanding your recommendation.
In other words, the task of this kata should be described as: create a class
Hearts
such that it keeps track of score, and has methods to evaluate score and such (per the other rules we already have). Then unit tests can be based off of each instance of that class, which will be able to self regulate better than depending on a global dictionary. With each of these instances, we have more secure tests, as well as simpler, more organized unit testing parameters.If that all sounds correct, check out the new code! most of it is still a work in progress, but with your wise guidance, I think I'm finally heading the right direction with this. If i'm heading the definite wrong direction, just leave the issue unresolved, and I'll re-evaluate again.
Thanks again for your help!
Hello again! I think I have sucessfully resolved this issue. The scope of the kata has changed quite a bit from the original, but I think that this makes for a better, more enjoyable kata anyway. I'll wait to publish again until you have had a chance to review everything new, and find the issue resolved to your standards. I'm still learing how parts of codewars work, so I'm not sure if you'll be able to do an actual test with the new testing. Either way, just let me know if there's anything else you need me to do to resolve this issue!
I'm marking this as resolved. I'll re-publish, and tackle any other issues as they come up.
Initial code uses
_player_score
but the sample tests usesalex_score
,bob_score
,chris_score
anddave_score
. They don't match.That's a good point. I think for clarity, I could either remove this example from the initial code, or use
alex_score
as the example instead. I think I'm leaning towards just removing this example since this is something seems to be pretty common in python classes. (I'm not sure though, this is only the 2nd class I've ever written.)For now, I've changed it to be
alex_score
, but if you think it's better to remove, let me know!If it helps, here's a full test that fails for me:
In the following example our answers differ on the 6th round.
I get a score of
{'Alex': 19, 'Bob': 26, 'Chris': 74, 'Dave': 37}
and you get{'Alex': 45, 'Bob': 36, 'Chris': 72, 'Dave': 55}
Each section is:
Hello again friend!
Voile and I have been working through this for quite awhile now, and it seems that everything is up and running! The kata has been refactored quite a bit, but I implemented some of your suggestions as well as some of theirs! Let me know if you have any other issues!
How sure are you of your implementation? I'm only asking because I'm consistently failing ~50 random tests every time I run the trainer, but pass everything else.
Just so we're clear:
EDIT#2:
HAND
with say,'2H', '3H', '2C', 'QS'
they have scored15 points
on that hand.26 points
to the player's score total. Instead, they recieve zero points, and every other player recieves 26 points. So, a failure to shoot the moon means that someone, even just one other player, recieved a point in that round. This would add 25 to the "failed moon shooter" and 1 point to the point theif. Both other players would score zero. I should probably be clear that I don't have any code checking for a 'failed shooting the moon', and only have a check for 'shooting the moon'.To be honest, I'm not surprised the random tests might be broken. I was told in a previous kata to always put code related to test cases alongside the actual test case. This has made bug fixing very tedious and difficult to identify when I have to scan through 300 lines of code to see what's even being called where. Previously, I had put the random card dealer, and a few other variables into the preloaded section to isolate code that will only be used for randomness. This made bug fixing a lot easier, since I had more organized random tests, and could focus only on the code used for testing.
The way random tests work right now is sub-optimal, but I'm not sure about how to fix it. I'm basically running a copy off of the random deal (the user is also given a copy of this) and running my code through a variable I named 'mySCORE', and then comparing the values in mySCORE to the values in SCORE. I worked through so many error messages during this process that I would have to guess on what the issue is. My best guess is that the issue is probably that you might be given a different list than the list my code is running on. Which would be a major issue... I'll take a look at it again with fresh eyes, but if I can't get this up and running by tonight, I'll probably un-publish until I have a way to fix it.
All that being said, I would love your advice on how to keep the unit tests more organized. I loved the way the preloaded section worked, but it makes sense that I shouldn't allow the user to somehow access that part of the code. If you also have a better idea on how to compare user results from my results, that would also be great!
Hehe, yeah I can understand how debugging would be painful. There's a chance I'm making mistakes too. I would change how you're doing the
SCORE
though. I don't see a good reason for this to be global state. Instead, make a function calledplay_game
or something like that where you give us the initial hands of 13 cards for all players and then test us for the final score. We already know the stopping condition will be when a player scores over 100 points. I'll play around some more to see if this is a 'me' problem though.Thanks for your help on this Kata, as well as the previous one! You're really giving me a run for my money when it comes to testing my code haha.
I wanted to ask you what you meant about SCORE. Are you recommending removing this part of the test entirely? or just change the way it's being used in the random tests? I think it's probably still the best way to evaluate the actual scoring logic in the example tests, so my instinct is to keep it there for those tests at least. However, I do think you're right about changing the global nature of it in the random tests. This is where half of my errors were happening. I do like the idea of having you guys score the whole game on your end, and simply comparing the final results. As far as I can tell, all that this might require is re-writing the description, and fixing the test targets.
Basically change your implementation to remove SCORE as a globally managed object. This means changing your code setup and how you're testing. You supply us with randomly drawn hands for the 4 players. Each play of the game (
n
rounds) will return the final score of the game. We know when to return because one of the players will have a score greater than 100.In code:
This is brilliant. I'm currently starting from scratch to get some better code to use in the tests generally, and also to weed out other weak spots. I will for sure work on something along these lines over the next few days. (maybe hours if I'm really lucky...)
Ha, there's no rush. For now I'm going to put this on the back burner, or take a detailed look at one of the failed random tests to figure out if it's me. Go hand by hand and keep a good track of the scores. Who knows, maybe somebody else will solve this too.
Please link part 1 and 2 in the description (since you're also asking us to copy our previous solutions to this kata).
Fixed!