「技術」カテゴリーアーカイブ

【ダイエット支援】【入力履歴機能】履歴からデータを入力

なかなかいい感じに仕上がっております。

    public function searchKeyword($keyword, $user)
    {
        $result = [];
        $records1 = EatingTemplateItem::where('item', 'like', "%$keyword%")->get();
        $records2 = $user->EatingHistoryItems()->where('item', 'like', "%$keyword%")->get();
        if(count($records1) + count($records2) >= 10 )
        {
            return [];
        }
        foreach($records1 as $record)
        {
            $obj = new \stdClass();
            foreach($this->templateParamNames as $paramName)
            {
                $obj->$paramName = $record->$paramName;
            }
            $result[] = $obj;
        }
        foreach($records2 as $record)
        {
            $obj = new \stdClass();
            foreach($this->templateParamNames as $paramName)
            {
                $obj->$paramName = $record->$paramName;
            }
            $result[] = $obj;
        }
        return $result;
    }
        onChangeItem: function() {
            if(this.contents.item!=""){
                var flg = this.setTemplete();
                if(flg == false) {
                    var self = this;
                    this.param.contents = this.contents;
                    axios.post('/api/eating/search', this.param).then(function(response){
                        self.keywords = [];
                        response.data.keywords.forEach(keyword => {
                            self.keywords.push(keyword);
                        });
                    }).catch(function(error){
                        self.error_flg = true;
                        self.errors = error.response.data.errors;
                    });
                }
            }else{
                this.keywords = [];
            }
        },
        setTemplete: function() {
            for (var index = 0; index < this.keywords.length; index++) {
                if(this.keywords[index].item == this.contents.item) {
                    this.contents.protein = this.keywords[index].protein;
                    this.contents.liqid = this.keywords[index].liqid;
                    this.contents.carbo = this.keywords[index].carbo;
                    this.contents.calorie = this.keywords[index].calorie;
                    return true;
                }
            }
            return false;
        }

これで入力履歴からデータの入力ができました。

ついでに同じデータが二重で履歴に登録されないように細工します。

    /**
     * ヒストリにデータを1件追加する
     */
    public function addHistory($param, $user)
    {
        $record = $this->searchKeyword($param["item"], $user);
        if(count($record) != 0)
        {
            return;
        }
        $model = new EatingHistoryItem();
        foreach($this->templateParamNames as $name)
        {
            $model->$name = $param[$name];
        }
        $model->save();

        $this->attachToUser($model, $user);
    }

これである程度利便性が高まりましたね。

あとは管理画面か・・・。

他のユーザーから管理画面を表示できないようにしないと。

【デザインパターン】Builerパターン

Builderパターンのコード例です。

package org.example.builder;

public abstract class Builder {
    public abstract void buildPart1(Product product);
    public abstract void buildPart2(Product product);
}
package org.example.builder;

public class ConcreteBuilder extends Builder {
    private Product product;

    @Override
    public void buildPart1(Product product) {

    }

    @Override
    public void buildPart2(Product product) {

    }

    public Product getResult(){
        return product;
    }
}
package org.example.builder;

public class Director {
    private Builder builder;
    public Director(Builder builder)
    {
        super();
        this.builder = builder;
    }

    public void construct(Product product)
    {
        builder.buildPart1(product);
        builder.buildPart2(product);;
    }
}
package org.example.builder;

public class Main {
    public static void main(String[] args)
    {
        Product product = new Product();

        ConcreteBuilder concreteBuilder = new ConcreteBuilder();
        Director director = new Director(concreteBuilder);
        director.construct(product);
        Product result = concreteBuilder.getResult();
    }
}

処理に必要なデータを段階的に渡していき、最後に処理結果を取得するパターンです。

LaravelのSQLビルダがそれに近いですね。

Builderインターフェースを定義し、それをConcreteBuilderとして実装します。

DirectorのコンストラクタにConcreteBuilderを渡し、以後、Directorのconstructメソッドで必要なパラメータをBuilderに渡します。

結果はgetResultで取得します。

【北海道大戦】札幌強すぎ問題

マップを修正して。札幌を9区に分けてみました。

これで単純計算で札幌の戦力が1/9になったはずですが、

都市間のリンクがぐちゃぐちゃになりまして、それをできる限り修正してみたらかなりいびつな形になっちゃいました。

まあいいや。

今後はリアル北海道地図でやりたいなぁ。

【ラズパイ】赤外線受信を試してみる。

前回は赤外線LED(送信側)を試しましたが、

今回は受信機側を試してみたいと思います。

ドキュメントにこう書いてありました。

受信部に向かって左から出力、GND、VCCということなので、

こういう回路を組んでみました。

出力に発行ダイオードと抵抗を繋げました。

この状態ではなにも信号は与えていませんが、

LEDが点灯しているのは、

この図を見ると、信号を受信したときに出力がHigh→Lowとなるようです。

試しに、エアコンのリモコンの信号を受信機に当ててみたいと思います。

微妙ですが変化があるようですね。

じゃあ、次はこの信号を読み取るプログラムを書いてみますか。

【ダイエット支援】【入力履歴機能】履歴検索して候補の表示

うまくスクショが取れなかった・・・

    public function searchKeyword($keyword, $user)
    {
        $result = [];
        $records1 = EatingTemplateItem::where('item', 'like', "%$keyword%")->get();
        $records2 = $user->EatingHistoryItems()->where('item', 'like', "%$keyword%")->get();
        if(count($records1) + count($records2) >= 10 )
        {
            return [];
        }
        foreach($records1 as $record)
        {
            $result[] = $record->item;
        }
        foreach($records2 as $record)
        {
            $result[] = $record->item;
        }
        return $result;
    }
    public function search(Request $request)
    {
        return response()->json([
            'keywords' => $this->eatingManagement->searchKeyword($request->contents['item'], Auth::user()), 
            ]);
    }
Route::post('api/eating/search', 'Eating\ApiController@search');
                            <td><input type="search" v-model="contents.item" autocomplete="on" list="keyword" v-on:keydown="onChangeItem"/></td>
                            <datalist id="keyword">
                                <option v-for="keyword in keywords" v-bind:value="keyword" />
                            </datalist>
        onChangeItem: function() {
            if(this.contents.item!=""){
                var self = this;
                this.param.contents = this.contents;
                axios.post('/api/eating/search', this.param).then(function(response){
                    self.keywords = [];
                    response.data.keywords.forEach(keyword => {
                        self.keywords.push(keyword);
                    });
                }).catch(function(error){
                    self.error_flg = true;
                    self.errors = error.response.data.errors;
                });
            }
        }

まだコードは暫定ですが、

とりあえず、入力した文字からデータベースを検索して、入力候補表示までできました。

とりあえず、検索結果だけ。

検索結果から各パラメータを自動入力させるのはまた次回に。

【デザインパターン】AbstructFACTORYパターン

AbstructFactoryパターンのコード例です。

package org.example.abstruct.factory.factory;

public abstract class AbstructProduct1 {
    public abstract void method1();
}
package org.example.abstruct.factory.factory;

public abstract class AbstructProduct2 {
    public abstract void method2();
}
package org.example.abstruct.factory.factory;

public abstract class AbstructFactory {
    public static AbstructFactory getFactory(String className)
    {
        AbstructFactory factory = null;
        try {
            factory = (AbstructFactory)Class.forName(className).getDeclaredConstructor().newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return factory;
    }

    public abstract AbstructProduct1 createAbstructProduct1();
    public abstract AbstructProduct2 createAbstructProduct2();
}
package org.example.abstruct.factory.concrete;

import org.example.abstruct.factory.factory.AbstructProduct1;

public class concreteAbstructProduct1 extends AbstructProduct1 {
    @Override
    public void method1() {

    }
}
package org.example.abstruct.factory.concrete;

import org.example.abstruct.factory.factory.AbstructProduct2;

public class concreteAbstructProduct2 extends AbstructProduct2 {
    @Override
    public void method2() {

    }
}
package org.example.abstruct.factory.concrete;

import org.example.abstruct.factory.factory.AbstructFactory;
import org.example.abstruct.factory.factory.AbstructProduct1;
import org.example.abstruct.factory.factory.AbstructProduct2;

public class concreteAbstructFactory extends AbstructFactory {
    @Override
    public AbstructProduct1 createAbstructProduct1() {
        return new concreteAbstructProduct1();
    }

    @Override
    public AbstructProduct2 createAbstructProduct2() {
        return new concreteAbstructProduct2();
    }
}

Factoryパターンが1Productを作成していたのに対して、AbstructFactoryパターンは複数Productを作成できるようにしたパターンです。

factory作成時にクラス名の文字列からインスタンスを作る、と本に書いてありました。

このやり方はいろいろ応用できるかも。

ちなみに、(AbstructFactory)Class.forName(className).newInstance();と書くのは非推奨となっています。

問題点は、Productを追加した場合、すでに作成している全てのconcreteProductに実装が必要と言うことですね。

「Error:java: エラー: リリース・バージョン〇はサポートされていません」の解決方法

久しぶりにIntelliJを使ったらハマった。

原因は使用しているJDKのバージョンが、実際にあるものと、IntelliJの設定が異なっているからです。

設定する場所はここ。

Project StructureのProject SDKのバージョンが、PCに入っているバージョンと一致しているか、

と、Project language levelのバージョンが一致しているか。

もう一つは、settingのJava compilerのbytecodeのバージョン。

この設定が全て一致していないと、タイトルにあるようなビルドエラーが出るようです。

焦るわ!

【デザインパターン】Factoryパターン

なんでデザインパターンの話になるとJavaなのかね?

まぁ、概念が解れば他の言語にでも応用は可能だけど。

さくっとサンプルコードを書いてみました。

package org.example.factory.creator;

public abstract class Product {
    public abstract void methodA();
    public abstract void methodB();
}

package org.example.factory.creator;

public abstract class Creator {
    public final Product create() {
        Product product = factoryMethod();
        return product;
    }

    protected abstract Product factoryMethod();
}

package org.example.factory.concrete;

import org.example.factory.creator.Product;

public class ConcreteProduct extends Product {
    public ConcreteProduct() {
        super();
    }

    public void methodA() {

    }

    public void methodB() {

    }
}

package org.example.factory.concrete;

import org.example.factory.creator.Creator;
import org.example.factory.creator.Product;

public class ConcreteCreator extends Creator {

    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}
package org.example.factory;

import org.example.factory.creator.*;
import org.example.factory.concrete.*;

public class Main {
    public static void main(String[] args) {
        Creator factory = new ConcreteCreator();
        Product object = factory.create();
        object.methodA();
        object.methodB();
    }
}

抽象クラスProductとCreatorを作成します。

Creatorクラスではcreateメソッドを実装していますが、その実態であるfactoryMethod()は抽象メソッドです。

これを使用するにはProductとCreatorを実装したクラスを作成する必要があります。

それがConcreteProductとConcreteCreatorという例で作成しています。

使用する場合は、まずはConcreteCreatorをインスタンス化し、Creator型で保持します。

以後、create()メソッドを使用して、ConcreteProductのインスタンスを作成して使用します。

新しいProductを追加する場合は、同じようにProductとCreatorを実装するクラスを作成し、Creator型で新しいCreatorをインスタンス化して使用すれば対応可能です。

このパターンを使用するメリットとしては、Productを作成する窓口がcreate()メソッドに一本化されます。

Productの初期設定をfactoryMethod()内に実装すれば、Productに対するあれこれ設定をするという余計な手間が省けます。

【北海道大戦】バトルのバランス調整

ちょっとコードを書き換えてバトルのバランス調整をしました。

        private void onClickMouseShowActionResult(asd.Vector2DF pos)
        {
            var result = janken(selectedAttack, selectedDeffece);
            if(result == BattleResult.win)
            {
                _deffencePower -= (int)Math.Floor(_attackPower * (Singleton.Random.NextDouble() + 0.1));
                if(_deffencePower <= 0)
                {
                    Singleton.GameData.BattleResultUpdate(BattleResult.win);
                    var scene = new MainScene();
                    asd.Engine.ChangeScene(scene);
                    _deffenceParam.Text = "戦闘力:0";
                }
                else
                {
                    _deffenceParam.Text = "戦闘力:" + _deffencePower;
                }
            }
            else if(result == BattleResult.lose)
            {
                
                _attackPower -= (int)Math.Floor(_deffencePower * (Singleton.Random.NextDouble() + 0.1));
                if (_attackPower <= 0)
                {
                    Singleton.GameData.BattleResultUpdate(BattleResult.lose);
                    var scene = new MainScene();
                    asd.Engine.ChangeScene(scene);
                    _attackParam.Text = "戦闘力:0";
                }
                else
                {
                    _attackParam.Text = "戦闘力:" + _attackPower;
                }
            }
            _attackResult.Hide();
            _deffenceResult.Hide();
            _status = GameStatus.SelectDeffenceAction;
        }

単純に戦力値で引き算する訳じゃ無くて、

乱数の係数を掛け合わせてみました。

単純計算ではわずかな戦力差でも一撃で決着が付いてしまいましたが、

これによって、僅差であれば、一撃で決着することは無くなります。

あとは札幌強すぎ問題ですね・・・