Google Maps API PHP連携 〜マップ情報をDBに登録する〜

Html -> DB

Google Maps APIを使用して地図を表示する画面の作成を行いました。

こんな感じです。

PHP連携

この画面の下部分にデータを登録するための入力部分があります。ここの入力をサーバー(PHP)へ送信してDBに登録します。
クライアントサイド(HTML)は作成したので次はリクエストを送信したときにデータを受け取りDBに登録する処理(PHP)を作成します。
ちょいメモ
実は画面からリクエストを送信する部分(ボタン)ですがまだ作ってません。。。

参考

参考にするサイトはこちらです。PHPマニュアルです。。。

HTML →PHP

HTML からの入力データをサーバ(PHP)に送信します。今回はHTMLとPHPを分断して実装するのでHTMLで初期表示処理の中で、DB からデータを取得するPHPを呼び出しますが、まずはデータ登録が先なので表示順とはいきませんが、この順序で実装していきます。

  1. 画面にGoogle Mapを表示する
  2. 初期表示処理は空、もしくはマップの初期処理のみを実装
  3. データ入力ボタンを押すと入力フォームが開く
  4. フォームにデータを入力するとサーバのPHPにデータを渡す(POSTリクエスト送信)
  5. PHPで入力(テキスト)とアップロードしたファイルを受け取る
  6. 取得したファイルにエラーがあるかチェック
  7. 同じく、ファイル拡張子のチェック
  8. ファイルをバイナリ(BLOB)でDB に登録

ここまでを実装しようとます。



JS 非同期 POST 〜非同期通信でのPOSTリクエスト〜

イントロダクション

前回KMLファイルがなんたら。。。と記載しましたが、結局のところはGoogle Mapの選択した位置にピンを落とす処理を追加しました。

現在の作成物はこちらのURL

https://zenryokuservice.com/sample/js/SampleMap.html

非同期通信処理(Ajax)

今回は、ここから非同期で記載した情報をサーバーに送信、JSONファイルを出力する処理を実装しようと思います。
早速ですが、非同期通信について触れておきます。

非同期通信とは

<同期通信>
HTMLフォームを使用して画面を遷移したり画面をリロードしたりするようなURLを更新するような通信のことを同期通信と言います。まぁ通常のリクエスト送信だと思っていただいて間違い無いと思います。

<非同期通信>
それに対して、非同期は何が違うのかというと画面の一部分を更新するときによく使います。
画面を表示したときに「loading ....」なんて表示されているのがこれです。
<同期通信の場合>
リクエスト送信した後に「レスポンス(次のページを受け取る)を待ちます。
<非同期通信>
リクエスト送信した後に「レスポンス」を待ちません。
なので「loading ...」なんて処理を行いながら「レスポンスが帰ってくる」のを待っています。

ポイント

レスポンスを待たなくて良いので次の処理が実行できるというわけです。「待ち」の時間が減るのでユーザーに優しい実装になります。

今回の用途

地図上の情報を取得、写真をサーバーに送信しJSONという形で保存しようという処理を実装しよう、というお思惑です。
前回記載しました内容の処理を実装します。

JavaScript

最近ではAngluarとかJQueryとかいろんなもの(フレームワーク?)がありますが、面倒なので使用しません。HTML5の仕様読みましたが、かなりの範囲を網羅する形でAPIが提供されているので、わざわざ他のJSライブラリなどを使用しなくて良いと思った次第です。
→話(使用する部品)がややこしくなるのであまり使いたくありません(笑)。

XmlHttpRequest

久しぶりに使用します。非同期通信を行うときに使用するオブジェクトです。他のライブラリなどはこいつを使用しているのでハナっからこの部品を使ってしまいます。APIドキュメントはこちらにあります。ドキュメントページからコードを失敬。。。
こいつをベースにして、ファイルなどのデータを送信する処理を実装しようと思います。

あとは、ソースを眺めながら考えます(笑)。

実装の流れ

先にサーバー側の実装を行います。これはクライアント(画面)からAjaxのリクエストを飛ばし、サーバー側で受けるので、受け口を先に作る…というわけです。ファイルの受け取りを行うので、とりあえず受信が出来ているか確認するものを作ります。

サンプル(クライアント)は下のリンクからアクセス出来ます。

https://zenryokuservice.com/sample/js/SampleMap.html

でわでわ。。。


/*  https://developer.mozilla.org/ja/docs/DOM/XMLHttpRequest#sendAsBinary() */

if (!XMLHttpRequest.prototype.sendAsBinary) {
  XMLHttpRequest.prototype.sendAsBinary = function(sData) {
    var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);
    for (var nIdx = 0; nIdx < nBytes; nIdx++) { ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff; } /* send as ArrayBufferView...: */ this.send(ui8Data); /* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */ }; } /* https://developer.mozilla.org/ja/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest * This framework is released under the GNU Public License, version 3 or later. * https://www.gnu.org/licenses/gpl-3.0-standalone.html * */ var AJAXSubmit = (function () { function ajaxSuccess () { /* console.log("AJAXSubmit - Success!"); */ console.log(this.responseText); /* you can get the serialized data through the "submittedData" custom property: */ /* console.log(JSON.stringify(this.submittedData)); */ } function submitData (oData) { /* the AJAX request... */ var oAjaxReq = new XMLHttpRequest(); oAjaxReq.submittedData = oData; oAjaxReq.onload = ajaxSuccess; if (oData.technique === 0) { /* method is GET */ oAjaxReq.open("get", oData.receiver.replace(/(?:\?.*)?$/, oData.segments.length > 0 ? "?" + oData.segments.join("&") : ""), true);
      oAjaxReq.send(null);
    } else {
      /* method is POST */
      oAjaxReq.open("post", oData.receiver, true);
      if (oData.technique === 3) {
        /* enctype is multipart/form-data */
        var sBoundary = "---------------------------" + Date.now().toString(16);
        oAjaxReq.setRequestHeader("Content-Type", "multipart\/form-data; boundary=" + sBoundary);
        oAjaxReq.sendAsBinary("--" + sBoundary + "\r\n" +
            oData.segments.join("--" + sBoundary + "\r\n") + "--" + sBoundary + "--\r\n");
      } else {
        /* enctype is application/x-www-form-urlencoded or text/plain */
        oAjaxReq.setRequestHeader("Content-Type", oData.contentType);
        oAjaxReq.send(oData.segments.join(oData.technique === 2 ? "\r\n" : "&"));
      }
    }
  }

  function processStatus (oData) {
    if (oData.status > 0) { return; }
    /* the form is now totally serialized! do something before sending it to the server... */
    /* doSomething(oData); */
    /* console.log("AJAXSubmit - The form is now serialized. Submitting..."); */
    submitData (oData);
  }

  function pushSegment (oFREvt) {
    this.owner.segments[this.segmentIdx] += oFREvt.target.result + "\r\n";
    this.owner.status--;
    processStatus(this.owner);
  }

  function plainEscape (sText) {
    /* How should I treat a text/plain form encoding?
       What characters are not allowed? this is what I suppose...: */
    /* "4\3\7 - Einstein said E=mc2" ----> "4\\3\\7\ -\ Einstein\ said\ E\=mc2" */
    return sText.replace(/[\s\=\\]/g, "\\$&");
  }

  function SubmitRequest (oTarget) {
    var nFile, sFieldType, oField, oSegmReq, oFile, bIsPost = oTarget.method.toLowerCase() === "post";
    /* console.log("AJAXSubmit - Serializing form..."); */
    this.contentType = bIsPost && oTarget.enctype ? oTarget.enctype : "application\/x-www-form-urlencoded";
    this.technique = bIsPost ?
        this.contentType === "multipart\/form-data" ? 3 : this.contentType === "text\/plain" ? 2 : 1 : 0;
    this.receiver = oTarget.action;
    this.status = 0;
    this.segments = [];
    var fFilter = this.technique === 2 ? plainEscape : escape;
    for (var nItem = 0; nItem < oTarget.elements.length; nItem++) { oField = oTarget.elements[nItem]; if (!oField.hasAttribute("name")) { continue; } sFieldType = oField.nodeName.toUpperCase() === "INPUT" ? oField.getAttribute("type").toUpperCase() : "TEXT"; if (sFieldType === "FILE" && oField.files.length > 0) {
        if (this.technique === 3) {
          /* enctype is multipart/form-data */
          for (nFile = 0; nFile < oField.files.length; nFile++) {
            oFile = oField.files[nFile];
            oSegmReq = new FileReader();
            /* (custom properties:) */
            oSegmReq.segmentIdx = this.segments.length;
            oSegmReq.owner = this;
            /* (end of custom properties) */
            oSegmReq.onload = pushSegment;
            this.segments.push("Content-Disposition: form-data; name=\"" +
                oField.name + "\"; filename=\"" + oFile.name +
                "\"\r\nContent-Type: " + oFile.type + "\r\n\r\n");
            this.status++;
            oSegmReq.readAsBinaryString(oFile);
          }
        } else {
          /* enctype is application/x-www-form-urlencoded or text/plain or
             method is GET: files will not be sent! */
          for (nFile = 0; nFile < oField.files.length;
              this.segments.push(fFilter(oField.name) + "=" + fFilter(oField.files[nFile++].name)));
        }
      } else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) {
        /* NOTE: this will submit _all_ submit buttons. Detecting the correct one is non-trivial. */
        /* field type is not FILE or is FILE but is empty */
        this.segments.push(
          this.technique === 3 ? /* enctype is multipart/form-data */
            "Content-Disposition: form-data; name=\"" + oField.name + "\"\r\n\r\n" + oField.value + "\r\n"
          : /* enctype is application/x-www-form-urlencoded or text/plain or method is GET */
            fFilter(oField.name) + "=" + fFilter(oField.value)
        );
      }
    }
    processStatus(this);
  }

  return function (oFormElement) {
    if (!oFormElement.action) { return; }
    new SubmitRequest(oFormElement);
  };

})();


Google Maps API 〜KMLファイルを作成するのはやめにしてJSON出力する〜

イントロダクション

前回、Google Maps APIを使用して地図を作成しました。
実装内容は以下になります。

  1. 画面をクリックするとピンが落ちてくる
  2. 選択場所の位置情報を画面に表示

KMLファイルを作る

参考サイトはこちらです。これを参考にしてKMLファイル(マップ情報を記載する)を作成するはずだったのですが、今回のやりたいこととずれているので、やめることにします。

JSONファイルを作る

KMLをやめにして、JSONファイルを作ることにします。経緯は以下のようになっています。

  1. KMLファイルは用途が違うのでやめ
  2. JSONファイルをサーバー上に設置して画面をロード(表示)するときにJSONを読み込む
  3. 地図上で選択、入力した情報をJSONファイルに出力するように実装する

このように処理内容を変更します。いわゆる「仕様変更」というものです。

JSONファイルの出力仕様

以下のような順序で処理を行う想定です。

  1. 地図の画面から登録する場所をタップ
  2. 選択した位置にオーバーレイが表示される
  3. 登録情報フォームに位置情報が表示される
  4. 登録する場所の名前とURL, 対象の写真を入力(選択)
  5. 登録ボタン(ラベル)を押下する
  6. PHPでそのデータをJSON形式でファイルに出力する

こんな感じで実装しようと思います。

技術的な話

今回の処理は2つに分かれます。

  1. クライアントサイド(HTMLとJS)、地図画面のこと
  2. PHPでのサーバーサイド処理、これはPHPでHTMLなどを出力しません。
  3. 送信される内容にテキスト、ファイルの2種類があるので、ファイルの取得(アップロードされたもの)を適当な場所に配置する or DBに登録する必要がある。

単純に画面からAjax(非同期通信)で対象のデータをサーバーに送信し次の処理を行ってしまいます。非同期なので送ってからレスポンスを待ちません。またその必要もありません。そのように設計したのもありますが。。。
なので、PHPではHTMLを出力するとか処理結果を返すことはさせません。この方が処理がスムーズかつ無駄が少ないからです。

実装に向けて

このように、仕組みを作る場合はシンプルにしたいものです。今回はうまく設計できたと思います(笑)。実装は以下の場所に随時実装していきます。

Github/ZenryokuService/LiveHouseMap

でわでわ。。。



Google Maps API 〜地図にオーバーレイを追加する〜

イントロダクション

前回、Google Maps APIを使用して地図を作成する準備を行いました。なんとか画面に地図を表示することができましたがこれだけでは面白くありません。。。

Google Mapにピンを追加

今回の本題です。作成したGoogle Mapにピン(オーバーレイ)を追加します。オーバーレイは
よく見るアレです。下の方にあります。

これは、自分の作成中の地図ですが「地図をクリックするとピンが表示される」という仕組みにしました。
意図するところは以下のような処理を考えております。

  1. 画面を選択する
  2. ピンが表示される
  3. 下の「名前」と書いてあるところに文字を入力
  4. 登録ボタンで位置情報をDBに登録する

以上のような処理を考えています。
現状の処理としては以下のようなイメージです。

  • HTMLでMapを作成する(JSの実装あり)
  • JSで細かい処理を行う

コード

参考にしたサイトは以下になります。

// 表示した地図にイベントを登録する
map.addListener('click', function(evt) {
   // イベント発生時の処理
   function (evt, map) {
// 緯度を設定する  document.getElementById('latValue').textContent = evt.latLng.lat();
// 経度を設定する document.getElementById('lngValue').textContent = evt.latLng.lng();
// オーバーレイを表示
selectedMarker = new google.maps.Marker(selectedOverlayOpt(evt));
    selectedMarker.setMap(map);
});

/** 選択用のオーバーレイOption */
function selectedOverlayOpt(mapEvent) {
    return {
        position: mapEvent.latLng,
        animation: google.maps.Animation.DROP,
        icon: {
            url: "mapImg/selected.png",
            scaledSize: new google.maps.Size(40, 40)
        },
    };


WebページにTwitterボタンを追加する方法

参考サイト:こちらのページを参考にしました。

ツイートボタンを追加する方法です。

  1. このツイッターボタン作成ページ?にアクセスします。
  2. キャプチャのように埋め込む(Embedする)ものを選択します。
  3. このボタンを押下して、埋め込むためのコードをコピー
  4. 自分のホームページ、ブログなどにコードをペースト

関連ページ

ツイッター開発者登録ページでツイッターAPIを登録する。










PHP コマンド実行 〜MacOSでphpコマンドを叩く(環境変数の設定と暗号化)〜

イントロダクション

TwitterAPIを使用するのに、ユーザー名とパスワードを使用します。しかし、このような情報はインターネット上に公開するとよろしくないので。。。

暗号化します

phpをテストするのに今まではウェブサーバー上でやっていましたが、ローカル(自分のパソコン上)で実行したい場合があります(今回のように)。なのでphpコマンドを実行する方法を記載します。

Macの場合はすでにコマンドが使用できるようです。しかし使えない場合にはどうしたら良いのか?自分の端末では再現できませんが、要点だけ。。。

早い話が、「php.exe」などの起動ファイルを環境変数に通せばOKです。環境変数とはシンプルに示すと以下のようになります。

REM Windowsの場合以下のコマンドで表示される
>path

# Macの場合は以下のコマンドで表示される
$ echo $PATH

このコマンドで表示される、パスが環境変数に設定がされている状態です。

とりあえず、Windowsの場合は、php.exeがあるフォルダを環境変数に加えればOKです。 Macの場合はHome brewを使用するようです。詳細は本家サイトを参照ください。

PHPコマンドで暗号化

今回はJavaを使いたいのでJarファイルを作成してPHPコマンンドでjarを実行してみます。

この動画では「Hello Java」を出力しているだけですが、Javaの処理を変えてやれば「Java呼び出し」はできているのでphpから起動できることの証明になります。

ちなみにphpでjavaを起動した時は環境変数などが読み込まれていないのでパスをそのまま実装します。

そして実行したコマンドは以下の通りです。

JDKへのパス/bin/java -jar 起動するJARファイル

<実行結果>

------- output ------------array(1) {
  [0]=>
  string(10) "Hello Java"
}

純粋なJavaの起動する方法はJavaBasic〜Hello World〜を参照ください。

そして、phpから起動するときに暗号化したパスワードを下のようにプログラム引数に渡します。

java -jar Cription.jar 暗号化したパスワード

phpのコードは以下のようになります。

<?php
$result = null;
$output = null;
exec('/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -jar Cryption.jar 暗号化したパスワード 0123456789012345', $output, $result);

print("------- output ------------");
var_dump($output);
print("-------- result -----------");
var_dump($result);
?>

実行結果

php test.php # コマンドの実行
------- output ------------array(4) {
  [0]=>
  string(54) "プログラム引数:暗号化したパスワード"
  [1]=>
ڀ}"ng(33) "暗号化:
  [2]=>
  string(40) ".Jpą!"
  [3]=>
  string(45) "復号号化:暗号化したパスワード"
}
-------- result -----------int(0)

とシンプルな感じです。

Javaのコードに関してはGitにあげてあります。

実際にテスト

作成したJARファイルをサーバーにアップします。URLは下に示します。

Githookのリクエストパラメータを取得します。

とりあえずテストします。

GitのWebhookからリクエストを受けて、リクエストの内容を出力して見ました。ファイルのパーミッション(権限)の部分で手こずりましたが、何とか。。。

下のようなコード(PHP)でログを取得しました。

 // Gitから(Webhookで)送信されたJSON
 $json_string = file_get_contents('php://input');
 // 送信されたJSONを読める形に変換する
 $json = json_decode($json_string,true);
 $fileName = chmod('githookLog.txt', 0666);
 $outData;
 foreach ($json as $key => $value) {
 $outData =$outData . "Key: " . $key . " / Value: " . $value;
 }
 file_put_contents('githookLog.txt', '--JSON:' . $_SERVER['REMOTE


悲報

レンタルサーバー上ではコマンドでjavaの実行ができませんでした。。。。

<実行手順>

  1. JDKの中身をサーバー上にアップロード
  2. PHPからexec関数を実行
    exec('../java/bin/java -jar Cryption.jar 暗号化したパスワード 0123456789012345', $output, $result);

 



Github page 〜Github pageでリポジトリの情報を公開しよう〜

イントロダクション

Githubを使用して自分のソース管理などを行います。しかしせっかく作ったものならば人に見てもらいたものです。これから作るものや仲間を集めたいなどこれらの場合も「こんなことやってます」という情報を展開する必要があります。そんなわけで。。。

Github pageでオープンソース

Gitリポジトリを作成したら以下のような感じで表示されます。(README作成済み)

そして、これはあくまでリポジトリなのでアクセスしてなんだかんだ。。。という部分には疎いです。(イメージなど通常のホームページのような表示のために。。。)

Github Pageの作成にはまずは「設定」を開きます。下のキャプチャで行くと「Settings」をクリックします。

すると下のような表示を見るけることができます(2019/06/06現在)

そして「None」の部分をクリックすると下のようにプルダウンだ開きます。

今回は、masterブランチを使用しようと思いますので真ん中の「master branch 」をクリックします。

そしてすぐ下にある「Choose theme」をクリックしてテーマを選択します。これは単純にテーマの情報(イメージ)が、この画面で閲覧できるので簡単にできます。そして。。。

最終的に

設定画面では上のような表示になります。この時点でGithubページが作成されています。自分の作成したものはこちらです。

https://zenryokuservice.github.io/GoalAchievement/

URLが「https://ユーザー名.github.io/プロジェクト名」になっています。

簡単ですがこんな感じです。

でわでわ。。。









じゃんけんゲームの仕様〜Java製じゃんけんゲームの全容〜

イントロダクション

「じゃんけんゲームVer1.0」のリリースに向けて作業中です。その作業でやらなくてはならない項目が以下のようになります。

ちなみに、はじめてJavaをやろうという方は、メニューの「JavaFX」リンクをクリックするとはじめての方向けの記事があります。

開けない場合は、記事の下にリンクを用意してあるのでそちらからどうぞ。

  1. プロジェクトサイトの作成
    • 目標達成PrjectにじゃんけんゲームPrjectをぶら下げる(目標達成のサンプルとしての位置付け)
    • 目標達成のフロー図を作成する(サンプルでじゃんけんゲームを表示)
    • 目標達成のフロー図を入力して表示できるようにする(余裕があれば。。。)
  2. ソースの解説と実装手順
    プログラミング初心者にもわかりやすいように、表示しているコンポーネントとソースコードを比較しながらプログラムの内容を説明する
    また、拡張(独自実装)する時の例を示しそれがどのように変わったのかサンプルを示す。
  3. 要件定義と画面設計書の作成
    作成したゲームの画像と各部品の処理内容、どのように動くのか?を定義する

画面設計をする

画面一覧

画面は以下のように使用する画面の数が4つあります、うち1つはアニメーションを使用するので、動画を載せておきます。

タイトル画面仕様

タイトル画面のクラス: BasicView.java(Gitへのリンク)
  1. タイトル文言を表示する
  2. 「じゃん」を青色のテキストで表示
  3. 「けん」を黄色のテキストで表示
  4. 「ぽん」を赤色のテキストで表示
  5. 「スタート」をボタンを表示
  6. 「スタート」ボタンを押下すると「TestingView」を表示する

<実装部分>

/** コンストラクタ */
public BasicView() {
// 縦のレイアウト
VBox layout = new VBox(300);
layout.setAlignment(Pos.CENTER);
// タイトル文言
layout.getChildren().add(this.getTitleNode());
// スタートボタン
Button start = new Button("スタート");
start.setOnAction(event -> setCenter(new TestingView()));
layout.getChildren().add(start);
// 画面に登録
Group gp = new Group(layout);
setCenter(gp);
}

「縦のレイアウト」

縦のレイアウトにはVBoxクラスを使用します。イメージとしては下のようになります。ソース的にはこんな感じです。

VBox layout = new VBox();
layout.getChildren().add(new Button("1番目に追加したコンポーネント"));
layout.getChildren().add(new Button("2番目に追加したコンポーネント"));
・
・
・

じゃんけん開始画面

スペリミス有り(笑)

じゃんけんゲームの開始クラス: TestingView.java
1. 「Ready?」の文言をラベルで表示する。
2. 「勝負!」のボタンを表示する。
-- ボタンを押下した時に以下の表示する。
-- ・自分の手のアニメーション。
-- ・CPUの手のアニメーション。

 

 

「Ready?」の文言をラベルで表示する。

<実装部分>

<ソース1: コンストラクタ>

judge = new Judgement();
// 画面サイズ取得
double height = MobileApplication.getInstance().getScreenHeight();
VBox tateLayout = new VBox();
// Rreadyの文言
ready = createReadyTxt();
// 一番上の横一列レイアウト
topLine = createLineLayout(height * 0.15, ready);
tateLayout.getChildren().add(topLine);

<ソース2: createReadyTxt()>

/**
* 画面上部に表示する「Ready?」のテキストを作成する。
* 
* @return 「Ready?」のテキスト
*/
private Text createReadyTxt() {
Text txt = new Text();
txt.setText("RxEADY?");
txt.setFont(new Font(45));
txt.setTextAlignment(TextAlignment.CENTER);
return txt;
}

赤い字は間違って入力している部分です(「バグ」と呼ばれます)、このメソッドではラベル(Textクラス)を使用して表示する文言を作成しています。(中央寄せ)

<ソース3: createLineLayout()>

/**
* 1行文の横レイアウトを作成し、コンポーネントを追加します。
* 
* @param size 1行文の縦幅
* @param txt 追加のコンポーネント
* @return HBox 作成したレイアウト
*/
private HBox createLineLayout(double size, Text txt) {
HBox layout = new HBox();
layout.setAlignment(Pos.CENTER);
layout.setMinHeight(size);
layout.getChildren().add(txt);
return layout;
}

「横のレイアウト」

HBoxを使用してコンポーネントを横に並べます。わかりやすい例としてはボタンが3つ並んでいるアニメーションの画面です。

<ソース>

// ボタンを表示するための横一列レイアウト
bottomLine = createLineLayout(height * 0.20, goo, chi, pa);

追加したコンポーネントを横に並べます。

次回はアニメーション部分について記載します。イメージは下のような感じです。

<じゃんけんゲームのアニメーション

timer = new AnimationTimer() {
            @Override
            public void handle(long time) {
                if (i % 50 == 0 && c < 3) {
                    ready.setText(judge.getJanKenPon(c));
                    c++;
                }
                if (c >= 2 && judge.getUserTe() != -1) {
                    judge.setFirstOut(false);
                }
                if (c >= 3) {
                    timer.stop();
                    rotateTransition.stop();
                    rotateTransition2.stop();
                    judge.setFinish(true);
                }
                i++;
            }

 

でわでわ。。。

 








Eclipse Gluon Game〜じゃんけんゲームを作る4:ライセンスを取得する〜

イントロダクション

前回、じゃんけんゲームVer1.0を作成しました。

そして、アンドロイド端末にゲームをデプロイしようと思ったのですが、apkファイルを出力するビルドができないのでなんでか考えました。

考えられる原因:(フリー)ライセンスを取得していない

十中八九これが原因だと思います。そして、このライセンスを取得するために以下のような準備をする必要があります。参考サイト:GLUONでのライセンス

英語のサイトなので、これを翻訳(Google翻訳)をすると下のようになりました。

キーポイント

  • ライセンスは、ライセンスが要求されているオープンソースプロジェクトでのみ使用できます。
  • 非商用のオープンソース開発に限定されています。
  • 1年間有効で年間更新可能です。
  • 申請するには、プロジェクトリーダーまたはコアコミッターになる必要があります。
  • プロジェクトは3ヶ月以上経過している必要があります。
  • プロジェクトは活発に開発中です。
  • プロジェクトは、商用サービスを提供したり、有料のソフトウェアバージョンを配布したりしてはなりません。
  • プロジェクトは、定期的に更新されるニュースセクションまたはプロジェクトの更新が掲載されているソーシャルネットワークアカウントへのリンクを含むWebサイトを持っています。
  • プロジェクトリリースは定期的にビルドを更新しました。

とりあえずは、プロジェクトの情報を発信するためのウェブサイトが必要なのでそちらを先に作成しなくてはならない状態です。

次はどーするか?

とりあえずは「プロジェクトサイト」の作成に着手しようと考えています。これには考えが何個かあってどこから着手しようか思案中です。

<考え(希望し)ている内容>

  • Git(GitHubのウェブページ)を使用してプロジェクトサイトを作成、公開する。
  • このBLOGを記載しているサーバー(ミニムサーバー)でリポジトリ(Git)のコミットなどの操作を行ったときのSNS(Twitterの予定)への連携処理(PHPにて実装予定)を行う。つまり。このサーバーでPHPを使いTwitterとGitを連携させる。
  • ロードマップなど、どのように作業を進めていくかを示すものを表示する。
  • Redmineのように、作業タスクと計画をリンクさせた形で計画~実行までを行いたい。
  • できれば、開発を行う仲間(コミニティ)を作りたい。

とりあえずはGitを学ぼう

オープンソースでJavaゲームから、人工知能までいろんなプロジェクトが存在しているGitを使用してやればうまくいきそうだと思っているのでここら辺を調べてみようと思っています。GitHubでは以下のようなことができるようです。(一部)

  • 静的(画面に動きのない、スクリプトなどがない)ウェブページの作成
  • リポジトリ(ソースなどのバージョン)管理
  • Issueの作成により、マイルストーン(ロードマップ的な実行手順を並べたもの)の作成
  • Webhookによるコミット時などのイベントによるリクエスト送信(SNS連携に使用できる)

まぁ調べてみないとなにもはじまらないかんじですね(笑)

 


Eclipse Gluon Game〜じゃんけんゲームを作る2〜

イントロダクション

前回は、作成したじゃんけんゲームの自己レビューの観点などを記載しました。

なので今回は、実際に自己レビューをやろうと思います。

自己レビューの内容

1:コードが汚い → コードが整理されていないので汚い。

ぱっと見で以下の点が気に入らない(「初めからやれよ!」と言われそうだが試行錯誤しながらだとそうも行かなかったのです。。。)

  • フィールド変数が多すぎる
  • アニメーションと勝敗判定がごちゃ混ぜになっている
  • コンポーネント(画面の部品)とアクションがごちゃ混ぜ

コードを眺めて見ると他にもあるが、とりあえずは目の前の敵を倒すことが先決! → 目の前のものを片付けると、先が見やすくなるなどメリットが沢山!

フィールド変数が多すぎる

前回記載しましたが「指摘した問題に対する『答え』」もセットにしておきます。問題と答えを同時は無理なので、問題→答えのように1問1答式に用意すると次にどうしたら良いか?がすぐにわかります。「答え」が難しいですがね(笑)

自分の出した答え

フィールドが多いのは、以下の部分で(クラス全体で)使用する変数が多いためです。

「じゃんけんの判定」と「結果の表示」

この部分はクラスを新たに作成して対応しようと思います。

<キーポイント>
1つのオブジェクトに1つの機能を実装する

なので、じゃんけんの判定と結果の文字列を返却する(まとめる)クラスを作成することにします。

この時点でのクラス構成は下のようになります。新しいクラスは「Judgement」クラスです。(なんかスタンドの名前みたい(笑))

「zenryokuservice.apps.fx.janken.util」パッケージを作成しそこに上のクラスを追加しました。Gitに登録していないので「?」が付いています。

そして、ここのコードから「じゃんけん判定」と「結果返却」の処理を抜き取ります。

ちなみに、ソースを修正して「間違った」「気に入らない」など元に戻したい場合はGit(バージョン管理)へコミット( or Push)をしなければいつでも元に戻せます。→リビジョン番号で取得すればそこの時点で戻すこともできます。

つまり「やれるだけやってから、いくらでも元に戻せる」ということです。

<リファクタ手順>

フィールドの移動
とりあえずは、移植(新規クラスへ移動したい)フィールドをサクッと移動してしまいます。

<移植した直後>

<TestingViewクラス>
<Judgementクラス>

ビルドエラーで赤くなっています、つまり修正が必要な部分です。

じゃんけん判定を行うために

今までは、TestingVIewクラスでじゃんけん判定を行っていたので描画処理で使用した変数などをごちゃ混ぜに使用していましたが、ここからは全て「じゃんけん判定」のために使用する変数を「Judgement」クラス、じゃんけんゲームの描画に使用する変数を「TestingView」クラスに作成する必要があります。

現状で出ているビルドエラー(赤い行)はここで必要になる修正部分になります。

どのように修正するか?

ここで考える必要があるのは「Judgement」クラスにどのようにして「判定」を行わせるか?になります。

どのようにするか?は直感的なもの(センス?)が必要な感じもしますが、1つずつやっていけばセンスなんぞはいりません!(センスとかダメダメなので。。。)

まずはビルドエラーを解消する
ビルドエラーのでている部分は以下の部分です。

  • ユーザーの手を設定
  • CPUの手を設定
  • じゃんけんの判定

そして、じゃんけんの判定は「Judgement」クラスでやるので判定メソッドは移植します。つまり「shobu()メソッド」を移植します。

shobu()メソッドの移動

ソースがこんな感じになりました。ビルドエラーに着目してください。左「TesingView」右「Judgement」

ユーザーとCPUの手を設定している部分を直す → Judgementクラスに「setUserTe()」と「setCpuTe()」のメソッドを追加する。

TestingViewクラスにユーザーの手とCPUの手を設定している部分を修正する。下のようなコードを修正します。そして、ちょっと悩んだのですが「Judgement」クラスは「new 」することにしました。なのでTestingViewクラスのコンストラクタに以下のコードを追加します。

// フィールド変数にJudgementクラスを定義
Judgement judge;
public TestingView() {
 ・
 ・ 
  judge = new Judgement();
 ・
 ・
}

ソースの修正

// ユーザーの手を設定
userTe = ? → judge.setUserTe(?);
// CPUの手を設定
cpuTe = ?  → judge.setCpuTe(?);

ここで、Getter/Setterの自動生成をしておきます。

下のようにビルドエラーが解消できました。

最後に起動して今までと同じように動くか確認します。

そして、リファクタリング後のコードです。(Gitにアップしています。)

でわでわ。。。