10: 2015-08-10 (Mon) 10:06:08 njf  |
Cur: 2015-08-15 (Sat) 17:34:45 njf  |
| | *URL構成 [#r4de93f6] | | *URL構成 [#r4de93f6] |
| | 以上のことを踏まえて、URLの構成は以下のようになります。 | | 以上のことを踏まえて、URLの構成は以下のようになります。 |
| | + | |
| | /crossdomain.xml | | /crossdomain.xml |
| | /api/entry | | /api/entry |
| | runtime: python | | runtime: python |
| | api_version: 1 | | api_version: 1 |
| | + | |
| | handlers: | | handlers: |
| | - url: /.* | | - url: /.* |
| | | | |
| | import webapp2 | | import webapp2 |
| | + | |
| | class HelloWorld(webapp2.RequestHandler): | | class HelloWorld(webapp2.RequestHandler): |
| | def get(self): | | def get(self): |
| | self.response.headers['Content-Type'] = "text/plain; charset=utf-8" | | self.response.headers['Content-Type'] = "text/plain; charset=utf-8" |
| | self.response.write("Hello, world!") | | self.response.write("Hello, world!") |
| | + | |
| | application = webapp2.WSGIApplication( | | application = webapp2.WSGIApplication( |
| | [('/', HelloWorld), | | [('/', HelloWorld), |
| | | | |
| | from google.appengine.ext import ndb | | from google.appengine.ext import ndb |
| | + | |
| | class UserData(ndb.Model): | | class UserData(ndb.Model): |
| | userId = ndb.IntegerProperty() | | userId = ndb.IntegerProperty() |
| | lastId = UserIdCounter(id=userIdIndex) | | lastId = UserIdCounter(id=userIdIndex) |
| | lastId.userId = 0 | | lastId.userId = 0 |
| | + | |
| | nowId = lastId.userId | | nowId = lastId.userId |
| | + | |
| | lastId.userId = lastId.userId + 1 | | lastId.userId = lastId.userId + 1 |
| | lastId.put() | | lastId.put() |
| | + | |
| | return nowId | | return nowId |
| | | | |
| | userId = self.request.get('userId') | | userId = self.request.get('userId') |
| | password = self.request.get('password') | | password = self.request.get('password') |
| | + | |
| | userData = getUserData(userId, password) | | userData = getUserData(userId, password) |
| | if userData: | | if userData: |
| | | | |
| | class NjfSave(webapp2.RequestHandler): | | class NjfSave(webapp2.RequestHandler): |
| | + | |
| | def post(self): | | def post(self): |
| | self.response.headers['Content-Type'] = "text/plain; charset=utf-8" | | self.response.headers['Content-Type'] = "text/plain; charset=utf-8" |
| | **パスワード暗号化 [#b678ed71] | | **パスワード暗号化 [#b678ed71] |
| | ここではパスワードを平文で保存していますが、個人情報などを扱う場合はパスワードを暗号化するのが一般的です。たとえばパスワード忘れ処理のためにメールアドレスを保存するなどした場合は、パスワードは暗号化した方が良いでしょう。しかし、カジュアルゲームでは個人情報取得すること自体がユーザーがいやがる可能性があるのでそこまで実装するかどうかは微妙です。 | | ここではパスワードを平文で保存していますが、個人情報などを扱う場合はパスワードを暗号化するのが一般的です。たとえばパスワード忘れ処理のためにメールアドレスを保存するなどした場合は、パスワードは暗号化した方が良いでしょう。しかし、カジュアルゲームでは個人情報取得すること自体がユーザーがいやがる可能性があるのでそこまで実装するかどうかは微妙です。 |
| | + | |
| | + | *費用 [#z4eebd4a] |
| | + | 費用についてはゲームによってセーブの回数や転送量が違うのでなんとも言えませんが、一日数百PV程度なら無料範囲でおさまるでしょう。 |
| | + | |
| | + | それ以上の場合で課金されるのは、ほぼ「Datastore Write Operations」という課金枠です。 |
| | + | これは名前の通りデータを保存した回数で、レコード毎に課金されます。これが2015/8/15現在、「$0.60/ Million Ops」となっています。十万回で0.6ドルですので、1万PVで1PV平均10回保存するゲームなら、一日60円、つまり月1800円程度となります。 |
| | + | 次に課金されやすい項目は「Datastore Read Operations」です。こちらはデータの読み込みで、一操作あたりの課金額はWrite Operationsと同じです。しかし、読み込みは最初のデータロード時のみのはずなので、Write Operationsに比べるとかなり少なく、上記のように1PVで10回保存するゲームならWrite Operationsの1/10です。 |
| | + | カジュアルゲームのデータ保存程度ではこれ以外ではほぼ課金されることは無いです。まれに転送量とインスタンスの立ち上げ時間が無料枠を少し越えるかどうか程度です。 |
| | + | |
| | + | よって、一日1万PV以上が一年以上続くような場合では月々定額のレンタルサーバーを借りた方が安くなるでしょう。一方数ヶ月で数百~数千PVにまで落ちそうなら、従量課金のGAEのほうが安くなります。 |
| | + | |
| | | | |
| | *サンプルコード [#ucddcda4] | | *サンプルコード [#ucddcda4] |
| | ここで解説したサンプルコードはこちらです。クライアント側のURLやcrossdomain.xmlの中のURLは環境に合わせて書き換えてください。 | | ここで解説したサンプルコードはこちらです。クライアント側のURLやcrossdomain.xmlの中のURLは環境に合わせて書き換えてください。 |
| | &ref(gaeWikiSample.zip); | | &ref(gaeWikiSample.zip); |