Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Deck of Cards – A playing card API (deckofcardsapi.com)
255 points by crobertsbmw on May 11, 2015 | hide | past | favorite | 137 comments



Hey, you did a thing and told people [0]! Good for you. Is it perfect? No idea, but from reading the comments here a lot of people don't think so. Who cares though [1]! You're so far ahead of so many people because you actually did something.

Next time maybe all your GETs will be RESTful, maybe not. Either way, you've done a thing, put it out there, and are presumably learning a lot by doing so.

Great work.

[0] http://carl.flax.ie/dothingstellpeople.html [1] http://www.garann.com/dev/2013/how-to-blog-about-code-and-gi...


I'm seeing a lot more discussion and debate, rather than criticism.

So good job for that too... I think this Deck of Cards API would make a great case study for analyzing and discussing the varying takes on how a RESTful interface should handle certain situations which aren't as straightforward as the typical blog or todo list examples.


A lot of the time it doesn't feel like that to me.

People release things they have worked long and hard on, only to get a bunch of negative comments picking on holes and mistakes.

The weird thing is they are the lucky ones; it's pretty damn hard to make it onto the front-page of HN now, regardless of the quality of the content. (Don't believe me? Take a look at how many times some articles have been reposted and the disparity in number of votes.)

Getting feedback should be great, but not many of us are good at it. Generally, we only comment on things we care about or find interesting (ignoring the stuff that is so bad it deserves harsh criticism like storing passwords in plain-text), but we forget to say that in the comment and only mention the minor flaw we saw.

I don't have a solution to this, other than to tell posters to be prepared for criticism and to take each up-vote as a major token of respect in what you've built.


Nice one! Good on you for building a thing and putting it out there.

A few comments/suggestions:

* You have DEBUG = True in your production Django config. (eg. http://deckofcardsapi.com/api/)

* You are mutating state with HTTP GET, this is an anti-pattern for a number of reasons. The common one I use with people I coach is that browsers/proxies will happily cache GET requests unless told not to, but there are a number of other reasons if you read up on REST [1].

* Being a public API in a well known domain this is a good opportunity to make the API self documenting & navigable with a hypermedia format. (eg HAL, Siren, JSON-LD) [2]

[1] http://martinfowler.com/articles/richardsonMaturityModel.htm...

[2] http://sookocheff.com/posts/2014-03-11-on-choosing-a-hyperme...


> You are mutating state with HTTP GET

I agree. However, this is the first API I've seen where a mutable GET actually makes sense. Drawing a card is definitely a GET. How would you do it instead?


> Drawing a card is definitely a GET.

I see where you're coming from ("I'm drawing / taking / GETting some cards"), but drawing cards is not an idempotent action. I would implement it as a POST.


In some sense you are PATCHing the deck by removing a card.


I've yet to see a case for PATCH that couldn't be solved with more clarity for everyone involved by a new resource.


I think it's more of a terminology thing, rather than 'GET me a card' you could 'POST remove 2 cards from the deck' and the side effect is the response tells you which cards were deleted.

But this kind of bike shedding drives me mad because oh my lord who gives a crap just build software and document it properly.


I give a crap, because when I see an API, I expect a GET to be idempotent. If a coworker implemented this, there would be words.


Same here. Working on a large codebase where people "just build software and document it properly" without following standards is not fun. Not to mention that frequently people end up shortening that to "just build software". It's better to get in the habit of following good standards even on small projects before bad habits form.


It's not necessarily bike shedding though. GET and POST have two different, widely-agreed upon semantic meanings. It's not just terminology.


As others have pointed out the HTTP verbs have meaning at a protocol level, trying to match a verb based on its English meaning is fraught with problems. Not least of which is the proxy problem I pointed out in my original comment.


I would argue that "drawing a card" isn't merely an information look up (GET) but an action with consequences (POST).

Looking at the cards in your hands, if the server maintains your hand state, would be a GET though.


It is acceptable for a client to retry a request that failed if it is a GET. This could happen if the server got your request but the response got lost, in which case you can't count on the deck having the right number of cards.


Why conform to arbitrary conventions when they don't make sense? Personally I think the best reason to conform to REST is because the user expects a "good" api to conform. Other then that is there any hard reason as to why it's "better" to strictly follow REST or even follow it at all?

Is an api that is consistent, fast and documented well, but uses only GET requests for everything including state changes really a horrible api?


> Is an api that [...] uses only GET requests for [...] state changes really a horrible api?

Yes, it is. Because HTTP clients (including browser) rely on the common method properties as defined by the HTTP standard (GET having no side effects, PUT being idempotent, etc.). The simplest example is caching / proxying, but there is other behaviour.

I strong recommend acutally taking a look at the HTTP standard. The RFCs such as RFC 7231 are well organized and human readable. For the definition of the HTTP verbs, see:

  RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content

  4.2 Common Method Properties
https://tools.ietf.org/html/rfc7231#section-4.2


I agree with the spirit of your post, but using the right HTTP verbs can have real, actual consequences because of how some caches and clients behave. You're more likely to accidentally send multiple requests or get stale data when you're using GET.


DELETE a card from the deck. Return the card(s) drawn in the response body. Have a separate resource for the top of the deck:

DELETE /api/<deck-id>/top?count=2

------

200 Ok

8♣

10♥


DELETE is idempotent to quote a Stack Overflow answer on the subject:

> Idempotence refers to the state of the system after the request has completed

> ...

> The key bit there is the side-effects of N > 0 identical requests is the same as for a single request.

http://stackoverflow.com/questions/4088350/is-rest-delete-re...


The example I gave is idempotent. Calling it n >0 times would result in the same side effects.


That's not what idempotent means. It doesn't mean it produces the same side effects every time, it means multiple calls are equivalent to a single call.


Gah! You're right. In that case POST would be the only acceptable option here.


A PUT would work, with action=draw&count=2, or action=shuffle, and so forth.


As a general rule "action" parameter is pretty non-RESTful.

Sometimes RPC-style interfaces like that are ok, but don't pretend that they are RESTful.

Also PUTs are supposed to be idempotent, so don't use a PUT for this.


I thought URLs (including query strings) were opaque under REST?


URLs are opaque, but the meanings of the HTTP methods aren't.


I'm not questioning that; I was questioning the statement '"action" parameter is pretty non-RESTful'. If URLs are opaque, why is it non-RESTful? Or is the point that if you're using query-string parameters, then by definition you're using a method that's supposed to be safe or idempotent?


If you used different HTTP methods, you'd already know which one to use, and don't need the action parameter. So the usage of the "action" parameter usually implies that that requests are all the same method. And if we don't want to violate the HTTP standard, that method must be neither GET/HEAD, nor PUT nor DELETE (as surely some actions are non-idempotent).

In other words, an action parameter which is actually used and which doesn't violate the HTTP standard, well, that almost certainly means that all requests are POST requests.

However, if all requests are POST, no matter if they are side-effect-free or not, no matter if they are idempotent or not, then this is not very REST-like.

Note that it is not important whether you think this argument does or doesn't holds for your particular API. My point is that this whole judgement is solely about HTTP methods, and has nothing to do with URLs being opaque.


> If you used different HTTP methods, you'd already know which one to use, and don't need the action parameter.

But the examples given by anilgulechas were 'action=draw' and 'action=shuffle'. Neither are idempotent, let alone safe, so presumably the only method to use in either case would be POST (notwithstanding anilgulecha's suggestion of a PUT).

So we need to distinguish between POSTs requesting a draw, and POSTs requesting a shuffle. Two options:

a) indicate it in the POST's body

b) indicate it in the URL.

If we go for (b), the query string seems as good a place as any.

What have I got wrong? Where would this violate REST (or the HTTP spec)?


PUT should be idempotent, though.


Could each draw return a draw_hash, that is usable only once? Not only could you then have idempotent draws, you could easily embed it as hypermedia,a previous hash could be sent to a hand_history to return an array of point in time data


>good opportunity to make the API self documenting & navigable with a hypermedia format. (eg HAL, Siren, JSON-LD)

Other than learning, what's the benefit here?


I assume you mean what is the benefit of hypermedia?

Martin Fowler does a good job explaining it (http://martinfowler.com/articles/richardsonMaturityModel.htm...).

As does Mike Amundsen (http://www.infoq.com/presentations/Building-Hypermedia-API).


I don't see much benefit in martin fowler's example

  <openSlotList>
    <slot id = "1234" doctor = "mjones" start = "1400" end = "1450">
      <link rel = "/linkrels/slot/book" uri = "/slots/1234"/>
    </slot>
    <slot id = "5678" doctor = "mjones" start = "1600" end = "1650">
    <link rel = "/linkrels/slot/book" uri = "/slots/5678"/>
    </slot>
  </openSlotList>

  Each slot now has a link element which contains a URI to tell us how to book an appointment.
Well, not really - we can only guess that by the fact that the link ends in "book".

We also don't know if we are supposed to GET, PUT, DELETE, POST.. or what data we are supposed to send to the url to actually make the booking.


Clients of a hypermedia REST API are supposed to have a priori knowledge of the link relations (the "rel" attribute). The fact the rel in this example looks like a URI is sometimes used as a convention (i.e., if the API supports it, a client may do a GET against the rel value, and get back a human-readable description of the purpose of the rel).

In the human readable description of the "/linksrels/slot/book" link relation, information should be given about what generally can be done with such links (like if GET or POST is supported, etc). This allows you to build your client applications. The value of the actual link (the 'uri' attribute) should be completely opaque to the client.


I agree though I expect Fowler may argue that that is what the HTTP verb OPTIONS is for. Amundsen on the other hand likes his hypermedia more explicit and I tend to agree with him.


1. His documentation is better than HAL, Siren, JSON-LD. It's a nice page.

2. GET makes sense here. If anything, it would be a PATCH. But it's silly to get bogged down in details.


> 2. GET makes sense here. If anything, it would be a PATCH. But it's silly to get bogged down in details.

Those "details" are quite important, as already explained in several other comments:

https://news.ycombinator.com/item?id=9523225

https://news.ycombinator.com/item?id=9523106

https://news.ycombinator.com/item?id=9523075

https://news.ycombinator.com/item?id=9523066

https://news.ycombinator.com/item?id=9525568


While this looks to me like a pretty clean and straightforward API, it's definitely not a REST API (not that it claims to be):

* The API doesn't really follow HTTP. It allows GET for state-modifying actions, which breaks assumptions that could be made by browsers, client libraries, caches, and proxies. Also, the "success" field seems fishy; a 200 response code is the usual HTTP way to indicate success.

* The API is not resource-oriented; the URLs "shuffle" and "draw" are verbs that describe the action to take. In a "real" REST API, URLs define conceptual resources (nouns), and you interact with the API by interacting with those resources.

* The API does not use hypermedia.

Hypermedia and HTTP compliance are discussed elsewhere in this thread, but I wonder if others have an opinion on the fact that the API isn't resource-oriented.

This "resource-oriented" rule has always bugged me about REST APIs. My impression has been that REST advocates claim that pretty much every API can and should be implemented with a CRUD-like interface (where the entire API consists of performing GET, POST, PUT, and DELETE on a conceptual set of resources), but it seems like that would be really awkward for this "deck of cards" use case. Is there value in trying to use resources here? What might it look like?


I'm not sure that a CRUD like interface would be best for something like this. In addition, as this is very much an API and the returned JSON changes depending on the action called on the resource, this looks to me like the ideal candidate to create a custom media type for. With that option open, we can simply define our own request verbs like so:

SHUFFLE /api/deck/<deck-id>

DRAW /api/deck/<deck-id>?count=2

Things become a lot simpler to use, document and implement.

I'd actually take advantage of the custom media-type option and return something much more succinct:

DRAW /api/deck/<deck-id>?count=2

200 OK

8♣

Have the response body be UTF-8 and use the card face runes in the response. Nice and simple.

You dont necessarily have to map your REST API to existing HTTP verbs and media types - in fact the real benefit in a use case like this is that you can implement something appropriate


Why the down vote? This is a perfectly acceptable approach! If you're going to down vote at least respond with an argument why


Probably because not only is the proposed API not REST it isn't even HTTP.


Both REST AND HTTP allow you to specify your own verbs and media types! What I was suggesting was that the semantics of the API could be better expressed as its own media-type with specific semantics rather than try to force the existing HTTP 1.1 semantics on it.

Think WebDAV; specify the API via an RFC like document and implement it that way the end result is not only easier to use, document and implement, other providers could implement compatible API implementations.

Seriously, has anyone here actually READ Fieldings paper?


I haven't, you are right I probably should.

But it wasn't hard to find something about standard methods and media types.

> REST enables intermediate processing by constraining messages to be self-descriptive: interaction is stateless between requests, standard methods and media types are used to indicate semantics and exchange information, and responses explicitly indicate cacheability.

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...


Thank you for your honesty. It's refreshing and I appreciate it.

I'm not sure if your response is an attempt at a counter argument, but the line "... standard methods and media types are used to indicate semantics and exchange information, and responses explicitly indicate cacheability" is exactly the point I'm making.

If the original author was keen to make their API RESTful (which I'm not particularly sure they are. Aside from the couple of minor issues people have already raised, there is nothing wrong with a JSON API served over HTTP. It's just not RESTful), they would standardize their media-types (by registering them with IANA) and document their custom HTTP verbs via a RFC. That is what is required to be truely RESTful.

In the example I gave, showed that by adhering to the principles of REST, they could actually simplify their API dramatically whilst allowing others to lean on their work (by implementing their own services that use their newly registered media-types).

Again, all this is documented in Fieldings dissertation. It is dense reading and very academic, but it's worth reading. I personally found it very enlightening.


The original API wasn't REST and wasn't claiming to be either! The commenter is right, this is a clear case for an RPC style protocol. One using HTTP (and robustly!) makes client creation easier, but it's still RPC and doesn't need to pretend to be REST.


Resource oriented and its implication of nouns as opposed to verbs doesn't have to equal CRUD. I can see a case for bending the nouns rule of thumb in this domain, for example I might have an api like so:

    POST /decks : returns a url to a new deck
    GET  /decks/<id> : returns a deck
    POST /decks/<id>/draw : returns a url to a card
    POST /decks/<id>/shuffle : returns a url to the deck
    GET  /cards/<id> : returns a card drawn from a deck
The draw/shuffle verbs arguably could be implemented like this:

    POST /cards : returns a url to a card (post body having deck id)
    POST /shuffles : returns a url to the deck (post body having deck id)
The cards POST makes a lot of sense, now that I look at it I think I would use that interface. And you could argue that the shuffles resource makes sense as at some point you may want to record and share when someone shuffles the deck.


Some of these don't really make sense.

    POST /decks/<id>/draw : returns a url to a card
    POST /decks/<id>/shuffle : returns a url to the deck
Are you adding a "draw" to deck <id>?

    POST /cards : returns a url to a card (post body having deck id)
    POST /shuffles : returns a url to the deck (post body having deck id)
Are you creating a card or a shuffle?

Here's how things should be, in my opinion:

    DELETE /deckCard/<deckId>
This removes a card from an abstract entity representing the relation between decks and cards. Thus, it draws a card and returns it, sort of like popping something off a stack.

    PUT /decks/<id> with body {shuffle: true}
This edits the abstract "shuffle" attribute of deck <id>, shuffling the deck. This is indeed odd, but I'm afraid it's the best you can do for a mutating request. I would recommend a non-mutating request that makes a new deck out of an old deck, perhaps using "source" as an abstract attribute.

    POST /decks with body {source: <oldId>}
It just goes to show that while REST is a good standard for CRUD operations, and is surprisingly extensible for non-CRUD operations, it can get confusing and become a real pain. Should one just deal with it or move to e.g. RPC? I haven't figured this out.


Just because a thing, such as a draw or a shuffle isn't a physical thing doesn't mean it cannot exist as resource. Programming is all about creating abstractions, so why cannot I create a shuffle or a draw resource? I could even record them and share them on their own endpoints for clients to view.

Commenting directly on you suggestions:

    DELETE /deckCard/<deckId>
This means each DELETE on this url would result in a different deck state which isn't idempotent as DELETE is mean to be.

    PUT /decks/<id> with body {shuffle: true}
Same with this, the resource would end up in a new state each time making it unsafe to do repeatedly as the HTTP spec says.

I think the issue is REST is taught with a CRUD view point and people have difficulty thinking about it in other ways. Also the English meanings of the HTTP verbs get confused with their HTTP meanings which doesn't help.

I liked this blog post which talks about the concept of "REST without PUT".

http://www.thoughtworks.com/insights/blog/rest-api-design-re...

edit: you've edited you comment since I started my reply:

I like your idea of replacing shuffle with a new deck:

    POST /decks with body {source: <oldId>}
You could then do things like lock the source deck which would make it easier to implement a multi-client system where you cannot draw from a deck until you have been informed it has been shuffled.


I agree with your comments and take them as evidence that REST is exceedingly difficult and complex for these use cases.

You can create new resources, just as I have, it just doesn't make sense to "POST /cards" when you're not making a new card at all.


I would approach it from a little further away conceptually.

A deck only makes sense in the context of a game, a draw only makes sense in the context of moving the card from the deck to some other container (hand, discard pile, arbitrary pile on the table).

I also like to model games as sequential actions (because that's how they work) so my API would be more like:

GET /game/<id>/turn/<index>/decks/<id>/card/<index> <- 1 or 0 for top card, other numbers to view more than one

Then your draw action is a move the card from the deck to one of the other places, either with a POST to the new place, that redirects you to the next turn of that place, or with a PUT to the card itself if you have some "location" field on the card that can be updated.

The question that strikes me though, is whether it makes sense at all for a client to be controlling the draw in a game of CaH, as it's not an optional step. Why not just have the model automatically put cards back in the players hands when they make their moves?


I like my REST interfaces, but they only really fit CRUD-like situations. Sometimes, you will want to be less restful to optimize for some real world issue, most likely latency.

I suppose it is a bit like de-normalizing your database for performance.

For a situation like this, I would keep it as restful as practically possible. Since the shuffle mutates the state, it should be a post/put. Since it doesn't create a new resource,you could argue it should be put, but you don't have new data anyway, so the point is kind of moot.

I'd probably collect my custom verbs behind a common path to make it more clear, like

    /api/decks/mydeckid/verbs/shuffle
Or to make it stand out more:

    /api/decks/mydeckid?verb=shuffle
The response would use http error/success codes like any rest interface.


If you do this, you are basically doing RPC, so in reality you've given up any RESTfulness.


Hence, "a bit like de-normalizing your database".


You've gained the useful parts of REST - lower transport overhead than SOAP, and being able to call it from a browser.


What's stopping you from calling SOAP APIs from a browser? Most use HTTP as the transport mechanism.


SOAP APIs tend to use POST even for readonly methods, and tend to use aggressively validated XML that's much harder to write by hand than typical "REST" JSON.


I'm sure why using POST for readonly methods is a problem in the browser. It potentially messes with caching, but it should still function correctly. (Granted, this is probably a poor design design decision, but has nothing to do with correct functionality.)

As far as constructing the XML, you should be able to use something like xmlbuilderjs[0]. That said, I completely agree that dealing with REST APIs in the browser is far more practical.

[0] https://github.com/oozcitak/xmlbuilder-js/


Plus, for the CRUD parts, it's still REST.


What exactly is hypermedia? Wikipedia is not helping me understand what would not to be changed to make the api use hypermedia?


Look up HATEOAS. I find Spring's documentation to be pretty good at explaining: http://spring.io/understanding/HATEOAS


Not that I had a similar situation, but how to implement actions such as shuffle or draw and make them-resource like?


I guess shuffles and draws should be their own resources, and you POST to it to do that action? You'd then keep a table of shuffle/draw events, which mutate the deck as a side effect.


I get it. I had an idea to make a "shuffled-copy" or a new deck with one less card, made from the original deck. Than you can theoretical rewind your shuffle process, since it's a chain of immutable decks. But I'm afraid that will really consume too much storage for a rather unimportant thing, at least in this case :) .


You could shuffle in a deterministic way, using a smallish seed, and store a list of those seeds which would cut down on storage. I realise that you probably wouldn't want to do this if you're trying to recreate Vegas, but it's an interesting challenge to mull over nonetheless :)


I for one like get requests. They are much easier to play with.




I've changed the secret key that I am using in production. I wanted the settings.py to be there so it works out of the box if anyone forks it.


Remember to always gitignore your list.txt file folks!


Good catch, haha.



That of course doesn't delete it from the history :-)

You can do that via https://help.github.com/articles/remove-sensitive-data/, but once it's been cloned, the file is of course out of the toothpaste tube so to speak :-)


(ಠ_ಠ)


I wonder if returning SVG would be possible - https://code.google.com/p/vectorized-playing-cards/

Edit: Could be an excellent idea - 8 of Clubs is:

* 28kb as a PNG.

* 14kb as an SVG

* 4kb as a gzipped SVG


I used the unicode symbols; ♠ etc for my game; http://playonline.cards

It was a bit fiddly but definitely wins on file size. I would have used SVG for the face cards but they really killed performance with animation unfortunately, so I went with a compressed PNG (20kb for all 3).


Thought about that as soon as I saw it returning rasters. SVG would be best offered alongside as an option; it requires more effort to use than just a png. Perhaps a 'vector' to accompany each 'image'?


Accept: headers. Default to image/png


Those cards look great! Much better than the OP's raster images.

But they seem familiar. I can't help but wonder, are they infringing on any copyrights?


Following that link, the first section on the page:

These poker sized cards have been created and hand optimized in various vector formats (.eps and .svg) using the open source .svg graphics editor Inkscape http://www.inkscape.org.

....

Generally, this means the cards are free to use (commercially and non commercially) but must be properly attributed (see "README.txt" file) and (The library itself, not your project) re-distributed only under the same license.


I like the website design but shuffling cards is extremely trivial to code. Also cards are mostly used for gambling games and it's a huge security hole to use a third party api for that unless it's from a very trustworthy source.

One maybe useful thing about this api is the card images, but there are also probably plenty of decks in the public domain.


> Also cards are mostly used for gambling games and it's a huge security hole to use a third party api

Depends. If you're writing a game you wanted the player to trust you might want to use an external shuffling service so you can easily show proof-of-deck after the game is over.

Of course, you could do this simply by giving the player a cryptographic hash of the shuffled deck beforehand, e.g. SHA-256(5H,4D,AS...)


I've worked as a developer for online gambling games for 6 years. We never shuffled the deck of cards. Instead, as player requests another card(s), they are generated using hardware RNG and returned to player. Deck only knows which cards are left in it, but their order is undefined until that call to RNG.


If I'm not mistaken, this sounds like an incremental fisher-yates shuffle.


You are correct. As the matter of fact, a bunch of games in majority of cases needed only the next card from the deck, that's why in our heads we almost always thought of "not shuffling at all".


How is that better? You just don't want to spend the time to shuffle a deck if only a few cards will be used? Or you are worried someone might cheat by being able to read card order ahead of time?


Is something new with this project? I believe this same thing was posted 10 days ago.

https://news.ycombinator.com/item?id=9462184

Would be interesting to hear if some of the issues raised in the previous submission were fixed or updated.


Has anyone noticed that it's on Github, and thus it wouldn't be too tough to submit an Issue or, even, a PR?


This thread is yet more evidence of the Bikeshed Phenomenon.


It's not bike-shedding when there's nothing else to talk about. This is basically a forum about bike shed painting.


And is not exactly encouraging to those who are thinking of submitting their projects.


Ha, nice. Your choice of images is...interesting :)

https://github.com/crobertsbmw/deckofcards/blob/master/stati...


I just stole all the images off wikipedia. I wanted to make sure I wouldn't get sued.



These strongly resemble the ones made by Nicu Buculei at http://openclipart.org


Neat! Possible typo:

> After two weeks, if actions have been made on the deck then we throw it away.

Might be "if no actions"?


fixed. Good catch.


Pretty cool! Love that theres no authentication and I can start straight from curl.

Nit: drawing from an empty deck does not throw an error: > curl http://deckofcardsapi.com/api/draw/i763hn8lcg0e/ {"remaining": 0, "cards": [], "deck_id": "i763hn8lcg0e", "success": true}

As does drawing a comically large number of cards: > http://deckofcardsapi.com/api/draw/vzlem7q4jhna/?count=10000... (...) "success": true}\n


I'm just getting a "400 Bad Request" for the home page (from Brisbane, Australia)


Seconded. US here.


Sorry about that. Should be fixed now.


Fixed.


If it supported the idea of multiple players, keeping track of what cards each player has, and facilitating passing cards between players; it could be a cool backend for lots of different card games.


I wonder if you could do most of this cryptographically. If you did, you could make a client that could do all of this peer-to-peer. I think you would just need the following to make a wide range of games (many popular ones, perhaps most?):

1. Client can produce a signature that it drew the k'th card from the deck for any k.

2. Client can produce a signature that the k'th card is X if it drew the k'th card.

3. Client can produce a signature that card X came from any arbitrary set of card indices containing k if it drew the k'th card. (This is the hardest one.) If it's easier, you could get most of this even restricting it to sets of cards that the client has drawn.

With just that, I bet you could make a protocol for most card games where no one can cheat, where the central server's role is only to give out information about k'th card one and only one time. Certainly it's enough for blackjack, most forms of poker, hearts, and go fish. Anyone have a game that would be difficult? Maybe one where hidden cards get passed from player to player.



I don't know much about cryptography. But this is very intriguing to me.


There are so many things a good API would have to do...

Different types of decks, handling of a discard, shuffling a card into the deck, shuffling the discard pile into the deck, handling hands, milling a card from the deck, multiple decks acting as one...

Though the simplicity of this api currently just having a deck that you take cards from is neat.


What's being used for RNG?


Appears to be python's random module, so not very secure if that's what you're after but it's probably correctly pseudorandom: https://github.com/crobertsbmw/deckofcards/blob/master/deck/...



Doesn't matter, as the whole thing is served without TLS.


Neat! Nice work! Some are definitely criticizing, but hey - you'll always have critics. Unless they're following through with a pull-request, don't mind them.

Great job on putting the project out there!

An idea: Multiple options for deck images - obviously would take time on the artwork, but you could set this in your initial call for a deck (Or maybe even make it so you can change it whenever - if someone would have a need for that for some reason). May be fun.

Great work!


The absence of a pull request does not negate the validity of a criticism. Hacker News is one of the most tech-savvy, intelligent and experienced audience you can find on the web. Everyone sucks, myself included. With that kind of attitude, I would never have learned anything.

Shielding yourself from criticism using an arbitrary criteria only perpetuates ignorance.


Sounds straightforward and simple. Well done.

Would like an option to set parameters of a deck. Some card games use only 8 cards from a set and not the whole 13.


Adding and subtracting from the starting deck would very useful. Adding Jokers, playing with only 1-10 (scopa), ect


Can someone show or explain:

1. An example of how this could be used.

2. How to do something other than just shuffling the cards.


I think it was just a fun side project. But as to how it could be used.. just a few weeks ago we were at a hackathon and built a quick poker texas holdem game. A library like that (arguably a bit more comprehensive) would have saved us a few hours.


Was it just a texas hold em ? Or a variation of it ? I assume being a hackathon it wasn't a vanilla texas hold em. Could you provide some more details and maybe the code ? After seeing this I'm interested to know what else you've done.


So we wanted to learn/play with react native. The project idea was to play a hand of poker online randomly against someone in less than 30 seconds. The fun part is you can only fold or go all-in : )


This seems like a really cool project!

But how are you shuffling the cards, and how are you identifying unique shuffled decks?

It looks like the deck_id is 12 characters, numbers or lower-case letters. That gives a range of 36^12 or around 4.7 * 10^18. The total range of a physical deck of shuffled cards is 52! or around 8 * 10^67.

It's possible I have misunderstood what deck_id is for.


Looks like deck_id references a persisted model: https://github.com/crobertsbmw/deckofcards/blob/master/deck/...

The model stores the state of the deck, including things like order and remaining cards and how many "decks" of 52 cards are in play.


Saw something similar demoed at Microsoft's Build event. Looks nice.


What's it good for, if it doesn't visualize my cards?


Wow. I never thought this could be an API. Really good work. I remember I spent a lot of time developing a class that deals with a deck of cards, shuffle and associate the card with a png.

I would use this API in the future.


OP: what was your motivation for this project?


Thanks for asking. I wanted to build a very simple API, and document it that my year ago self could understand it and actually figure out how to use the whole thing. I don't know if this is a good or bad thing, but I spent more time documenting/designing the single doc page then I did writing the actual API. I also thought the idea was unique enough that it was worth sharing.

The reason for GET and POST is that it was easier for my year ago self to copy and paste a GET url into chrome and hit Enter and see what happens.


Seriously, why wouldn't you just use a local RNG? Do you realize it's actually less work than reading API documentation?


Consider it a bad Rube Goldberg Machine.


  numbers = ['2','3','4','5','6','7','8','9','10','J','K','Q','A']
  suits = ['CLUBS', 'SPADES', 'HEARTS', 'DIAMONDS']
  deck = [(num,suit) for num in numbers for suit in suits]
  random.shuffle(deck)
  draw_card = lambda deck: deck.pop()


Kudos! Simple and to the point.


Cute, but an implementation of the mental poker protocol would be far more valuable.


I think I'll do that next.


Looks good.


HTTP errors as a service


Fixed.


    -people to spam
    -
    -weber@kcnext.com
    -info@cremalab.com
    -andy@lovekc.org
    -info@truckily.com
    -info@secondlifestudios.com
    -help@getflywheel.com
    -hello@elevate.co
    -hello@goodtwin.co
    -Info@ObjectLateral.com
    -editor@siliconprairienews.com
    -info@squareoffs.com
    -josh@socialchangenation.com
    -websupport@psicurity.com
    -sales@rfp365.com
    -travis@rivetcreative.com
    -info@phlyppgear.com
    -kyle@feralfew.com
    -matt@feralfew.com
    -zach@feralfew.com
    -courtney@feralfew.com
    -ben@homesforhackers.com
    -info@cyberjammer.net
    -info@SponsorShout.com
https://github.com/crobertsbmw/deckofcards/commit/2b5675df52...




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: