Java Mid Basic〜リファクタリングLv2 処理の整理とクラス分け〜

イントロダクション

前回 リファクタリングの構成について考えました。今回は、実装に入りたいと思います。

クラス分け

まずは、このアプリ全体の流れを作ります。「流れ」というのは、入力〜出力までの処理順の事です。

この流れをワンパターンにしてシンプルな形にしようという訳です。

どーやるか

インターフェースを使います。以前やったプロパティファイルと連携してコマンドを好きなだけ作れる…しかしプログラムには手を入れない…というオブジェクト指向の基本ワザを使います。

基本ワザ?

基本ワザとは以下のような実装方法のことです。

<プロパティファイル>
コマンド1=クラスの完全名
title=jp.zenryoku.sample.lv3.cmd.Title

<Javaファイル>
上記のプロパティファイルからクラスを呼び出し、そのクラス(CommandIFを実装)を呼び出す仕組みを作る

というような実装を行います。
### 概要
コマンドからクラスの完全名を取得する部分に関しては、以前やったものをちょいといじって使用できます。つまり考え方は同じということです、下にリンクを記載しておきます。よかったらどうぞ。

* [プロパティファイルを読み込む](https://zenryokuservice.com/wp/2019/08/08/java-mid-basic-%e3%80%9clv2_6_java%e3%81%ae%e5%9f%ba%e6%9c%ac%e3%83%97%e3%83%ad%e3%83%91%e3%83%86%e3%82%a3%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%82%92%e8%aa%ad%e3%82%80%e3%82%b2%e3%83%bc%e3%83%a0/)
* [Discordでコマンドを好きなだけ作る方法](https://zenryokuservice.com/wp/2018/07/16/java-discord-commandexecuter%e3%80%9c%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%82%92%e5%a5%bd%e3%81%8d%e3%81%aa%e3%81%a0%e3%81%91%e8%bf%bd%e5%8a%a0%e3%81%97%e3%82%88%e3%81%86%e3%80%9c/)

<手順>
1. コマンドの入力を受けてコマンド実行クラスを取得する
2. 実行クラスのメソッド「execute()」を実行
3. 処理結果をコンソールに出力

どのコマンドが来ても起動できるように実装します。
当然、例外処理(想定外のコマンド)も実装します。

### リファクタリング開始
元のコードは、こちらのコードです。前回作成した[Map読み込みのコード](https://github.com/ZenryokuService/PracticeJava1/blob/master/PracticeJava1/src/jp/zenryoku/sample/lv2/Lv2_8_Map.java)です。記載した[記事はこちら](https://zenryokuservice.com/wp/2019/08/14/java-mid-basic-%e3%80%9clv2_8_java%e3%81%ae%e5%9f%ba%e6%9c%acmap%e3%82%92%e4%bd%bf%e3%81%86%e3%82%b2%e3%83%bc%e3%83%a0%e3%83%ab%e3%83%bc%e3%83%97%e4%bb%98%e3%81%8d%e3%80%9c/)です。
記事の方に実装方法など細かい部分を記載しています。

今回はリファクタリングを行います。

### ダメな部分
これに関しては、[こちらの記事に記載しました](https://zenryokuservice.com/wp/2019/08/18/java-mid-basic%e3%80%9c%e3%83%aa%e3%83%95%e3%82%a1%e3%82%af%e3%82%bf%e3%83%aa%e3%83%b3%e3%82%b0lv2%e6%a7%8b%e6%88%90%e3%82%92%e8%80%83%e3%81%88%e3%82%8b%e3%80%9c/)が、早い話がごちゃごちゃして見づらいコードだということです。
これらを解消するのに、どーしたら良いか?を考えたのが上の記事になります。UMLなど便利だと思います。

### 処理フローを作る
早い話が、このアプリケーションで行う処理をワンパターン化しようということです。そのパターンというのが、上に記載したものです。

<手順>
1. コマンドの入力を受けてコマンド実行クラスを取得する
2. 実行クラスのメソッド「execute()」を実行
3. 処理結果をコンソールに出力

これを実装するのに、プロパティファイルとインターフェースを使用します。リファクタリングをしながら実装します。

### リファクタリング開始
ますは、メインメソッドを整理します。
現状は以下のようになっています。
MainMethod V1

public static void main(String[] args) {
    // 今回は作成したこのクラスを使用します。
    Lv2_8_Map myClass = new Lv2_8_Map();

    Scanner input = new Scanner(System.in);

    while(true) {
        System.out.print("入力してください: ");
        String inStr = input.nextLine();
        // プロパティファイルの値を取得する
        String value = myClass.getPropertes(inStr);
        if (value == null) {
            System.out.println("プロパティのキーがありません");
        } else {
            System.out.println("プロパティのキー: " + inStr);
            System.out.println("プロパティの値: " + value);
            continue;
        }
        if ("hello".equals(inStr)) {
            System.out.println("Hello World!");
        } else if (inStr.matches("[0-9].*[0-9]")) {
            String answer = myClass.calculate(inStr);
            System.out.println("答えは:" + answer + "です。");
        } else if ("dir".equals(inStr)) { 
            // Dirコマンドを実装する
            myClass.dirCommand();
        } else if ("title".equals(inStr)) {
            myClass.showTitle();
        } else if (inStr.startsWith("move")) {
            myClass.showPositionInfo(inStr);
        } else if ("bye".equals(inStr)) { 
            myClass.commandHistory();
            break;
        } else {
            System.out.println("想定外の入力です");
            break;
        }
        myClass.addCommand(inStr);
        System.out.println("Next command ... ");
    }
    System.out.print("AP is fiinished. Bye!");
}

まぁ長い。。。[Java Mid Basic](https://zenryokuservice.com/wp/?s=java+mid+basic)を記載する度に追加して来たコードですので、整理されていません。
そんなわけで、まずはSystem.out.println()のコードを1つだけにしようと思います。
下のメソッドを追加します。

/**
 * コンソール出力するメソッド。
 * @param message コンソール出力する文字列
 */
public static void printMessage(String message) {
    System.out.println(message);
}

そしてSystem.out...の部分を全て上のメソッドに置き換えます。メインメソッドで使用するので修飾子「static」をつけます。staticのついたメソッドはアプリケーション内で1つだけ作成することができます。逆にいうと名前が同じでなければいくらでも作れます。
そして、上記のSystem.out.println()System.out.print()の両方を使用しているのでこの2つを使い分けるために引数を追加します。
実装としては以下のメソッドを追記します。

/**
 * コンソール出力するメソッド。
 * @param message コンソール出力する文字列
 * @param withLn 改行するかしないか
 */
public static void printMessage(String message, boolean withLn) {
    if (withLn) {
        System.out.println(message);
    } else {
        System.out.print(message);
    }
}

このように、メソッドの名前が同じで、引数の数が違うメソッドを作成するとき「オーバーロード」と呼びます。

修正したコードは下のようになりました。(メインメソッド)
MainMethod V2

public static void main(String[] args) {
    // 今回は作成したこのクラスを使用します。
    Lv2_8_Map myClass = new Lv2_8_Map();

    Scanner input = new Scanner(System.in);

    while(true) {
        printMessage("入力してください: ", false);
        String inStr = input.nextLine();
        // プロパティファイルの値を取得する
        String value = myClass.getPropertes(inStr);
        if (value == null) {
            printMessage("プロパティのキーがありません");
        } else {
            printMessage("プロパティのキー: " + inStr);
            printMessage("プロパティの値: " + value);
            continue;
        }
        if ("hello".equals(inStr)) {
            printMessage("Hello World!");
        } else if (inStr.matches("[0-9].*[0-9]")) {
            String answer = myClass.calculate(inStr);
            printMessage("答えは:" + answer + "です。");
        } else if ("dir".equals(inStr)) { 
            // Dirコマンドを実装する
            myClass.dirCommand();
        } else if ("title".equals(inStr)) {
            myClass.showTitle();
        } else if (inStr.startsWith("move")) {
            myClass.showPositionInfo(inStr);
        } else if ("bye".equals(inStr)) { 
            myClass.commandHistory();
            break;
        } else {
            printMessage("想定外の入力です");
            break;
        }
        myClass.addCommand(inStr);
        printMessage("Next command ... ");
    }
    printMessage("AP is fiinished. Bye!");
}

次は、プロパティファイルの部分です。プロパティファイルから値を取得、キーが存在しなければ、ワーニングを出力する。という処理です。これをメソッドに切り出します。
ちょいと注意です。メソッドに切り出した時に「myClass」が元の実装だとスコープ外に来てしまうためビルドエラーが出ます。これはmyClassをフィールド変数に引越しすることで回避できます。
private static Lv3_1_RefactorLv2 myClass;
そして、初めに作成した"hello"と入力された時の処理はif文で繋げていたのでこの部分をごっそりメソッドに切り出します。

/**
 * 初めに実装したもの
 * @param cmd 入力コマンド
 */
public boolean basicMethod(String cmd) {
    boolean isEnd = false;
    if ("hello".equals(cmd)) {
        printMessage("Hello World!");
    } else if (cmd.matches("[0-9].*[0-9]")) {
        String answer = myClass.calculate(cmd);
        printMessage("答えは:" + answer + "です。");
    } else if ("dir".equals(cmd)) { 
        // Dirコマンドを実装する
        myClass.dirCommand();
    } else if ("title".equals(cmd)) {
        myClass.showTitle();
    } else if (cmd.startsWith("move")) {
        myClass.showPositionInfo(cmd);
    } else if ("bye".equals(cmd)) { 
        myClass.commandHistory();
        isEnd = true;
    } else {
        printMessage("想定外の入力です");
        isEnd = true;
    }
    return isEnd;
}

これで、メインメソッドの中がスッキリしました。

public static void main(String[] args) {
    // 今回は作成したこのクラスを使用します。
    myClass = new Lv3_1_RefactorLv2();

    Scanner input = new Scanner(System.in);

    while(true) {
        printMessage("入力してください: ", false);
        String inStr = input.nextLine();
        String propStr = myClass.getPropString(inStr);
        if (myClass.basicMethod(inStr)) {
            break;
        }
        myClass.addCommand(inStr);
        printMessage("Next command ... ");
    }
    printMessage("AP is fiinished. Bye!");
}

あとは、下の方に溜まっているメソッドたちをなんとかしたいところですが、先にインターフェースの実装に着手しようと思っています。次回にインターフェースの実装をやります。

でわでわ。。。



テキストRPGを作る〜数秘術の概要まとめ〜

数秘術の普遍数

上記の数値をテキストRPGの作成にしようと思い、調査しました。その結果をまとめます。
ちなみに、数秘術での分類とゲームで使用するパラメータの分類は以下になります。

<ゲームでの分類>

  1. HP: 生命力(ヒットポイント)
  2. MP: 魔法力(マジックポイント)
  3. 力: 物理攻撃力(体力テストから算出)
  4. 素早さ: 攻撃時に、先手を取りやすい
  5. 知力: 知識の応用力、パズルやナゾナゾ、問題の解決をした回数
  6. 協調性: 算出方法検討中、ゲーム内の「パートナー」との連携力を示す
  7. 行動力: 算出方法検討中、ゲーム内の魔法の効力を決定する

<数秘術での分類>

  1. 基本原理
  2. 心理機能
  3. 高次の性質
  4. 様相
  5. エレメント
  6. 支配星
  7. 人物像

参考にしたのは以下の書籍です。

普遍数の種類

上記の書籍によると11種類あり、以下のような特徴を持っています。

<数秘術での分類>

普遍数1=パイオニア

  1. 基本原理: 男性性、陰陽の「陽」、万物を生む因子(種子)、宗教上では、主神、全てを超越した者、モナド
  2. 心理機能: 個性、自立心、目的意識、強さ、独自性、洗濯と意思決定
  3. 高次の性質: 個性化、自分らしさ、自己主張
  4. 様相: 行動
  5. エレメント: 火
  6. 支配星: 太陽
  7. 人物像: 勝者、工程、王

普遍数2=パートナー

  1. 基本原理: 女性性、二元性、揺らぎ、想像力、内省、直感
  2. 心理機能: 協調性、人間関係、バランス、分別、正義感
  3. 高次の性質: 愛情、知恵、実りの豊かさ
  4. 様相: 周囲に配慮して振る舞う
  5. エレメント: 水
  6. 支配星: 月
  7. 人物像: チームプレーヤー、パートナー、」人生の伴侶

普遍数3=伝道者

  1. 基本原理: 結合による想像、三位一体、拡大と生成、知性と行動力の両立
  2. 心理機能: コミニケーションの欲求、心の動きを重視した自己表現
  3. 高次の性質: 愛情、知恵、実りの豊かさ
  4. 様相: 話すこと
  5. エレメント: 風
  6. 支配星: 土星
  7. 人物像: コミュニケータ、講師、牧師、ダンサー、コディアン

普遍数4=建設者

  1. 基本原理: 物質界、現実、個体、正方形と立方体、考えを形にする、人間の4機能(肉体、感情、知性、霊性)
  2. 心理機能: 自制、他人とは距離を置く、一人一人の個性を認める
  3. 高次の性質: なし
  4. 様相: 不活発
  5. エレメント: 地
  6. 支配星: 地球
  7. 人物像: 科学者、彫刻家、農業従事者、園芸家、技術者

普遍数5=自由人

  1. 基本原理: 活発、創意工夫、創造性、外交的、知識欲。多芸多才、好奇心旺盛、情報伝達力に優れる
  2. 心理機能: 充実した人生を送りたいという欲求、万人の自由の権利を守ろうとする
  3. 高次の性質: なし
  4. 様相: 想像力
  5. エレメント: エーテル(風)
  6. 支配星: 水星
  7. 人物像: 作家、詩人、幻視家、冒険家、発明家、理想主義者

普遍数6=奉仕者

  1. 基本原理: 神が創造に費やした日数、六芒星、創造性、芸術、生命のリズム
  2. 心理機能: 無私の精神を発揮する
  3. 高次の性質: なし
  4. 様相: セクシーでエロティック
  5. エレメント: 地
  6. 支配星: 金星、美、愛、平和、芸術、奉仕の星
  7. 人物像(適職): 芸術家、弁護士、外交官、ヒーラー

普遍数7=夢想家

  1. 基本原理: 地球から見える7つの惑星(日〜土)、7、チャクラ(7つ)
  2. 心理機能: 本質を追求、真理に迫る、人と神をつなぐ
  3. 高次の性質: なし
  4. 様相: 活動的、抽象的な考え方をする
  5. エレメント: 風
  6. 支配星: 海王星
  7. 人物像(適職): 哲学者、科学者、教育者、著述家

普遍数8=実業家

  1. 基本原理: 立方体、4つ目の次元に時間を加える、DNAの螺旋
  2. 心理機能: 意志力と実行力
  3. 高次の性質: なし
  4. 様相: ストイック、人の上に立つ
  5. エレメント: 水
  6. 支配星: 土星
  7. 人物像: 大企業のCEO(成功経営責任者)、金融関係者、実利主義者、裁判官

普遍数9=調停役

  1. 基本原理: 最も洗練されている、完成と終了、ミューズ(ギリシャ神話の9柱の女神)
  2. 心理機能: 控えめ、自制、無私
  3. 高次の性質: なし
  4. 様相: 行動
  5. エレメント: 火
  6. 支配星: 火星、軍神マルスの星
  7. 人物像: 改革者、人道主義、自由の闘士、理想主義者、外科、精神科医

普遍数11=幻視家

  1. 基本原理: 直感、予知、予言、霊感、真理、美、陰陽のバランス、普遍的な正義の象徴
  2. 心理機能: 高次の意識状態を洞察する
  3. 高次の性質: なし
  4. 様相: 人生の意味を考える
  5. エレメント: 水と風の混合
  6. 支配星: 冥王星
  7. 人物像: カウンセラー、叡智を授ける導師

普遍数22=設計者

  1. 基本原理: 天地を結ぶ、大きな理想を実現する、マスタービルダー
  2. 心理機能: 抽象的な考え方を具現化し人の役に立てようとする
  3. 高次の性質: なし
  4. 様相: 深謀遠慮
  5. エレメント: 火と地
  6. 支配星: 冥王星
  7. 人物像(適職): 建築家、大規模な人道支援の設立者、大学の学部長

数字の出し方

上記の普遍数が要素にあたり、以下の「カルマ数など」の値を算出して、その人を占うようです。
というわけで、算出方法について見てみます。

用意するもの

・アルファベットのブロック体で書いた出生時の名前。
・紙と鉛筆

手順

<注意>
本物の数秘術ではわかりませんが、ヘボン式ローマ字で記載、計算します。別に占いをやるわけではないので何を使用しても関係ないので(笑)

  1. 準備で用意したアルファベットの文字列の母音を上記の表から変換した数字を合計します。
    TAKUNOJI = 1 + 3 + 6 + 9
    ここの値が2桁になったので一桁にします。
    1 + 3 + 6 + 9 = 19 = 10
    1 + 0 = 1
  2. 子音の数を合計します。
    TAKUNOJI = 2 + 2 + 5 + 1
    ここで注意ですが、たくのじは苗字がありません。苗字がある人は、名前の時と同様に苗字算出してください。

そして、算出した名前と苗字の数を合算、一桁に直します。わかりづらいので、たくのじに苗字をつけます「七志野」という苗字にします。なので以下のような形で算出します。
<名前>
N 5A 1 N 5 A1 S 1 H 8 I9N 5 O 6 T 2 A 1 K 2 U 3 N 5 O 6 J 1 I9
<前半>
母音:NANASHINO => 1 + 1 + 9 + 6 => 17 = 1 + 7 => 8
子音:NANASHINO => 5 + 5 + 1 + 8 => 19 => 1 + 9 => 10 => 1 + 0 => 1
<後半>
母音:TAKUNOJI => 1 + 3 + 6 + 9 => 19 => 1 + 9 => 10 => 1 + 0 => 1
子音:2 + 2 + 5 + 1 => 10 => 1 + 0 => 1
<前半>と<後半>を合計して算出1 + 8 => 9
というわけで「七志野たくのじ」の人格数は「9」となります。

以降「算出方法」として記載している計算式は「七志野たくのじ」を計算した時のものを記載しています。

カルマ数など

  1. 人格数: 生まれつきの性格、人間関係の傾向、物の見方や行動パターン(上記の例を参照)
  2. ハート数: この世に生きる喜びをどのように味わい、表現するか?という傾向を示す
    <1. 算出方法>
    名前を数字に変換した時に出てきた数字の母音部分の合計
    上記の<名前>部分より1 + 1 + 6 + 1 + 3 + 6 + 9 => 27 => 2 + 7 => 9
  3. 運命数: 生まれながらに持った特徴
    <2. 算出方法>
    生まれた月日を計算
    7/12 => 7 + 1 + 2 => 10 => 1 + 0 => 1
    同様に年
    1942年 => 1 + 9 + 4 + 2 => 16 => 1 + 6 => 7
    運命数=「7」
  4. 意思数: うちなる自己=意思、やる気とか行動に出るものとは違う
    <3. 算出方法>
    名前の人格数を出した時の子音の数の合計
    <名前>部分より5 + 5 + 1 + 8 + 5 + 2 + 2 + 5 + 1 => 34 => 3 + 4 => 7
    意思数=「7」
  5. 特性数: 人生の中で重要な意味を持つ分野
    <4. 算出方法>
    名前の人格数を出した時の出てきた回数の多い数字上位2つ、ただし、6回以上同じ数字があった場合は1つ
    NANASHINO TAKUNOJI => 1(4回), 5(4回)
    特徴数=「1、5」
  6. 欠落数: 5とは反対の分野
    <5. 算出方法>
    人格数を出した時の出て来なかった数字
    NANASHINO TAKUNOJI => 4、7
    欠落数=「4、7」
  7. 成熟数: 人格数、運命数を要素に含む総合的なもの
    <6. 算出方法>
    人格数 + 運命数で算出9 + 7 => 16 => 1 + 6 => 7
    成熟数=「7」

上記までの内容に出てきた共通するもの

  1. 太陽系の惑星(日〜土の惑星)
  2. 火水風土の四大元素と東西南北
  3. ギリシャ神話の神々

まとめ

ここに出てきた、「分類」と「計算した結果」「出てくる数値」をテキストRPGのプロパティ(ステータスや職業、属性)に関連付けて使用したいというものです。

そして、各普遍数に対応するステータステンプレートを作成し、ゲームに反映しようと企んでいる次第です。

でわでわ。。。

関連ページ

UMLで設計を行う



JavaScript Google Maps API 〜Map表示の(実装)方法〜

イントロダクション

前回はGoogleMapのAPIを使用する準備を行いました。
早い話が、APIのキーを取得しました。
取得した後に、ちょいと順序が違ってきてしまったので改めて、実装について触れようと思った次第です。

Google Maps JavaScript API

Googleから提供されているAPIドキュメントを見てみると、実装のサンプルがそのまま乗っています。
なので今まで深く触れていませんでした、が!どんな処理なのか今一度見てみようと思います。
上記のリンクより、こちらのリンクはJSFidleというものでHTML, CSS, JSが見れる優れものでした。

そして、上記のリンク先のコード配下になります。(コピペ)

      var map;
function initMap() {
    // Mapの生成処理(HTMLのDIVタグのid="map")
    map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });
}

コードの内容

DIVタグにMapを埋め込みます。そのために使用するコードは下の部分です。

new google.maps.Map(DOMエレメント)

この処理で、DOMエレメント=DIVタグにマップを埋め込みます。(作成します)
そして、第二引数のJSONデータの部分について、これは見ればわかる人はわかるでしょう。(自分はこのようなのを見て理解するのに時間がかかったクチです(笑))

{ center: {lat: -34.397, lng: 150.644}, zoom: 8}

これをつなげると、上のようなコードになります。ちなみに開業しているのでぱっと見が違います。(見やすい)

map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });

このコードで、マップの作成ができたら次は。。。

Marker追加

マーカーの追加をやりたいと思うのが人情。。。(自分だではないと思います。)
そして、マーカーの追加は下のようにやるようです。上記のリンクよりコピペです。

// Initialize and add the map
function initMap() {
  // The location of Uluru
  var uluru = {lat: -25.344, lng: 131.036};
  // The map, centered at Uluru
  var map = new google.maps.Map(
      document.getElementById('map'), {zoom: 4, center: uluru});
  // The marker, positioned at Uluru
  var marker = new google.maps.Marker({position: uluru, map: map});
}

// The marker, positioned at Uluruの部分から下がマーカー追加処理になります。
1行で終わるのでとてもわかりやすいと思います。Map作成時と同じような形なのでここの説明は割愛します。

InfoWindow追加

そして、マーカーの次は情報ウィンドウが表示したい。。。
これもリンク先にサンプルコードからしてあります。
同様にコピペしました。

// This example displays a marker at the center of Australia.
// When the user clicks the marker, an info window opens.

function initMap() {
  var uluru = {lat: -25.363, lng: 131.044};
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: uluru
  });

  var contentString = '<div id="content" >'+
      '<div id="siteNotice"  >'+
      '</div >'+
      '<h1 id="firstHeading" class="firstHeading"    >Uluru</h1    >'+
      '<div id="bodyContent">'+
      '<p><b>Uluru</b>, also referred to as <b>Ayers Rock</b>, is a large ' +
      'sandstone rock formation in the southern part of the '+
      'Northern Territory, central Australia. It lies 335 km (208 mi) '+
      'south west of the nearest large town, Alice Springs; 450 km '+
      '(280 mi) by road. Kata Tjuta and Uluru are the two major '+
      'features of the Uluru - Kata Tjuta National Park. Uluru is '+
      'sacred to the Pitjantjatjara and Yankunytjatjara, the '+
      'Aboriginal people of the area. It has many springs, waterholes, '+
      'rock caves and ancient paintings. Uluru is listed as a World '+
      'Heritage Site.</p>'+
      '<p>Attribution: Uluru, <a href="https://en.wikipedia.org/w/index.php?title=Uluru&oldid=297882194">'+
      'https://en.wikipedia.org/w/index.php?title=Uluru</a> '+
      '(last visited June 22, 2009).</p>'+
      '</div>'+
      '</div>';

  var infowindow = new google.maps.InfoWindow({
    content: contentString
  });

  var marker = new google.maps.Marker({
    position: uluru,
    map: map,
    title: 'Uluru (Ayers Rock)'
  });
  marker.addListener('click', function() {
    infowindow.open(map, marker);
  });
}

このコードは以下の手順で処理を行っています。

  1. ウルル(地球のへそ)の位置(座標)をJSONで作成
  2. マップを作成
  3. HTMLコンテンツを作成
  4. 情報ウィンドウの生成
  5. マーカーの作成と情報ウィンドウの追加

こんな処理を行っています。
表示結果はリンク先にありますのでそちらを確認していただきたく思います。ぱっと見だけであれば、下にキャプチャを貼っておきます。

この画面はこちらに本物のサンプルがあります。

こんな感じです。

でわでわ。。。



JavaScriptでユーザー認証 〜シンプルな認証処理〜

イントロダクション

最近作成している、GoogleMapを使用したページがある程度見れるものになってきたので、そろそろと公開できるような形にしたいと思い、ちょいとギミックを追加します。

パスワード認証

皆さんご存知「パスワード認証」を実装します。
これを実装すれば、「<入力>」「<送信>」などのボタン押下で、不特定多数の人に地図データを登録される心配がなくなります。

パスワード認証の実装

シンプルにボタンをクリックしたらパスワード入力ダイアログボックスが表示され、入力→認証という流れで処理を行います。
パスワードは見つけられないように、サーバーサイド(PHP)で持つことにします。つまり実装としては下のような感じになります。

認証準備

まずは、入力とデータの送信が出来ないようにボタンを非表示にします。
これはシンプルにHTMLでstyle="display: none"を設定してやります。具体的には以下のようなHTMLコードに変更します。
<Before>

        <button class="butt1" onclick="sideWinHandle(sideWin)"><入力>   </button>
        <button class="butt2" onclick="postData()"><送信>  </button>

<After>

        <button name="loggedIn" class="butt1" onclick="sideWinHandle(sideWin)" style="display: none;"><入力></button>
        <button name="loggedIn" class="butt2" onclick="postData()" style="display: none;"><送信></button>
        <button onclick="openLoginForm()"><Login> </button>

そして、ボタン押下時に走らせる処理onclick="openLoginForm()"を設定します。
これが出来たら、あとはJSの実装のみです。

ズバリ下のような実装を追加します。ちょっと特殊なのはprompt()です。

function openLoginForm() {
var input = prompt("Login Form");
    if ('パスワード' === input) {
        var loggedInButton = document.getElementsByName("loggedIn");
        loggedInButton.forEach(but => {
            but.style = "display: visible";
        });
    }
}

これで下のように動きます。

  1. 「Login」ボタンを押下
  2. プロンプトが開き、入力を求める
  3. 入力した値がJSのinput変数に代入される(上のコード参照)

シンプルに実装できていると思います。

問題が1つ

この実装だと、パスワードがバレバレで、セキュリティ的にアウトです。しかし、今回の実装はあくまでサンプルなのでまぁよしとします。

実際の使用方法

実際は入力して判定するときにクライアント側ではなく、サーバー側(PHPなど)で判定を行います。
今の自分の実装だと、入力した値をサーバーに送信(Ajax通信)して判定結果をもとに画面の表示・非表示を切り替えるなどを行うのが、安全なやり方だと思います。

ぢつは。。。

今の実装をしていて気がつきました。「ハナっからこーすればいいよな?」と思っております。初めの初期表示時に処理を行うことに執着していて気がつかなかった次第です。



Java Mid Basic〜リファクタリングLv2構成を考える〜

イントロダクション

前回までに、UMLの書き方などを理解しました。使用しているUMLツールは「Star UML」です。
プログラムを書くのにUMLを使って「どのようなクラス構成にするか?」を考えます。
まずは、現状のクラス構成を図にしてみます。「現状」というのは作成中のコンソールゲーム(学習用)です。

現状のクラス図

動きとしては、下の動画のように動きます。

<仕様>

  • ・アプリが起動したらユーザーの入力を待つ
  • ・入力(コマンド)によりコンソール出力する内容を切り替える
  • ・hello->"Hello World"
  • ・計算式(「1 + 2」など)->計算結果
  • ・bye->実行したコマンドの一覧を出力してアプリ終了
  • ・title->テキストファイルの中身を出力
  • ・上記以外->"想定外の入力です"を出力し、次のコマンド入力を待機

クラス図にすると下のような形になります。

ここから、どのようにクラス構成を作れば良いか考えます。

リファクタリング

「基本的」というのは「土台になる」という意味で使用しています。そして、今回のリファクタリングを行うの時の
基本的な考え方は以下の通りです。

  1. 1機能につき、1クラス
  2. 作成するクラス(機能)は再利用できるように作る
  3. JavaDocなどを使用して、新規でコードを見る人にもわかるようにコーディングする

現状の問題点

クラスが1つだけなので、大雑把に4機能(上の画像内の<>で囲っているもの)がこのクラスの中にあり「ごちゃー」としていて、まるで汚い部屋のようです。
まずは整理整頓ですね、そして、クラスを複数作成するのでこの部分クラスとクラスの繋がり部分をうまく作成してやる必要があります。

さらなるアイディア

整理整頓を行うついでに「こーすれば!」というものも組み込むともっと良いと思います。

関連ページ

UMLツール Star UMLを使う〜

UMLツール Star UML〜ユースケース図を書いて見た〜



RPG人名録にある、出典ゲーム一覧

RPGを学ぶ

テキストRPGの作成に向けて学習を始めました。
そして、色々と彷徨っているうちに以下の本に出会いました。

RPG人名録

この本について触れる記事を記載しました。目的は「ロールプレイングゲームを知る」ことです。

しかし、記事的に商品情報も載せたいので記載すればよかったのですが、こちらのブログに記載することにした次第です。

上の本は、テレビゲームが普及してきた時代に発行された本で、RPGという言葉が社会に認知されてきた頃の本のようです。現代(2019年代)でも現役のゲームもあります。

歴史を紐解いて見るのも良いですね。

出典ゲーム一覧

聞いたことのあるゲーム名が結構あるのにビックしています。。。

何を学ぶのか?

RPGの世界観というより、どんな風にゲームをプレイしているのか?そしてどのようにゲームの展開をしているのか?
ゲームのあふれている現代では大体がテレビゲームを始めるのに「マニュアルを読んで理解」なんていうことはありません。(と思う)便利な時代ですから「面倒なものは。。。」となりがちなようですが、一概には言えないようです。
実際に「TRPG」なんていうものも「マニュアルを読んで理解」が必要だけど、人気のあるジャンルです。

つまり

ゲームの世界をどのようにプレーヤーに見せるのか?を学びたいと思っている次第です。

でわでわ。。。



UMLツール Star UML〜ユースケース図を書いて見た〜

ユースケース

ユースケース図は、大雑把に、ユーザーとシステムの関連、及び「どのように使用するか?」を絵にします。
これを作っておくと「もともと何をしようとしてたっけ?」となった時に便利です。
【余談】
プログラムを作成していると、PCの内部的なところに集中してしまうため、現実での流れが見えなくなってしまうことが多々あります。なので、いつでも「どうだったっけ?」を引き出せるようにしておくと便利なのです。

書き方

UMLの書き方を参照してください。ここには現在作成中のウェブアプリのユースケースを記載しています。
GoogleMapを使用した札幌のライブハウス紹介サイトです。

ユースケース図の書き方

Start UMLでの書き方を記載します。
とりあえずは、アプリケーションを起動します。

そして、上部にある「Model」をクリックします。メニューが出てくるので、「Use Case Diagram」を選択します。現在青くなっているところは「アクティビティ図」なのでちょっと違います。

するとしたのようなメニューが出てくるのでこれらを選択して画面に追加していきます。

最終的には(現時点で)以下のような図ができました。

細かい部分は、アクターなどのダイヤグラムを選択した時に右下にプロパティを設定する部分が表示されるので、これらに値を入れます。

こんな感じで作成していけると思います。

でわでわ。。。



UMLツール 〜Star UMLを使う〜

イントロダクション

突然ですが、自分はMacのノートパソコンを使用しています。
なので、WindowsでのUMLツールが使えません。というかWindowsはデスクトップなので持ち歩きができない。。。が故にMacをメインに使用しています。
何が言いたいかというとMacでのUMLツールはWindowsと違うということが言いたかったのです。

UMLツール

WindowsでのUMLツールは有名なものが沢山ありますが、Macはイマイチ(だと思っているだけかも?)ですが、Start UMLというのを見つけたのでそれを使用しています。(使用し始めました)。

設計図

ここ数日Java Mid Basicという記事を記載しています。そして「コンソールゲームを作成しながらJavaの基本を理解しよう」をコンセプトにしているので、ゲームを作成しながらになります。
そして、ついに頭の中だけではまとまりきらなくなってきたのでUMLを使用して設計しつつ基本をやりつつ。。。となった次第です。

インストール

MacなのでAppStoreから「start uml」で検索すれば一発です。インストール後に使い方など、すべて英語なので一苦労です。「じゃ他のを使えば?」と声が聞こえてきそうですが、UMLのユースケース図、クラス図、アクティビティ図などいろんな種類を作成するのに探してみるとこのツールが一番無難だったので使用しています。、、

クラス図を作る

UMLの書き方に関してはこちらを参照してきただきたいのですが、今回はStart UMLでの書き方に注目して記載します。
まずは初期表示画面です。バージョン情報なども表示しました。(ヘルプから表示できます)

この画面で、兎にも角にもクラス図を作成します。

左のツールボックス(Tool Box)のすぐ下に「Class」とあるのでそれをクリックして作成します。
「Class」と青い色がついている部分にクラス名を入力してクラスを作成します。

画面の両端に上のような領域があります、ここで細かい部分を確認、使用することができるようです。
現在の画面は下のようになっています。

単純にクラスが1つあるだけになっています。
ここに、必要なフィールドを追加します。一応、現在作成しようとしているのは「テキストRPGのプログラム設計」です。
最終的にどのような形にするか?を考えるための設計です。
正直のところは、どのような設計にするか考えていないので設計はできない状態ですが、その前にStar UMLの使い方を理解する必要があるので。。。
作成したクラスを右クリックします。

「Attrubute」を選択すると、フィールド(メンバ変数)を定義できるようです。

同様に「Operation」でメソッドを定義。

画面の右下にある「Properties」の部分でステレオタイプを入力できます。

ループ処理

そして、シーケンス図でのループ処理は「Combined Fragment」を使用して作成できます。

細かい部分は今後記載していきます。
でわでわ。。。



Java Mid Basic 〜Lv2_8_Javaの基本(Mapを使う)ゲームループ付き〜

イントロダクション

前回は、ファイルの読み込みを行いました。
こんな感じで動きました。

Mapを使う

今回は、Mapを使用します。java.util.Listと同じようにインターフェースです。このMapインターフェースは実装クラスにHashMapがあります。詳細はリンク先の「既知のすべての実装クラス」を見てください。
そして、今回はこのMap(HashMap)を使って、ゲーム上のマップ(目には見えない)を表現することを考えたいと思います。

目に見えないマップ

通常、ゲームのマップといえばキャラクターが動いて「〜の街に入る」とかの動きをするのですが、今回はテキストRPGを作ろうとしているので、その部分を表示しません。全て「プレーヤーの想像」に映し出せるようになんとか「文章」を考える必要があります。そしてBGMも大切です。。。が、まずは「Javaを理解する」を目的としているのでプログラムの方を優先します。
「目に見えないマップ」とは、プログラムの処理上では存在しているけど、ユーザー(プレイヤー)は見ることができない。。。という意味です。
例えば、ユーザーにDBからデータを取得するためのSQLを見る必要はないし、機密情報でもあるので画面には表示しません。
同様に、今回のコンソールゲームでは、なるべくプレーヤーの想像の中に「画面」を描画してもらえるように作成するので、目に見える マップは邪魔以外の何物でもないのです。(そういうコンセプトなのです(笑))

実行結果

処理内容

作成したコードはGitにあります。

/** 現在位置の情報を返却する */
public void showPositionInfo(String pos) {
    if (placeInfo == null) {
        System.out.println("現在位置の情報が設定されていません。(placeInfo = null)");
        System.exit(-1);
    }
    // 入力が「move 数字」になっていない場合はエラー
    if (pos.matches("move [0-9]") == false) {
        System.out.println("入力コマンドが不適切です。move [0-9]で入力してください");
        System.exit(-1);
    }
    // から文字を削除
    String place = pos.replaceAll("move", "");
    // moveを削除
    place = place.replaceAll(" ", "");
    System.out.println(placeInfo.get(place));
}

初めのif (placeInfo == null) {はフィールド変数にインスタンスが設定されていない場合の例外対応です。想定外の場合というのを考慮に入れています。が他の部分など、全対的にどのような流れで処理を行うのか考えていない状態なので、まぁ、勘弁してください。
そして、コマンドが「move 1」のように「1」の部分が数字で入力されている場合この時にMapに登録されている値を表示します。
ちなみにMapに登録する処理は以下のコードで実装しています。

/** 現在位置の情報を保持するMapを作成 */
public Map getInfoMap() {
    HashMap map = new HashMap<>();
    map.put("1", "マス1");
    map.put("2", "マス2");
    map.put("3", "マス3");
    map.put("4", "マス4");
    return map;
}

HashMapのインスタンスを生成して、”1”のキーには値: "マス1"を設定します。同様に2〜4まで設定したところで設定処理を終了しています。
プログラムの作成は今までにやってきているので、下の「関連ページ」を参照してください。

でわでわ。。。

関連ページ



PHP Image File 〜iPhoneやAndroidでの画像送受信の問題〜

イントロダクション

GoogleMapを使用して見つけた場所(店など)をGoogleMapに登録するブラウザアプリケーションを作成中です。
途中まで作成していて携帯からアップロードした写真のデータが表示できない事象に遭遇しました。

スマホの写真(拡張子)

iPhoneではHEICを使用していました。Androidも同じものを使用している記事を見かけましたが、確認はしていません。
とりあえずのところは、画像を編集するのに提供されているコンバーターを使用する必要があり、既存のプログラムにも手を入れる必要があるということがわかりました。

既存プログラム

作成したプログラムのことですが、Ajax+PHPでの実装を行なっており、詳細に関してはこちらに記載しております。

問題

問題になっていることは、画像を送受信して表示できるものとできないものがあるということです。送受信するのはbase64でのデータをサーバーから送信しクライアントサイドでそれを表示しています。がスマホからサーバーに送信、DBに(BLOBで)登録したものは画面に表示できない事象にあってしまいました。テクノロジー的にも上記のようなファイルコンバートが必要になるようです。

結局

無理をして画像を表示する必要もないと判断しました。
ブラウザーからの入力はテキストのみにして、Youtubeの動画を表示するようにしました。
画面より、Youtubeの画像IDを入力しGoogleMapのinfoWindowに表示する方法をとりました。
とりあえずは、問題もなく動いているのでこの方法でサイトの方を作成していく予定です。

でわでわ。。。

関連ページ