marg-do's

関数型生活

cocos2d-xでiOSデフォルトのMapViewを表示する

cocos2d-xではデフォルトでMapViewのような物が無いので(当たり前といえば当たり前)、地図を表示させる部分のみネイティブで実装する必要がある。

とりあえずiOS版だけメモ。

// HelloWorldScene.cpp
// メインの実装ファイル

// ……省略……

// MapViewを開始する
void HelloWorld::startMapView()
{
    // native viewと相性が悪いため一旦止める
    // MapView終了後Director::sharedDirector()->resume();でcocos2d-x側に復帰
    Director::sharedDirector()->pause(); 
    MapView::showMap();
}

// ……省略……
// MapView.h
// MapViewとブリッジするクラス

#ifndef MapView_h
#define MapView_h
class MapView
{
public:
    static bool showMap();
};
#endif
// MapView.mm
// iOSのネイティブ実装
#import "MapView.h"
#import <MapKit/MapKit.h> // 事前にMapKitを導入しておく

// cocos2d-xと連携するためには以下の2行が必要らしい
#include "deprecated/CCString.h"
using namespace cocos2d;

void MapView::showMap() {
    // 復帰時には[mv removeFromSuperview];で削除
    MKMapView *mv = [[MKMapView alloc] init];
    mv.frame = CGRectMake(0,0,320,480);

    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    [window addSubview:mv];
}

golangでサーバーの死活監視スクリプトを書いた

golangを触ってみたかったので、サーバーの死活監視スクリプトを書いてみました。

開発環境

コンパイル

手元のMacBookからサーバーでそのまま動くバイナリファイルへとクロスコンパイル出来ます。

$ GOOS=linux GOARCH=amd64 go build serveralive.go

あとはscpで送るなりして、cronで自動実行するようにしておけば、手軽にサーバーの死活監視が出来ます。

コード

package main
 
import (
    "fmt"
    "strings"
    "net/http"
    "io"
    "io/ioutil"
    "bytes"
    "log"
    "net/smtp"
)
 
const (
    API_URL = "http://hogehoge/api" // API(サーバー)のURL
        EXPECTED_API_RETURN = "OK" // 成功時のAPIからの返答
    MAIL_TO = "xxxxxxxxxx@gmail.com"  // 失敗した時に通知するメールアドレス
)
 
// APIへGETリクエストを送ってデータを取得
func request() (string) {
    resp, err := http.Get(API_URL)
    if (err != nil) {
        log.Fatal(err.Error())
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if (err != nil) {
        log.Fatal(err.Error())
    }
    return strings.Trim(string(body), "\n") // 前後の余分な改行を削除しておく
}

# エラーが発生した場合にメールを送る
func sendMail(mes string) {
    c, err := smtp.Dial("localhost:25")
    if err != nil {
        log.Fatal(err)
    }
    c.Mail("root@localhost")
    c.Rcpt(MAIL_TO)
 
    wc, err := c.Data()
    if err != nil {
        log.Fatal(err)
    }
    defer wc.Close()
    buf := bytes.NewBufferString("To:" + MAIL_TO)
    buf.WriteString("\r\n")
    buf.WriteString("Server seems to be dead")
    buf.WriteString("\r\n")
    buf.WriteString(mes)
    if _, err = buf.WriteTo(wc); err != nil {
        log.Fatal(err)
    }
    c.Quit()
}
 
func main() {
    res := request()
    exp := EXPECTED_API_RETURN
 
    if res != pas {
        mes := "Your API seems to be dead."
        mes += "EXPECTED: " + exp + "\n"
        mes += "ACTUAL: " + res + "\n"
        sendMail(mes)
    }
}

HaskellのWebフレームワークSnapで簡単セッション管理

HaskellのWebフレームワークといえばYesodですが、今回は勉強目的も兼ねてよりライトなフレームワークSnapを試してみます。 commitSessionを忘れていて結構手間取ったのですが、一度覚えてしまえばシンプルに使えていいと思いました。

開発環境

  • OS X 10.9.3
  • ghc 7.6.3
  • cabal 1.20.0.2
  • snap 0.13.2.6

Snapのインストール

今回は省略

実際のコード

起動して、http://localhost/save_sessionで動作を確認できる。

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Conrtol.Lens.TH

import Snap
import Snap.Snaplet.Session
import Snap.Snaplet.Backends.CookieSession

import qualified Data.ByteString.Char8 as B8
import qualified Data.Text as T
import Data.Maybe

--------------------------------------------------

-- | Session拡張を導入
data App = App { _sess :: Snaplet SessionManager }
makeLeses ''App

--------------------------------------------------

main :: IO ()
main = serveSnaplet defaultConfig app

-- | ルーティングの指定
routes :: [(B8.ByteString, Handler App App ())]
routes = [ ("/save_session", save_sessionH)
              , ("/load_session", load_sessionH) ]

app :: SnapletInit App App
app = makeSnaplet "app" "session sample application" Nothing $ do
    s <- nestSnaplet "sess" sess $
            initCookieSessionManager "site_key.txt" "sess" (Just 3600)
    addRoutes routes
    return App s

--------------------------------------------------

save_sessionH :: Handler App App ()
save_sessionH = do
   let (key, value) = ("name", "marg_do") -- セッションに保存するkey, value
   with sess $ setInSession key value -- セッションを保存
   with sess $ commitSession -- セッションをクライアントのクッキーにコミットする
   writeBS "<a href=¥"/load_session¥">LOAD SESSION</a>"

load_sessionH :: Handler App App ()
load_sessionH = do
    value <- with sess $ getFromSession "name" -- クッキーから値を取り出す
    case value of
        Just x -> writeBS . B8.pack . T.unpack $ x -- 取得成功
       Nothing -> writeBS "ERROR" -- 取得失敗

参考文献

ラッパーオブジェクト

js>var s = "test";
js>s.len = 4;
js>typeof(s.len)
undefined

なぜこのようなことになるのでしょう?

js>var s = "test";
この段階では、sは文字リテラル"test"自体を指している。

js>s.length;
s.lengthは(new String(s)).lengthと解釈され、新たなオブジェクトが生成される。
そして、(new String(s)).lengthが評価された時点でそのオブジェクトは捨てられる。
この時に作られた一時的なオブジェクトをラッパーオブジェクトと呼ぶ。

sは文字リテラル"test"を指したまま。

js>s.len = 4;
文字リテラルに対してプロパティを設定することはできない。(sはobject型ではなくstring型である)

js>typeof(s.len);
再びラッパーオブジェクトが生成されるが、このオブジェクトにlenプロパティは存在しない。