【北海道大戦】マップデータを作成

そもそも、北海道大戦って何?

北海道の全市町村179ありますが、それらが全道統一を目指してバトルしたらどうだろう?って思い付きで考えたゲームです。

とりあえず、Excelで北海道マップを作成しました。

Excel方眼紙はこうやって使う。

でも、このままではデータとして使用できないので、番号に置き換えます。

ちゃんと179市町村ありました。

右に市町村の一覧があり、それらに番号が振られており、マップ上の市町村に番号を設置しました。

これをさらにExcelマクロで加工します。

イメージとしては、Json形式となるようにマップを検索し、X座標とY座標をまとめます。

Sub output()
    Dim TownArea As Object
    Dim Rows As Integer
    Set TownArea = Worksheets("Sheet1").Range("AU1", Range("AU1").End(xlDown).End(xlToRight))
    Rows = TownArea.Rows.Count
    
    Dim Area As Object
    Dim RightLength As Integer
    Dim DownLength As Integer
    Set Area = Worksheets("Sheet1").Range("B2:AS36")
    RightLength = Area.Columns.Count
    DownLength = Area.Rows.Count
    
    Dim WS2 As Object
    Set WS2 = Worksheets("Sheet2")
    Dim WriteLine As Integer
    WriteLine = 1
    WS2.Cells(WriteLine, 1).Value = "{""list"":["
    WriteLine = WriteLine + 1
    
    For R = 1 To Rows
        Dim number As Integer
        Dim name As String
        number = TownArea.Cells(R, 1).Value
        name = TownArea.Cells(R, 2).Value
        
        WS2.Cells(WriteLine, 2).Value = "{""name"" :"""
        WS2.Cells(WriteLine, 3).Value = name
        WS2.Cells(WriteLine, 4).Value = """, ""point"" :["
        
        For RL = 1 To RightLength
            For DL = 1 To DownLength
                If Area.Cells(RL, DL).Value = number Then
                    WS2.Cells(WriteLine, 5).Value = "{""x"" :"
                    WS2.Cells(WriteLine, 6).Value = RL - 1
                    WS2.Cells(WriteLine, 7).Value = ", ""y"" :"
                    WS2.Cells(WriteLine, 8).Value = DL - 1
                    WS2.Cells(WriteLine, 9).Value = "}"
                    WS2.Cells(WriteLine, 10).Value = ","
                    WriteLine = WriteLine + 1
                End If
            Next
        Next
        WS2.Cells(WriteLine - 1, 10).Value = "]},"
    Next
    WS2.Cells(WriteLine - 1, 10).Value = "]}"
    WS2.Cells(WriteLine, 1).Value = "]}"
End Sub

これをテキストにコピーして、セル間のタブを置換処理で削除すれば、Jsonとして完成します。

整形したらこんな感じになりました。

これでようやくマップデータとして使用できそうです。

昨日は一日中ストレッチをしていました。

ストレッチの力は偉大。

特に肩と首の周りの治療を行っているので、その辺りを積極的に動かしたり、筋肉を伸ばしたりしていました。

まぁ、夏日であったと言うのもあったけど、これだけで結構汗が出てきまして、

その甲斐もあってか、体重が86kgまでダウンしました。

そして、今日はお酒を飲むつもりは無い!

明日さらにダウンするかも。

最近はというと、パソコン作業がだいぶ伸びてきました。

メインでやっているのは、

  • ピクロス解析ツール(C#)
  • ダイエット支援ツール(PHP / Laravel)
  • ラズパイ

この3つ。

さらに、北海道大戦とかいうゲームを練っている最中です。

その影響でゲームをする時間が少なくなり、

プレイするゲームをいくつか削除しました。

今プレイしているのは、

  • マインクラフトダンジョンズ(PC)
  • アリスギアアイギス(PC)
  • 禍つヴァールハイト
  • きららファンタジア
  • プリンセスコネクト!Re:Dive
  • ドールズフロントライン
  • De:Lithe
  • この素晴らしい世界に祝福を!ファンタスティックデイズ
  • エクゾスヒーローズ
  • ドラクエ6
  • バンドリ!ガールズバンドパーティ!!(iPad)
  • HeyDay(iPad)
  • クラッシュロワイヤル(iPad)

それでも容量ギリギリです。

64GBじゃ足りません。

ってか、リストアップしてみたらまだまだ多すぎやん。

でも、バックグラウンドで動かしたり、自動で周回できる物が多いので、そんなに負担にはならない物が多いです。

あとは、ジョギングを始めました。

夕方に4キロぐらい走ってます。

しかし、ジャージのズボンに穴が空いているのに気がついて

ちょうとおしりのところ。

また買い足ししなくちゃいけないなぁと思っています。

給付金振り込みはよ。

もう郵送から1週間ぐらい経ったけどなぁ。

【ラズパイ】【GLCD】ASCII文字列を表示する

前回までの状況はこちら。

今回は複数の文字を表示させます。

これもサンプルコードをPython用に書き換えました。

def GLCDPuts(Xp, Yp, text):
    x = Xp
    for s in text:
        GLCDPutc(x, Yp, s)
        x += 6

やってることはそんなに難しくはありませんでした。

文字と文字の間隔は1ドット空けています。

def __main():
    PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCDInit()
    GLCDDisplayClear()
    GLCDPuts(40, 10, "ABCDE")

    try:
        while True:
            time.sleep(1.0)
    except KeyboardInterrupt:
        GPIO.cleanup()

【バンドリ】【ガルパ】6/3のハロハピ放送局で公開された情報まとめ

花火、きれいでしたねー

さて、いよいよRASの実装が近づいてきましたよ~

新カバー楽曲

ノスタルジックレインフォール

テレビアニメ「恋は雨上がりのように」のOPテーマです。

予想レベル24

新バンドRAISE A SUILEN

ほぼほぼバンドリ3rdシーズンの内容ですね。

EXPOSE ‘Burn Out!!!’がイベント開始と同時に実装されます。

予想レベル26

同時にカバー曲「ヒトリノ夜」が実装されます。

アニメ「GTO」のOPテーマでした。

カバーコレクションに収録されている曲ですね。

予想レベル25

イベント後編にはバンドリ3rdシーズンの13話で披露されたBeautiful Birthdayが実装されます。

まとめ。

イベントは6月10日開始です。

次のイベントですね。

星配布と無料ガチャは嬉しい。

イベントで勝ち抜くにはメンツが必要。

ガチ課金勢には敵わないけどな。

【ラズパイ】【GLCD】ASCII文字を表示する

前回までの状況はこちら。

PythonコードをgitHubにアップしました。

https://github.com/takishita2nd/GLCD

サンプルソースにフォントのビットパターンデータがありましたので、これを置換処理を使ってPython用に書き換えました。

https://github.com/takishita2nd/GLCD/blob/master/Font.py

これを使用して、ディスプレイにアスキー文字を表示させます。

    [ 0x7e, 0x11, 0x11, 0x11, 0x7e ], # A   0x41

1文字8×5のサイズになっているようです。

お試しで表示させてみました。

chara = [0x7e, 0x11, 0x11, 0x11, 0x7e]

def __main():
    PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCDInit()
    GLCDDisplayClear()
    addr = 0
    SelectIC(1)
    SetPage(0)
    for c in chara:
        SetAddress(addr)
        WriteData(c)
        addr += 1

    try:
        while True:
            time.sleep(1.0)
    except KeyboardInterrupt:
        GPIO.cleanup()

このデータを表示するサンプルコードをPython用に書き換えました。

def GLCDPutc(Xp, Yp, c):
    code = ord(c)
    #ページ内のラインを選択
    L = Yp % 8
    #8×5のキャラクター文字を描画する
    for i in range(5):
        SetLocation(Xp + i, Yp)
        f = Font.Array[code - 0x20][i] << L
        WriteData(f)
        if (L != 0) & (SetPg < 7):
            SetPage(SetPg + 1)
            SetAddress(SetCol)
            f = Font.Array[code - 0x20][i] >> (8 - L)
            WriteData(f)
def SetLocation(Xp, Yp):
    global SetPg
    global SetCol
    cs = 0
    #チップの選択とカラムのアドレスの処理を行う
    if Xp < 64:
        #左側(IC1)を選択
        cs = 1
        SetCol = Xp
    else:
        #右側(IC2)を選択
        cs = 2
        SetCol = Xp - 64
    #ページとラインの選択
    SetPg = Yp // 8
    #LCDに描画するアドレスの位置を設定
    SelectIC(cs)
    SetPage(SetPg)
    SetAddress(SetCol)

好きな場所に文字を書くことができます。

ページ跨ぎとか、チップ跨ぎにも対応しているようです。

def __main():
    PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCDInit()
    GLCDDisplayClear()
    GLCDPutc(20, 5, "B")

    try:
        while True:
            time.sleep(1.0)
    except KeyboardInterrupt:
        GPIO.cleanup()

【LARAVEL】【ダイエット支援】データ一覧画面からデータ削除

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/diet-mng

データ削除処理を作成します。

とはいっても、もう追加、編集処理が出来上がっているので、そんなに難しくありませんでした。

ぱぱっとやってしまいます。

    public function delete($id, $user)
    {
        $model = $this->getItemById($id);
        $this->detachToUser($model, $user);
        $model->delete();
    }
    /**
     * データを1件削除する
     */
    public function delete(Request $request)
    {
        $this->weightManagement->delete($request->contents["id"], Auth::user());
        
        return response()->json();
    }
Route::post('api/weight/delete', 'Weight\ApiController@delete');
<template>
    <div>
        <div id="overlay" v-show="show">
            <div id="content">
                <p v-if="error_flg == true" class="error">
                    <ui>
                        <li v-for="error in errors">{{ error }}</li>
                    </ui>
                </p>
                <table class="edit">
                    <tbody>
                        <tr>
                            <td>日時</td>
                            <td>{{contents.date}}</td>
                        </tr>
                        <tr>
                            <td>体重</td>
                            <td>{{contents.weight}}</td>
                        </tr>
                        <tr>
                            <td>体脂肪</td>
                            <td>{{contents.fat_rate}}</td>
                        </tr>
                        <tr>
                            <td>BMI</td>
                            <td>{{contents.bmi}}</td>
                        </tr>
                    </tbody>
                </table>
                <p id="command">
                    <button @click="clickDelete">OK</button>
                    <button @click="closeModal">キャンセル</button>
                </p>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    props: ['show'],
    data() {
        return {
            errors: [],
            error_flg: [],
            param: {},
            contents: {
                date: "",
                weight: "",
                fat_rate: "",
                bmi: "",
            },
        };
    },
    created: function() {
    },
    methods: {
        dataSet: function(data) {
            this.contents = data;
        },
        clickDelete: function() {
            var self = this;
            this.param.contents = this.contents;
            axios.post('api/weight/delete', this.param).then(function(response){
                self.closeModal();
                self.$emit('update');
            }).catch(function(error){
                self.error_flg = true;
                self.errors = error.response.data.errors;
            });
        },
        closeModal: function() {
            this.$parent.showDeleteDialogContent = false;
        },
    }
}
</script>
            <weight-delete-dialog-component ref="deleteDialog" :show="showDeleteDialogContent" @update="invokeUpdateList"></weight-delete-dialog-component>
        onClickDelete: function(id) {
            var editData = {};
            this.datalists.forEach(element => {
                if(element.id == id){
                    editData.id = id;
                    editData.date = element.date;
                    editData.weight = element.weight;
                    editData.fat_rate = element.fat_rate;
                    editData.bmi = element.bmi;
                    return true;
                }
            });
            this.$refs.deleteDialog.dataSet(editData);
            this.showDeleteDialogContent = true;
        },

いいかんじです。

【C#】【ピクロス】【ALTSEED】データ入力UIの改善

前回までの状況はこちら。

最新ソースはこちら。(gitHub)

https://github.com/takishita2nd/Picross

いままではデータ入力値がパレットの陰に隠れて見えづらい、という問題をうすうすと感じていましたが、これを修正したいと思います。

具体的には、パレットの上に入力値を表示し、ENTERボタンを押下することで入力データを反映させます。

なので、パレットを拡張。

そして、パレット周りの処理をがっつり書き換えました。

    class Palette
    {
        public void OnClick(asd.Vector2DF pos)
        {
            if (paletteZeroSquareObject.IsClick(pos))
            {
                if(_valueText.Text != "" && _valueText.Text != "0")
                {
                    if (_valueText.Text.Length < 2)
                    {
                        _valueText.Text += "0";
                    }
                }
            }
            else if (paletteBSSquareObject.IsClick(pos))
            {
                if(_valueText.Text.Length > 0)
                {
                    _valueText.Text = _valueText.Text.Remove(_valueText.Text.Length - 1);
                }
            }
            else if (paletteCRSquareObject.IsClick(pos))
            {
                _valueText.Text = "";
            }
            else if (paletteENSquareObject.IsClick(pos))
            {
                value = _valueText.Text;
                _isClickEnter = true;
            }
            else
            {
                for (int row = 0; row < 3; row++)
                {
                    for (int col = 0; col < 3; col++)
                    {
                        if (paletteSquareObjects[row, col].IsClick(pos) == true)
                        {
                            if(_valueText.Text.Length < 2)
                            {
                                if(_valueText.Text == "0")
                                {
                                    _valueText.Text = paletteSquareObjects[row, col].GetValue();
                                }
                                else
                                {
                                    _valueText.Text += paletteSquareObjects[row, col].GetValue();
                                }
                            }
                        }
                    }
                }
            }
        }

        public bool IsClickEnter()
        {
            return _isClickEnter;
        }

        public string GetValue()
        {
            return value;
        }

パレットを使用する側もがっつり書き換えます。

                            if (palette.IsClick(pos))
                            {
                                string value = string.Empty;
                                palette.OnClick(pos);
                                if(palette.IsClickEnter())
                                {
                                    palette.Hide();
                                    if (selectedNumberSquare != null)
                                    {
                                        selectedNumberSquare.SetValue(palette.GetValue());
                                        if (selectedNumberSquare.GetStringValue() != string.Empty)
                                        {
                                            if (selectedRowIndex >= 0)
                                            {
                                                if (Math.Abs(selectedColIndex - 1) > rowNumberSquare[selectedRowIndex].Count)
                                                {
                                                    var square = new NumberSquare(selectedRowIndex, selectedColIndex - 1);
                                                    asd.Engine.AddObject2D(square.getBackTexture());
                                                    asd.Engine.AddObject2D(square.getTextObject());
                                                    rowNumberSquare[selectedRowIndex].Add(square);
                                                }
                                            }
                                            else if (selectedColIndex >= 0)
                                            {
                                                if (Math.Abs(selectedRowIndex - 1) > colNumberSquare[selectedColIndex].Count)
                                                {
                                                    var square = new NumberSquare(selectedRowIndex - 1, selectedColIndex);
                                                    asd.Engine.AddObject2D(square.getBackTexture());
                                                    asd.Engine.AddObject2D(square.getTextObject());
                                                    colNumberSquare[selectedColIndex].Add(square);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (selectedRowIndex >= 0)
                                            {
                                                if (Math.Abs(selectedColIndex - 1) <= rowNumberSquare[selectedRowIndex].Count)
                                                {
                                                    asd.Engine.RemoveObject2D(rowNumberSquare[selectedRowIndex][Math.Abs(selectedColIndex + 1)].getBackTexture());
                                                    asd.Engine.RemoveObject2D(rowNumberSquare[selectedRowIndex][Math.Abs(selectedColIndex + 1)].getTextObject());
                                                    rowNumberSquare[selectedRowIndex].RemoveAt(Math.Abs(selectedColIndex + 1));
                                                    for (int col = selectedColIndex + 1; Math.Abs(col) < rowNumberSquare[selectedRowIndex].Count; col--)
                                                    {
                                                        rowNumberSquare[selectedRowIndex][Math.Abs(col)].SetPosition(selectedRowIndex, col - 1);
                                                    }
                                                }
                                            }
                                            else if (selectedColIndex >= 0)
                                            {
                                                if (Math.Abs(selectedRowIndex - 1) <= colNumberSquare[selectedColIndex].Count)
                                                {
                                                    asd.Engine.RemoveObject2D(colNumberSquare[selectedColIndex][Math.Abs(selectedRowIndex + 1)].getBackTexture());
                                                    asd.Engine.RemoveObject2D(colNumberSquare[selectedColIndex][Math.Abs(selectedRowIndex + 1)].getTextObject());
                                                    colNumberSquare[selectedColIndex].RemoveAt(Math.Abs(selectedRowIndex + 1));
                                                    for (int row = selectedRowIndex + 1; Math.Abs(row) < colNumberSquare[selectedColIndex].Count; row--)
                                                    {
                                                        colNumberSquare[selectedColIndex][Math.Abs(row)].SetPosition(row - 1, selectedColIndex);
                                                    }
                                                }
                                            }
                                            selectedNumberSquare.SetValue("0");
                                        }
                                        selectedNumberSquare = null;
                                    }
                                }
                            }
                            else
                            {
                                palette.Hide();
                            }

とりあえず、UI周りはこれで十分かと思います。

じゃあ、ロジックに戻りましょうか。

【LARAVEL】【ダイエット支援】データ一覧画面からデータ更新

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/diet-mng

データ編集・更新できるようにします。

まず、編集ダイアログのコンポーネントですが、入力のときと別物にしましょう。

同じコンポーネントも使えるかもしれないけど、いろいろめんどくさい。

<template>
    <div>
        <div id="overlay" v-show="show">
            <div id="content">
                <p v-if="error_flg == true" class="error">
                    <ui>
                        <li v-for="error in errors">{{ error }}</li>
                    </ui>
                </p>
                <table class="edit">
                    <tbody>
                        <tr>
                            <td>体重</td>
                            <td><input type="number" v-model="contents.weight" /></td>
                        </tr>
                        <tr>
                            <td>体脂肪</td>
                            <td><input type="number" v-model="contents.fat_rate" /></td>
                        </tr>
                        <tr>
                            <td>BMI</td>
                            <td><input type="number" v-model="contents.bmi" /></td>
                        </tr>
                    </tbody>
                </table>
                <p id="command">
                    <button @click="clickAdd">入力</button>
                    <button @click="closeModal">閉じる</button>
                </p>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    props: ['show'],
    data() {
        return {
            errors: [],
            error_flg: [],
            param: {},
            contents: {
                id: "",
                weight: "",
                fat_rate: "",
                bmi: "",
            },
        };
    },
    created: function() {
    },
    methods: {
        dataSet: function(data) {
            this.contents = data;
        },
        clickAdd: function() {
            var self = this;
            this.param.contents = this.contents;
            axios.post('api/weight/edit', this.param).then(function(response){
                self.clear();
                self.closeModal();
                self.$emit('update');
            }).catch(function(error){
                self.error_flg = true;
                self.errors = error.response.data.errors;
            });
        },
        closeModal: function() {
            this.$parent.showEditDialogContent = false;
        },
        clear: function() {
            this.contents.weight = "";
            this.contents.fat_rate = "";
            this.contents.bmi = "";
            this.error_flg = false;
            this.errors = [];
        }
    }
}
</script>

そして、それを使用する側の親コンポーネント。

        <div>
            <weight-input-dialog-component :show="showInputDialogContent" @update="invokeUpdateList"></weight-input-dialog-component>
            <weight-edit-dialog-component ref="editDialog" :show="showEditDialogContent" @update="invokeUpdateList"></weight-edit-dialog-component>
        </div>
        onClickEdit: function(id) {
            var editData = {};
            this.datalists.forEach(element => {
                if(element.id == id){
                    editData.id = id;
                    editData.weight = element.weight;
                    editData.fat_rate = element.fat_rate;
                    editData.bmi = element.bmi;
                    return true;
                }
            });
            this.$refs.editDialog.dataSet(editData);
            this.showEditDialogContent = true;

ポイントは、編集ダイアログにデータを渡すとき。

親コンポーネントから子コンポーネントのメソッドをコールしています。

これは、子コンポーネントを定義するときに、

ref="editDialog"

と書くことで、

            this.$refs.editDialog.dataSet(editData);

と、子コンポーネントのメソッドを実行できます。

その引数でパラメータを渡して、表示させています。

あとは、今までどおり。

Repository

    public function edit($id, $weight, $fat_rate, $bmi)
    {
        $model = $this->getItemById($id);
        $model->weight = $weight;
        $model->fat_rate = $fat_rate;
        $model->bmi = $bmi;
        $model->save();
    }

    public function getItemById($id)
    {
        return WeightManagement::where(['id' => $id])->first();
    }

controller

    /**
     * データを1件更新する
     */
    public function edit(Request $request)
    {
        $param = $this->weightManagement->getParam();
        $this->weightManagement->edit( $request->contents["id"], 
            $request->contents["weight"],
            $request->contents["fat_rate"],
            $request->contents["bmi"]
        );
        
        return response()->json();
    }
Route::post('api/weight/edit', 'Weight\ApiController@edit');

【ラズパイ】【GLCD】ディスプレイのいろんなところに表示させてみる。

前回までの状況はこちら。

前回でLCDディスプレイの初期化も終わってますし、データを書き込む関数も一通り揃っています。

なので、いろいろ書いてみましょうか。

とはいっても、今の状態では、ドット単位で表示する/しないの設定しかできませんが。

def __main():
    PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCDInit()
    GLCDDisplayClear()
    SelectIC(1)
    SetPage(0)
    SetAddress(0)
    WriteData(0xFF)
    try:
        while True:
            time.sleep(1.0)
    except KeyboardInterrupt:
        GPIO.cleanup()

ICチップ1番、ページ0、アドレス0に0xFF(全点灯)を設定します。

左上一列が点灯しました。(分かるかな・・・)

ICチップ1番、ページ1、アドレス1に書き込みました。

ICチップ1番、ページ7、アドレス63に書き込みました。

ICチップ2番、ページ0、アドレス0に書き込みました。

ICチップ2番、ページ7、アドレス63に書き込みました。

右下の4ドットは右上に表示するアイコンに対応しています。

なので、LCDを全点灯した場合、右下4ドット分は欠けて見えます。

まぁ、ここまでをまとめると、

こういうことですな。

ここまで分かれば、後はデータさえ用意できれば、いろいろ表示できそうだ。