OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerファイルにおける RUN・CMD・ENTRYPOINT の使い分け

DockerファイルでのRUN・CMD・ENTRYPINTは似たような命令です。ですが、これらを使い分けることができると(セキュリティ的にも)大変便利です。

## 対象

- Dockerの概要が分かっている人
- Linuxにおける[シェル](https://eng-entrance.com/linux-shell)の概要が分かっている人

## RUN

- Dockerイメージを作成するときに実行されるコマンド
- 1つのDokerfileに複数記載が可能

## ENTRYPOINT

- **[シェル](https://eng-entrance.com/linux-shell)を介さずにコマンドを実行する**
- 1つのDokerfileに1つしか記載できない

## CMD

- コマンドを実行する
- 1つのDokerfileに1つしか記載できない

## ENTRYPOINT + CMD

- Dockerイメージpushを上手に使うことで、ENTRYPOINTのみのDockerイメージとCMDのみの実行コンテナとに分けることができる
    1. 実行コンテナ作成の際に、ENTRYPOINTのみのDockerイメージをpullする
    2. ENTRYPOINTのみのDockerイメージで指定したコマンドが実行コンテナで実行される
        - 作成されたコンテナの用途を限定できる ― pullされるDockerイメージ側で指定したコマンドしか実行できないため

### pullされるDockerイメージ

- ```ENTRYPOINT```でコマンドを指定する

### 実行コンテナ

- ```CMD```を```ENTRYPOINT```で指定したコマンドの補完となるよう指定する

### 例

下記のdockerfileを基にしたDockerイメージをDockerHubに上げます。

```dockerfile
FROM alpine:latest
EXPOSE 80
RUN apk add --no-cache net-tools
RUN apk add --no-cache nmap-nping
ENTRYPOINT ["nping", "-c", "3", "--tcp", "-p", "80"]
```

ここでは```{DockerID}/ping:latest```として上げています。DockerHubに上げる手順は[以前の記事](https://qiita.com/y_k_individual/items/064e058c5e280c161b7f)を参照してください。

実際に動かすコンテナのdocerfileは以下になります。

```dockerfile
FROM {DockerID}/ping:latest
CMD ["www.google.co.jp"]
```

コンテナを構築し、実行します。

```Shell
docker image build -t sample/ping:latest .
docker container run -p 80:80 --name ping sample/ping:latest
```

コンテナ実行結果：

![ENTRYPOINT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/0b4516d7-f663-773d-4a49-16ad9e2eadb0.png)


## まとめ

Dockerfileの命令は深く踏み込むと少々複雑です。効果的に使い分けてください。

## 参考

[Dockerfile リファレンス](http://docs.docker.jp/engine/reference/builder.html)

[Docker/Kubernetes 実践コンテナ開発入門](https://www.amazon.co.jp/dp/B07GP1Q3VT)

[[docker] CMD とENTRYPOINT の違いを試してみた](https://qiita.com/hihihiroro/items/d7ceaadc9340a4dbeb8f)

[DockerfileのCMDとENTRYPOINTを改めて解説する](https://qiita.com/uehaj/items/e6dd013e28593c26372d)
【合格体験記】Azure Fundamentals（AZ-900）勉強方法（クラウド業務未経験）

![WS000019.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398297/a4d18385-f5a1-2025-3043-946b1b229709.jpeg)

2020年4月に、[Microsoft Azure Fundamentals(AZ-900)](https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-900) 試験を受けて合格しました。

AZ-900という試験に合格すると、Azure Fundamentalsに認定されます。Azureにはいくつか試験がありまして、これが一番初級の試験です。

Azureの案件に入ることが決まり、何にもわからんわいなと思った為、受験。業務未経験ですし、初心者です（AWSもGCPも全部触ったことがなかった）。そういうレベルの人の勉強方法とのことを念頭に参考にして頂けると良いかと思います。

Azure試験の中では一番簡単なレベルではあるものの、広く浅くAzureサービスについて問われる形になっているので、クラウド自体が初心者の場合はそれなりに勉強しておく必要があります。

#Azure Fundamentals 合格までの勉強方法

1. 合格対策Microsoft認定AZ-900:Microsoft Azure Fundamentalsテキスト＆問題集
2. Microsoftラーニングパス「Azureの基礎」（無料）

上記2点のみ、使いました。勉強期間は2週間程。

##1. 合格対策Microsoft認定AZ-900:Microsoft Azure Fundamentalsテキスト＆問題集

買ったのはこちらの1冊。
[「合格対策Microsoft認定AZ-900:Microsoft Azure Fundamentalsテキスト＆問題集」](https://www.amazon.co.jp/%E5%90%88%E6%A0%BC%E5%AF%BE%E7%AD%96Microsoft%E8%AA%8D%E5%AE%9AAZ-900-Microsoft-Azure-Fundamentals%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%EF%BC%86%E5%95%8F%E9%A1%8C%E9%9B%86-%E5%90%89%E7%94%B0%E8%96%AB-ebook/dp/B0872LVYD6)

[<img width = 300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398297/7041fbc2-14d9-bbb2-6f14-9a10028aa932.jpeg">](https://www.amazon.co.jp/%E5%90%88%E6%A0%BC%E5%AF%BE%E7%AD%96Microsoft%E8%AA%8D%E5%AE%9AAZ-900-Microsoft-Azure-Fundamentals%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%EF%BC%86%E5%95%8F%E9%A1%8C%E9%9B%86-%E5%90%89%E7%94%B0%E8%96%AB-ebook/dp/B0872LVYD6)

全部で150ページ程の読みやすい本です。導入にはピッタリでした（税抜2,200円）。
この後紹介するMicrosoft Learn「Azure基礎」に取り組む前にこの本をさらっと読んでおくと、スムーズに進めます。おすすめ。

模擬問題も多少ついていて、理解が深まった体感があります。ただし、こちらの本に出てくる問題だけでは本試験は対応できません（はっきり）。

ちょっと易しすぎますし、内容も合格には不十分だと感じています。
導入として読むのに非常に最適だけどこれ1冊では合格できない、そういう本。

##2. Microsoftラーニングパス「Azureの基礎」

Microsoft公式サイトの[「Azureの基礎」](https://docs.microsoft.com/ja-jp/learn/paths/azure-fundamentals/)というラーニングパスを読みました。

それなりに量があるのと、若干日本語が不自然な部分が消化しづらかった点ではありますが、無料でここまで勉強できるのはありがたいことです。

勉強は以上の2点のみ。

#Azure Fundamentals 試験の感想

クラウド初心者でも大丈夫、ちゃんとやれば2週間程度で合格できます。

ただ、初級向けの試験だからといって手を抜くと、簡単に落ちがちな試験でもありますので、お金がもったいないと思う方は（受験料12,500円）一発で合格しよう。

グッドラック！
Dockerイメージpush手順

ただ"docker image push ～"とコマンドを打つだけではうまくいきません。Dockerイメージをpushする手順を以下にまとめます。

## 対象

本などで"docker image push"の概要は知っているが、実践したら失敗した人

## 手順

以下のDocerfileを例にして説明します。

```dockerfile
FROM alpine:latest
EXPOSE 80
RUN apk add --no-cache net-tools
RUN apk add --no-cache nmap-nping
ENTRYPOINT ["nping", "-c", "3", "--tcp", "-p", "80"]
```

1. Dockerイメージをbuildする

    ``` Shell
    docker image build -t sample/ping:latest .
    ```

2. 一旦コンテナまで作成し、そのコンテナを元にDockerイメージをcommitする

    ``` Shell
    docker container run -p 80:80 --name ping  sample/ping:latest www.google.co.jp
    ```

    コンテナ実行結果：

    ![push.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609106/f7b660f7-1ce2-862c-292e-ee9a92d7f3d5.png)


    ``` Shell
    docker container commit ping {DockerID}/ping:latest
    ```

3. DockerHubにログインする

    -p オプションをつけるとパスワードが画面に表示されることになります。-p オプションは**コマンド履歴を見ることのできる環境では使わないでください。**

    ```Shell
    docker login -u {DockerID}
    ```

4. Dockerイメージをpushする

    パブリックリポジトリの場合、CLIからpushすると、リポジトリは自動的に作成されます。

    ```Shell
    docker image push {DockerID}/ping:latest
    ```

## 終わりに

Dockerイメージをpushする手順をまとめました。効率的なコンテナ運用に役立てていただければ幸いです。

## 参考

[Docker コマンド](http://docs.docker.jp/engine/reference/commandline/index.html#image-commands)

[Docker のインストールからレポジトリへのpush までやってみた【CentOS 7】](https://qiita.com/umi/items/d4b5a68263ad0444693b)

[Dockerでcommitしてみる](https://qiita.com/mats16/items/712575dc50513dfdf0a2)

[Docker imageのpushに失敗したらログインし忘れが原因かも](https://minus9d.hatenablog.com/entry/2018/07/22/111846)
Dockerコンテナとは何か改めて考える

Dockerコンテナについて少し詳しく解説をします。

## 対象

- Dockerの概要は知っているが、もう少し詳しく学びたい人
- [目的・戦略・戦術の違いが分かる人](https://note.com/kubax16_com/n/nb09f81d0e8ab)

## 目的 (Objective)

以下の問題の改善を目的としています。

- アプリケーションの実行環境が変わると、確実な実行が保証できない
- 環境構築に時間がかかる

## 戦略 (What)

以下の戦略をとっています。

- 複数システムが同居しても競合の問題を起こさない
- 各システムで独立した実行環境を構築する

## 戦術 (How)

仮想化によって、上記の戦略を実現しています。

特徴：  

- アプリケーションとOS・ライブラリ・Tool等をワンパッケージで提供する
- 他の仮想化技術より早い起動を実現する
  - [カーネル](https://wa3.i-3-i.info/word15.html)をホストPCと共有することで、コンテナ実行の度にカーネルを読み込まずに済む  
        理由：  
        ディストリビューション(CentOS、Ubuntu等)が異なってもカーネルは共通である([Linuxとは本来、カーネル部分だけを指す](https://ja.wikipedia.org/wiki/Linux%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB))。  
        そのため、Linux上で動かすのであれば、カーネルをホストPCと共用しても問題ない。
- 可搬性・冪等性を確保する
    - 可搬性・冪等性を阻害する要因
      - CPUアーキテクチャが異なる
      - カーネルバージョンが異なる
      - ダイナミックリンクライブラリを使用する
- dockerfile用DSL・DockerHubを用意することで、環境構築の手間を減らす
    - アプリケーションデプロイに特化している
      - 全てのアプリケーションがコンテナ化に向いているわけではない  
            コンテナは一旦破棄し、作り直すと、初期状態に戻る。そのため、ステートレスなアプリケーションと相性が良い。反面、ステートフルなアプリケーションは下記のような工夫が必要である。
          - ホストPCとディレクトリを共有
          - 永続化が必要な部分をストレージ用コンテナに分離

### コンテナの仕様

[OCI](https://opencontainers.org/)にて標準化が進められています。

### コンテナ適用例

- 本番環境
  - 開発環境と本番環境との差異を吸収する
- 開発メンバ間での開発環境の統一
- サンプル環境・サンプルコードの配布
  - 実行環境ごと配布することになるので「動かない」可能性を減らせる

## 終わりに

コンテナの基本事項をまとめ直しました。コンテナ構築の際に役立てていただけたら幸いです。

## 参考

[Docker/Kubernetes 実践コンテナ開発入門](https://www.amazon.co.jp/dp/B07GP1Q3VT)

[コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤](https://www.amazon.co.jp/dp/B079Q6S12G)

[さわって学ぶクラウドインフラ　docker基礎からのコンテナ構築](https://www.amazon.co.jp/dp/B089VZXX63)

[【初心者向け】Linuxカーネルって一体なんだ？](https://qiita.com/uguis410/items/17ec1e447e9716bfdca7)
【Laravel】UnitTest、FeatureTest、BrowserTestの違い

# はじめに
Laravelにおいて、
テストコードは3種類存在します。

・UnitTest
・FeatureTest
・BrowserTest

この３つの違いがよく分からなかったので、
自分なりにしっくりくるように簡単に整理しました。

# UnitTest
`/tests/Unit`配下にテストを配置する。
一番粒度の細かいテスト。

Service、Model、Middleware、Policyなど、
自分で作ったクラス１つ１つと対応するように
テストクラス（ファイル）を１つ１つ作る。

その対象クラスのメソッド１つ１つの動作を検証するための
テストケースをコードに書いていく。

Controllerクラスのテストは
UnitTestではなくFeatureTestとするほうがしっくりくる。

# FeatureTest
`/tests/Feature`配下にテストを配置する。
UnitTestより粒度を大きくしたテスト。

１つのHTTPリクエスト単位の動きをテストする。
=ルーティング１つごとにテストクラス（ファイル）を作る
=コントローラのアクションメソッド単位でのテスト

UnitTestでテストした各クラスを結合した状態で
コントローラの動き（つまりリクエストを受けてレスポンスを返すまで）をテストするというイメージ。

１つのコントローラアクションに対応したテストクラス（ファイル）の中で、
・ログインした状態でアクセス時の動作
・未ログインアクセス時の動作
・検索パラメータ付けたアクセス時の動作
・ユーザに特定ロールを付けた状態の動作
など１つ１つのケースをテストケースとしてコードを書く。

# BrowserTest
`/tests/Browser`配下にテストを配置する。

実際にブラウザを使って画面にリクエスト、
ボタンをクリック、
マウスホバー、
フォーム送信などの操作をするテストをコードで実行できる。

FeatureTestにさらに
・複数HTTPリクエストの遷移
・画面操作時のJsの動作
のような観点を加えてテストできるイメージ。

Unit、FeatureはPHPUnitで動作するテストなのに対し、
BrowserTestは`laravel/dusk`というパッケージを使ったテスト。

# 参考
https://readouble.com/laravel/7.x/ja/testing.html
https://readouble.com/laravel/7.x/ja/dusk.html
roslib.jsで独自メッセージ型を使う

あまりニーズがなさそうですが、roslibjsで独自メッセージ型を使うケースについて調べてみました。
roslibjsとは、web上でrosのトピックを送受信したり、rosのサービス/アクションを叩いたり
できるようになるjavascriptライブラリです。

ロボットに取り付けた画面からロボットに指令を出したり、ロボットからの情報を表示したりします。
rosにはrviz, rqt等、ROS基盤にアクセスするアーキテクチャはありますが、
エンドユーザ向けの画面を作りたい場合はコテコテ作る必要があります。

pyqtで画面を作ればpythonコードで直接rosAPIにアクセス出来て楽ですが、
UIというとWebアーキテクチャがメインっぽいですし、qtに依存するのもあれですし・・

基本的なことはROSのwikiに丁寧に書かれてます。
http://wiki.ros.org/roslibjs/Tutorials/BasicRosFunctionality

独自メッセージ型と書きましたが、Web側(つまりroslibjs)で型定義するわけではありません。
あくまで型定義はロボット側ROSパッケージで行います。どういうことなのか。

#1.独自メッセージ型をROSパッケージで定義
これもwikiに書かれてるので、そのとおりにサンプルを用意します。
http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv

#2.メッセージ型を確認
```
>rosmsg show beginner_tutorials/Num
int64 num
```
作成したパッケージbeginner_tutorialsの下に、Numというメッセージ型が新規作成され、
その型がint変数一個であることがわかります。

#3.ros側のブリッジサーバ起動
```
roslaunch rosbridge_server rosbridge_websocket.launch
```
新しいパッケージを作成し、source devel/setup.bashをした後、ブリッジサーバを
起動する必要があります。でないと、ブリッジサーバが新しい独自メッセージ型を
認知できません。

#4.ros側でトピック待ち
```
>rostopic echo /aaa
WARNING: topic [/aaa] does not appear to be published yet
```
新しいメッセージ型を、/aaaという名前のトピックで受信します。
とはいえ、この時点でrosマスタはそんな名前のトピックは知りません。
ただ、「そのうち誰かが/aaaという名前でトピックをpublishするだろう」と
思ってるだけです。

#5.Webページ側でトピック発行
基本的なコードは上記のwikiに書かれてるので、トピックを発行するとこだけ抜粋すると、

```javascript

var pub = new ROSLIB.Topic({
    ros:ros,
    name:'/aaa',
    messageType: 'beginner_tutorials/Num'
});
pub.publish(new ROSLIB.Message({num: 999}));
```
これで、４の画面に以下のようにトピックが届きます。

```
> rostopic echo /aaa
num: 999
```

roslibjs側では、beginner_tutorials/Numというメッセージ型が
どういう型なのか定義されているわけではありません。
ただ、型の定義に合わせてデータを構成して送れば、
rosマスタが良しなにトピックのサブスクライバに配信してくれます。

4で、/aaaという正体不明のトピックが登録されたrosマスタは、
このようにWebページからトピックを発行されて初めて、

/aaaというトピックが、beginner_tutorialsパッケージのNumメッセージ型を
保持したトピックであることを知ります。そして、rostopic echoしてるところ、
すなわちコンソールのサブスクライバにトピックを配信します。
PHPStormからDockerのPHPコンテナでPHPUnitを実行する方法

# はじめに
ローカル環境でDockerを利用しているときに、
PHPStormの画面上からPHPUnitを実行できるようにするための
設定方法を紹介します。

大きく２つの設定が必要になります。

* PHP interpreterを設定
* PHPUnitのinterpreterを設定

# PHP interpreterを設定

・「Settings」->「Languages & Frameworks」->「PHP」->「CLI Intepreter」->「...」をクリック
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/f9ea8827-0145-529f-8d99-878c14d52e67.png)

・左上の「＋」->「From Docker, Vagrant, VM, WSL, Remote...]をクリック
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/8dd8a2d2-fc85-8387-7a44-c7cfca08939f.png)

・「Docker Compose」のラジオボタンを選択する
→「Configuration file」にdocker-compose.ymlのパスを設定
→「Service」でphp-fpmのコンテナを選択
→「OK」クリック
※「Docker」を選択すると、PHPUnitでDBコンテナを利用する際に接続できないので「Docker Compose」で設定する
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/bd52afaa-0f33-c808-e48e-f4cc0e5e4b9f.png)



# PHPUnitのinterpreterを設定

・「Settings」->「Languages & Frameworks」->「PHP」->「Test Frameworks」->左上の「＋」->「PHPUnit by Remote Interpreter」をクリック
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/a2c2f4ea-7d90-22c3-3310-300c2bc5adb9.png)

・先ほど登録したDockerコンテナのInterpreterを選択
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/53da988e-dab9-2a72-9c96-ebfebe0820ae.png)

・「Path to script」にDockerコンテナのautoload.phpのパスを設定
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/ea776663-0723-a812-e056-9f45f523d861.png)

・「Default configuration file」にphpunit.xmlのパスを設定
![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/99117762-1b84-0bd3-83df-2dbfa13d7656.png)


・PHPStomのテストクラスファイルを開いて、左にある緑の三角マークをクリックでテスト実行
![9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/116884dc-bb12-8314-58b1-4c1606e665bd.png)

・テスト結果確認
PHPStormの左下の「Run」タブが表示され、そこにテスト結果が表示されます。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297693/e7910359-159d-5b9c-af6d-7c5fb6bddad7.png)
push通知

「[push.js](https://pushjs.org)」を使う

CDN

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/push.js/0.0.11/push.min.js"></script>
```

html

```html

<!DOCTYPE html>
<html lang="ja">
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/push.js/0.0.11/push.min.js"></script>
<meta charset="UTF-8">
<title>ブラウザでプッシュ通知を実装</title>
</head>
<body>
<center>
 <h1 style="margin-top: 300px">ブラウザでプッシュ通知を実装しよう</h1>
</center>
<center>
 <input type="button" id="push" onclick="return push()" value="クリックするとプッシュ通知が送られます"/>
</center>
</body>
</html>
```

Javascript

```javascript

<script>
    function push(){
        Push.create("更新情報",
        {
            body: "ブログの更新をお知らせします!",
            icon: 'casley_logo.png',
            timeout: 8000,
            onClick: function () {
                window.focus();
                this.close();
            }
        })
    }
</script>
```

参考：[https://www.casleyconsulting.co.jp/blog/engineer/293/](https://www.casleyconsulting.co.jp/blog/engineer/293/)
Vue-cli + github pages + google domains を使う

忘れてしまったら嫌なので備忘録として書いていきます。
ちょっと前にgithub pagesに[manif-maker](https://manifg.com/)というアプリをデプロイしたんですが、ドメイン取得したりなんかしたことが無いので、練習としてやろうと思ったがいろいろ躓きました

#google domainsでドメインを取得
[google domains](https://domains.google/intl/ja_jp/)ここでドメインを取得してください。

#DNSのカスタムリソースレコード
google domainsのサイドバーにあるDNSを押し、下の方にカスタムリソースレコードとあるので、下記を入力していく  

![スクリーンショット (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573077/8ab078df-b474-4388-114c-a87b9d3057f1.png)

白で隠したところには username.github.io と入力

#githubのSettingsに行き、ドメインの設定をする
githubのsettingsに行き、github pagesの所を見ます。
そこにCustom domainとあるので、そこに取得したドメインを入力してsaveを押してください。
またEnforce HTTPSを押しhttps化してください

またこの手順を踏むと、vueのdocsフォルダに**CNAME**というファイルが自動で作成されて、ドメイン名が書かれていました。

どのサイトもここまで書かれていたのですが  

```
Failed to load resource: the server responded with a status of 404 ()
```
というエラーがconsoleに出て、ずっと真っ白画面のままになりました。

#真っ白画面を解決した方法
vue.config.jsにpublicPath: './'と書きexportし、ビルドします。真っ白画面じゃなくなり、ちゃんと見れるようになりました。

また進展があったら書いていこうと思います
Nuxt.js + Buefy に Storybookを導入する

## 結論

`.storybook/preview.js` に以下を記述します。

``` preview.js
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'
import '@mdi/font/css/materialdesignicons.css'
import Vue from 'vue'

Vue.use(Buefy)
```

## 前提
* Nuxt.js：v2.12.2
* Buefy：v0.8.20
* Storybook：v6.14.5

`npx create-nuxt-app` のUIフレームワークの選択でBuefyを選び、Nuxt.jsプロジェクトを作成したものとします。

## Storybookの導入
[公式ガイド](https://storybook.js.org/docs/guides/guide-vue/)の通りセットアップします。プロジェクトのルートディレクトリで以下を実行します。

```
npx -p @storybook/cli sb init --type vue
```

以下のディレクトリ・ファイルが自動的にできます。

```
./
├── .storybook
│   ├── main.js
├── stories
│   ├── 0-Welcome.stories.js
│   ├── 1-Button.stories.js
│   ├── MyButton.js
│   └── Welcome.js
```

この時点で、 `components` 直下に以下のようなコンポーネントを作成します。特に意味のないコンポーネントですが、Buefyの `b-input` を使っているところが重要です。

```MyComponent.vue
<template>
  <b-input v-model="variable" />
</template>

<script>
export default {
  name: 'MyComponent',
  data() {
    return {
      variable: 0
    }
  }
}
</script>
```

`stories/2-MyComponent.stories.js` を新規作成し、以下のように書きます。デフォルトで作成された他の2つの.stories.jsと同様に書いているので、一見正常に実行できそうな気がします。

```2-MyComponent.stories.js
import MyComponent from '../components/MyComponent'

export default {
  title: 'MyStory',
  component: {
    MyComponent
  }
}

export const Mytest = () => ({
  components: { MyComponent },
  template: '<my-component />'
})
```

しかし、厳しい現実に襲われます。`npm run storybook` を実行し、localhost:6006にアクセスして該当ページを見ても何も表示されません。Chromeの開発者ツールのConsoleに、以下のようなエラーが出ます。

```
[Vue warn]: Unknown custom element: <b-input> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
```

`<b-input>` がないよと怒られています。いやいやBuefy最初にいれたやんという気がしますが、どうもNuxtでimportされているものがStorybookでもimportされているとは限らないようです。
ちなみに `*.stories.js` では `import MyComponent from '@/components/Mycomponent'` もエラーになります。@がソースディレクトリを指していることを認識してくれません。StorybookはNuxtから独立したライフサイクルを持っているのでは？という気がしています。

さて、[参考記事](https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78)によると、Storybookの設定ファイルには3つ重要なものがあると書かれています。

* main.js  
  その名の通りメインの設定ファイルです。Storybookの生成を担当します。
* preview.js  
  Storybook全体で使いたいパラメータやコンポーネント等を指定します。
* manager.js  
  Storybook自体のUIをカスタマイズするために使います。あんまり使わないみたいです。

Buefyは全体で使いたいコンポーネントに相当するので、`.storybook` ディレクトリに `preview.js` を作成します。また、Buefyに加えてBuefyで使用するcssも読み込みます。([素晴らしい参考記事](https://kalappo.net/storybook-buefy-font/))

```previes.js
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'
import '@mdi/font/css/materialdesignicons.css'
import Vue from 'vue'

Vue.use(Buefy)
```

実行してエラーが出る場合は、mdiのせいと思われるのでmdiをインストールします。

```
npm i @mdi/font
```

以上で、Storybook上で `b-input` 等Buefyのカスタムタグが表示されるようになります。

## おわりに
* Nuxtで読み込んでいるものがそのままStorybookで使えるわけではない点
* グローバルに使いたいコンポーネント等の読み込みのために `preview.js` を作らなければならない点

以上2つが僕にとって初見殺しでした。同じようにハマった方の役に立てれば幸いです。

## 参考
[Storybook for Vue(公式)](https://storybook.js.org/docs/guides/guide-vue/)
[Declarative Storybook configuration](https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78)
[StorybookでBuefyのMaterial Design Iconsが表示されない](https://kalappo.net/storybook-buefy-font/)
python 3のhttp.serverを使って30秒でローカルwebサーバーを立てる

初心者でもできる、超簡単にローカルwebサーバを立ち上げる方法。
python環境が必要。

# python環境の確認
macであればデフォでpython2.7.xが入っている。

```
$ python -V
python 2.7.16
```

なおpython 2系でも別モジュールで簡単にローカルwebサーバを起動できるが、**python 2は2020年1月1日でサポートが終了している**のでpython 3を推奨。

# python 3系：http.serverモジュールを使う

ターミナルで以下のコマンドを実行。

```
$ python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
```
デフォルトのポートは8000だが、以下のようにポート番号指定もできる。
```python -m http.server 8080```

このコマンドを実行したディレクトリをルートにしてwebサーバが起動する。
次に、webブラウザで以下のどちらかのアドレスにアクセスする。
```http://localhost:8000```
```http://127.0.0.1:8000/```
![スクリーンショット 2020-06-26 7.11.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660621/db1c1f7e-8302-484b-25fe-d544d253be1c.png)
上のように、実行されたディレクトリやファイルがリストで表示される。
今回は、"Hello World!"と表示するテストプログラムを実行した。
![スクリーンショット 2020-06-26 7.17.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660621/696c9855-a73d-3f3b-aa1a-990b2eb4d677.png)
成功！

確認できたら、```Ctrl + c```でローカルサーバを終了。

# python 2系：SimpleHTTPServerモジュールを使う
手順はpython 3と同じ。

```
$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
```
フリー素材

・神奈川工科大学(標準画像データベースSIDBA)
[http://www.ess.ic.kanagawa-it.ac.jp/app_images_j.html](http://www.ess.ic.kanagawa-it.ac.jp/app_images_j.html)

・自作したもの(キャリブレーションボード)
![2c0224eef75036407dc60103187179a6[1].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/e0b6712d-913d-e865-4227-e1981070cb0d.png)
![53639189932b82a9a5fd0bfff63c9ee4[1].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/a118ec0d-055d-143f-af4b-662a7735ac2e.png)
![9db5ca1c3bbb16e63ce845311530c4bb[1].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/3ec97788-9ff4-96da-75d5-8e3ba157add1.png)
![cfd00b1c9cce7f1046f5a6d85b71624e[1].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/49328eb9-900a-a1af-9775-a183ec9d8344.png)
![2e30b0fa178956eba0296f16756a67dd[1].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/3154ea74-fced-563e-aff1-dad909c98c53.png)
Uncaught TypeError: fs.existsSync is not a functionのエラー解決

# 状況
Windowsアップデートついでにnode.jsとかモジュールをアップデートしたらelectronでエラーが出るようになった。

```
Uncaught TypeError: fs.existsSync is not a function'
```


![err.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169464/e7ee2fb4-b746-28fc-7242-53447cce514a.png)

# 環境

- windows 10 Pro Insider Preview 2004 (20150.1000)
- node v14.4.0
- Electron 9.0.4
- Vue.js 2.6.11
- Vuex 3.4.0
- vuetify 2.2.11

# 原因

ipcRendererが原因のもよう。
レンダラープロセスがノードモジュールにアクセスしようとして失敗しているみたい。

# 解決方法

vue.config.jsファイルに下記を追記したら動いてくれた。

```
module.exports = {
  transpileDependencies: [
    'vuetify'
  ],
  pluginOptions: {
    electronBuilder: {
      nodeIntegration: true
    }
  }
}
```

これでレンダラープロセスがノードモジュールにアクセスできるようになりエラーが回避できる。
ただし脆弱性になりうるので、公開するアプリなどでは注意が必要とのこと。
(自分用)AWS_1(Linux仮想マシンとインスタンスの起動/インスタンス周りを整理)

# 項目
1. Linux仮想マシンの起動と整理

# 1.Linux仮想マシンの起動
## 1-1.AWSコンソールにアクセス
- AWSにサインアップ後、ページからコンソールにアクセスする
- ルートユーザとIWA?ユーザが有るけど多分`ルート`で良いと思う...

## 1-2.インスタンスを作成(仮想マシンを起動)
1. コンソールから`EC2`を選択
2. 先に右上の所から東京リージョンを選択しとく
3. `インスタンスを作成`を選択
4. `Amazon Linux AMI`か`Amazon Linux2 AMI`を選択、取り敢えず無印を選択で良いはず
5. インスタンスタイプは`t2 micro`ってやつが無料枠なので取り敢えずそれ選択
6. インスタンス作成の確認→`作成`
7. キーペアを作成みたいなポップアップが出る、上のメニューバーから`新しいキーペアを云々`を選択、キーペア名は適当に<br>`キーペアのダウンロード`をし、後生大事に保存
8. キーペアを適当な場所へ移動させ、ターミナルにて置いてある場所まで`cd`
9. `chmod 400 キーペア名`でキーペアのセキュリティを上げる

## 1-3.パブリックIPアドレスを作成
- このままだと見るたびにIPアドレスが変わってなんかめんどくさい
- なのでIPアドレスを固定する

1. 左側のメニューから`Elastic IP`を選択
2. 青いそれっぽいボタンを押す
3. 指示に従い取り敢えずIPアドレスを作成
4. `アクション`を選択し、`作成したIPアドレスの関連付け`をクリック
5. インスタンスのテキストバーをクリックすると下になんか出てくる、選択
6. `関連付ける`を選択
7. 完了

## 1-4.HTTPで接続できる様にする
- SSHだけじゃ色々不都合

1. インスタンスのリストから右にスクロールして、`セキリュティグループ`のリンクをクリック
2. 上の方にある`アクション`を選択
3. `インバウンドルールの編集`を選択
4. `ルールの追加`クリック
5. `HTTP`か任意のそれを選択
6. 多分保存を押してもエラーが出る
7. 送信元みたいなところでエラーが出てるので、そこをクリックしSSHと同じ奴を選択
8. 保存
9. Flaskを使いたい場合は<br>`カスタムTCP`を選択、ポート番号を`5000`に、ソースは他と同じ様に`0.0.0.0/0`やるの忘れずに！

# 2.終わりに
- 次はリモートコントロールだったり
- 明後日ぐらいまでに`phpMyAdmin`を接続していよいよ開発へ
使用しない事にしているSELinuxについて 

# SELinuxとはアクセス制御である

### MACとDAC

- MAC(Mandatory Access Contorol:強制アクセス制御)
- DAC(Discretionary Access Contorol:任意アクセス制御)

従来のLinuxではファイルの所有者やrootユーザーがパーミッションを変更(DAC:任意アクセス制御)

MACではサーバー管理者によって定義されたセキュリティポリシーに従ってアクセス権がユーザーやプロセスに与えられる
(ファイルの所有者やrootユーザーであっても定義されている事以外は行えない)

### MAC(強制アクセス制御)の代表的なもの

- SELinux
- SMACK(Simplified Mandatory Access Contorol Kernel)
- AppArmor(Application Armor)

SElinuxとSMACKはセキュリティコンテキスト情報をファイルの拡張属性に保持
(ファイルシステムが対応している必要がある)
AppArmorはセキュリティコンテキスト情報をファイルパスで保持
(ファイルシステムを選ばない)

## SELinuxの機能

#### TE(Type Enforcement)

ラベルを付与する事で細やかなアクセス制御を実現
プロセス→「ドメイン」
ファイル・ディレクトリ→「タイプ」

#### ドメイン遷移

子プロセスを親プロセスとは異なるドメイン(権限の範囲)に遷移させる
(必要なものだけに制限する)

#### RBAC(Role Based Access Control)

従来のLinuxでrootユーザーが持っていた絶対的な権限を分散し、「システム管理者」、「WEB管理者」といったロール(役割)をユーザーに割り当てる




```bash
# 現在のSELinuxの状態確認
[root@host ~]# getenforce
Permissive
[root@host ~]# setenforce 1
[root@host ~]# getenforce
Enforcing
[root@host ~]# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          error (Success)
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      31
# Boolean値で示されるポリシー状態の取得
[root@host ~]# getsebool -a
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
antivirus_can_scan_system --> off
antivirus_use_jit --> off
auditadm_exec_content --> on
authlogin_nsswitch_use_ldap --> off
(略)
# ラベルを確認する
[root@host ~]# ps axZ
LABEL                             PID TTY      STAT   TIME COMMAND
system_u:system_r:kernel_t:s0       1 ?        Ss     0:00 /usr/lib/systemd/syst
system_u:system_r:kernel_t:s0       2 ?        S      0:00 [kthreadd]
system_u:system_r:kernel_t:s0       3 ?        S      0:00 [kworker/0:0]
system_u:system_r:kernel_t:s0       4 ?        S<     0:00 [kworker/0:0H]
system_u:system_r:kernel_t:s0       5 ?        S      0:00 [kworker/u2:0]
system_u:system_r:kernel_t:s0       6 ?        S      0:00 [ksoftirqd/0]
system_u:system_r:kernel_t:s0       7 ?        S      0:00 [migration/0]
system_u:system_r:kernel_t:s0       8 ?        S      0:00 [rcu_bh]
system_u:system_r:kernel_t:s0       9 ?        R      0:00 [rcu_sched]
system_u:system_r:kernel_t:s0      10 ?        S<     0:00 [lru-add-drain]
system_u:system_r:kernel_t:s0      11 ?        S      0:00 [watchdog/0]
system_u:system_r:kernel_t:s0      13 ?        S      0:00 [kdevtmpfs]
# ファイルのパーミッション、ラベルを確認
[root@host ~]# ls -Z
-rw-r--r--. root root system_u:object_r:unlabeled_t:s0 0527host02.log
-rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
-rw-r--r--. root root system_u:object_r:unlabeled_t:s0 newreq.pem
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 mnfstest

```
プログラマーって稼げるの？（自分用の記事です）

###記事を書いた動機
自分のプログラマーになる動機を見直すためです。
「なぜプログラマーになりたいのか？」を考え直すことで今後の学習に関して、無駄をなくしていこうと思っています。

###そもそもエンジニアって稼げるのか？
たぶん、無理です。少なくとも自分には。
そもそも、平均年収をみても、そこまで他業種とかけ離れている訳でもなく、いたって普通の年収ですよね。
SNSなどで「エンジニアは稼げますよ！」って言っているのは、万人向けではない。当たり前だけど。
そもそも、物事の金額は、「需要と供給」によって成り立っている。
「需要が高く、供給が少ない」場合に物の価値が上がる！
「エンジニア」は「自らのスキル」を物として、他者に提供（販売）していると言える。
じゃ、稼ぐためには？
そう、「需要が高いかつ参入者が少ない」案件を採るしか無い。
しかし、「参入者が少ない」ということは、「難しい」ということ。
どこかで聞いたけど、人間の才能はほとんど「遺伝」らしい。
自分の才能を過去の経験から「客観的」にみた場合、どうだろう？優秀だと思えるだろうか？

僕は、「エンジニアで」稼ぐのは、あきらめる！
短い人生、取捨選択は非常に重要だと思う。

###だけど、お金を稼ぎたい！（楽しいから）
まあ、他のことで稼げるものを探そう...。
さぁ、本題！
「なぜ、エンジニアになりたいのか」を考えよう！

結論、「詳しくは分からないw」
ハッキリ言って、「勘」だな、これは。
【Mac超初心者】ショートカットやファイル検索の方法とか

#はじめに
15年以上Windowsのみを使用して、初めてMacを使うようになってハマった(沼った)ことや、
便利なショートカットなど、自分用メモがメイン。

###装飾キーの記号
- ⌘：command(コマンドキー)
- ⌥：option(オプションキー)
- ⇧：Shift(シフトキー)
- ⌃：control(コントロールキー)



###ショートカット

- スクリーンショット

| ショートカットキー      |撮れるスクリーンショット    |
|:------------------|:------------------:|
|Shift + command + 3|現在の画面全体を撮影    |
|Shift + command + 4|マウスで範囲選択して撮影 |
|Shift + command + 5|撮影範囲や方法を詳しく撮影| 


- かな打ち状態で簡単に矢印を入力する方法

|方向|キー|
|:--:|:--:|
|←|z+h|
|↓|z+j|
|↑|z+k|
|→|z+l|

- cssをコメントアウトする方法

コメントアウトしたい箇所を選択して、`command + /`
解除も同様


####ディレクトリの検索方法
`command + Shift + G`を押すと下図のようになるので、そこにファイルパスを入力してEnterでOK。
![2020-06-26 02.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597055/8eaeddb2-db17-0642-5ac8-1bc9e5784c58.png)

そのうち整理するかも
django-sassを使ってみた

#django-sassとは？
`django-sass`はDjangoで扱うSassコンパイラパッケージです。
https://pypi.org/project/django-sass/

#なんでdjango-sass？
DjangoでSassを利用する場合、[django-libsass](https://github.com/torchbox/django-libsass)と[django-sass-processor](https://github.com/jrief/django-sass-processor)が使われることが多いです。
今回django-sassを選んだ理由はコードがシンプルで読みやすかったからです。扱いやすそうだったので使ってみました。

#環境
- OS: mac Catalina 10.15
- Python: 3.8.2
- Django: 2.2
- django-sass: 1.0.0

#インストールからコンパイルまで
基本的に[ドキュメント](https://pypi.org/project/django-sass/)の通りコマンドすればOKです。
####1. インストール
pipでインストールします。

```shell:shell
pip install django-sass
```

####2. Djangoのappsに追加
`settings.py`の`INSTALLED_APPS`にdjango_sassを追加します。

```python:settings.py
INSTALLED_APPS = [
    ...,
    'django_sass',
    ...,
]
```

####3. manage.py sassを実行
今回のプロジェクトの構成は以下の通りです。

```shell:shell

├── manage.py
├── my_project
├── my_app
├── templates
│    └── base.html
└── static
     ├── css
     └── scss
         └── main.scss
```
manage.py scssを実行します。

```shell:shell
python manage.py sass static/scss/main.scss static/css/main.css
```
第１引数はscssファイルのpathを、第２引数にはコンパイル後のcssファイルをどこに作成するか、pathを記述します。
ちなみに第２引数の部分は自動で生成されるので、ディレクトリなど作成する必要はありません。
laravel web.phpで解決　データベース項目追加できなかった件

課題で入力フォームを増やすというものがあったが、どれだけフォームを変更してもデータベースが更新されず常におなじ値になっていた。

原因は、以下の// Eloquent モデルが定数になっていたこと

```php
use App\Book;
use Illuminate\Http\Request;

/**
* 本のダッシュボード表示(books.blade.php)
*/
Route::get('/', function () {
    $books = Book::orderBy('created_at', 'asc')->get();
    return view('books', [
        'books' => $books
    ]);
    //return view('books',compact('books')); //も同じ意味
});

/**
* 新「本」を追加 
*/
Route::post('/books', function (Request $request) {

    //バリデーション
    $validator = Validator::make($request->all(), [
        'item_name' => 'required|max:255',
        'item_number' => 'required|min:1|max:3',
        'item_amount' => 'required|max:6',
        'published' => 'required|min:7',
    ]);

    //バリデーション:エラー 
    if ($validator->fails()) {
        return redirect('/')
            ->withInput()
            ->withErrors($validator);
    }
    //以下に登録処理を記述（Eloquentモデル）
// Eloquent モデル
    $books = new Book;
    $books->item_name = $request->item_name;
    $books->item_number = $request->item_number;
    $books->item_amount = $request->item_amount;
    $books->published = $request->published;
    $books->save(); 
    return redirect('/');
    



});

/**
* 本を削除 
*/
Route::delete('/book/{book}', function (Book $book) {
    $book->delete();       //追加
    return redirect('/');  //追加

});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Juliaを始めてみる（Windows10）

最近注目を集めているデータサイエンスの言語として`Julia`がある。
ウチの子から聞いて知ったが、`JupyterNotebook`の語源は
"Ju"lia + "Pyt"hon + "R"でということ。なるほど。
（ちなみにJupyterNotebookの前はIPython notebookだったみたい。だから拡張子が、`.ipynb`なんだね。）
今回は`Julia`を始めるための記事ということで、いろんなとこから調べたものをまとめるという記事になります。

#### Juliaについて
「`Python`や`R`とは何が違うの？」
から。
まずは簡単な歴史から。
僕が学生だった頃は`C言語`が主流で、在学中に`Java`が流行り始めたという流れ。途中に`R`が出てきた（研究では`Mathematica`を使ったりしてたが）。
このようにプログラミング言語はいろいろある。
その中で`C`よりも古くからよく使われているのが`FORTRAN`かな。
そんな数多くあるプログラミング言語を大きく2つにわけると次のようになる。

- 静的型：FORTRAN,C,C++.JAVA
- 動的型：R,Python,Mathematica

動的と静的って？いろんな違いはあるが、よく言われるのが「速さ」の問題。
静的は速く、動的は遅い。
それなら静的の方がいいんじゃないか？とか言われそうだが、動的の方がプログラミングはしやすい（多分カンタンと言って問題ない）。動的はコード書きながらそれ実行できるし。その分、実行速度の面では期待しちゃだめよって感じ。
基本的にこれら2つの問題はトレードオフで両方を兼ね備えるのは難しい。
その両方を求めてできた言語が`Julia`になるわけ。2012年にMITで。
つまり、進藤先生らの言葉を借りれば
Pythonのように書けて、Cのように動く
言語が`Julia`という感じ（らしい）。

実際に使ってみて思ったのはインストール（環境構築）すら簡単ですぐに使えるようになるし、プログラミングコードも簡潔に書けるからむしろPythonよりも簡単かも。と思ったくらい。

#### Juliaを使ってみる

Windowsへのインストールを想定しています。

[Julia](https://julialang.org/downloads/)

こちらから自分のプラットフォームに合わせたファイルをダウンロードしてインストールしてください。
その後はインストール先にPathを通すだけ。基本的にこれで使えるようになります。
Pathは「コントロールパネル」$\to $「システムとセキュリティ」$\to$「システム」$\to$「システムの詳細設定」$\to$「環境変数」
でPathの項目にインストールした場所を追加するだけ。
（これでわからない人はどっかでPathの追加方法などを調べてみてください。）

インストールが終わったら起動してみる。
起動すると

![julia.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543442/9fb421be-f6ed-2361-cf1d-c3c6e4c13920.png)

のようなPERLの画面が出る。ここに適当な計算式を入れてエンターすれば実行できる。
（困った人は`2+3`とか`println("Hello zumilab")`とか入力すればいい）
パッケージ管理も簡単で上の画面で`]`を入力する。

```julia
(v1.4) pkg>
```
のようにJuliaのバージョンの表示とパッケージ管理モードに移行する。
ここで`add パッケージ名`を入力すればよい。
ヘルプモードへの移行はJuliaモード時に`?`を押せばよい。JuliaモードへはBackspace押せば戻れる。

これで使えるようになったけど今後を考えるとずっとPERLでやるのは。。ってなるよね。
僕はPythonをVSCodeで使ってるからそっちでJuliaもという感じでやったりするけどそれもそんなに面倒じゃない。VSCode側でパッケージインストールすれば終わりだし。
とはいえ、便利だからとりあえずJupyterNotebookでは使えるようにしようか。
`IJulia.jl`というパッケージをJuliaにインストールする必要があるので、

```julia
(v1.4) pkg> add IJulia
```
を実行すると必要なパッケージがインストールされる。それ終わったら、BackSpace（Propagationじゃないよ）押してjuliaモードにして、

```julia
julia> using IJulia
julia> notebook()
```
とすればJupyterNotebookが起動して、今後はJupyterNotebookからカーネルで`Julia`を選べるようになる。
これで環境構築は多分おわり。カンタン。Pythonのときは色々やらなきゃだったから余計にそれ感じる。（PythonはAnacondaの記事が多すぎてそれで最初混乱した）
しかもパッケージはPythonとかRほど充実していないから使い勝手悪いと思うかもしれないけど、PythonとかRもコンピュータに入っていれば簡単に呼び出せるってのもいいよね。
そうなるともう`Julia`をメインでもよいのかもしれないね。
これは言い過ぎか。
では、次はまた別の記事で（多分CCA（Canonical Correlation Analysis）？）
画像１枚で３DモデルをつくるPIFuHD がうまく実行できない時の対処法

![result_cheerful-sportswoman-practicing-yoga-tree-pose-4498150_256.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/843d830d-0cb8-c888-8c15-51b66c3145eb.png)

[3D結果動画（GoogleDrive）](https://drive.google.com/file/d/1tVvNn91s3ekvy5FJuHsGJoxaDe9f3Jsy/view?usp=sharing)
[Colabノートブック・デモ](https://colab.research.google.com/drive/11z58bl3meSzo6kFqkahMa35G5jmh2Wgt#scrollTo=afwL_-ROCmDf)

##デモがうまく行かない時

・GitHubのReadMeに「深刻なアーティファクトが観察された場合は、removebgなどの既成のツールを使用して背景を削除してみてください。」とあるので、人物と背景のコントラストが明瞭なほうがいい。

・「Run PIFuHD!」というセルに、「-r」というメッシュの解像度を指定するオプションもあります。
Google Colabで実行する場合は256が限度です。
より高解像度のメッシュを再構築したい場合は、自分のマシンで試してください。

実行が終わると、resultsディレクトリにresult_{image_file_name}.objファイルができます。
**[Mesh Lab](https://www.meshlab.net/)というソフトでobjファイルをインポートすると、3Dオブジェクトを操作できます。**
機械学習関連の情報を発信しています。
https://twitter.com/JackdeS11
flaskが２回初期化される問題

#はじめに
Flaskを使ってアプリを作成し、Slackのボットでアプリからの通知していました。が、ローカルでデバックモードで試した時も、Herokuでデプロイしてみてもなぜか同じ通知が２回くる…。

<img width="421" alt="スクリーンショット 2020-06-25 4.31.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501835/cc41698a-f072-02b4-3506-9901e28479d6.png">

色々調べてみるとflaskが２回初期化されていることが原因でした。下に解決方法をまとめます。

#Development環境での解決方法

#####解決方法①
Flaskでアプリを作成する際は、debugモードにしておくと変更を加えたときに手動でリロードしなくて良いため、下のようなコードを書いている思います。

```python
if __name__ == '__main__':
    app.run(debug=True)
```
この部分を

```python
if __name__ == '__main__':
    app.run(use_reloader=False)
```
と変更するとリロードされません。

#####解決方法②
２つ目の解決方法としては、２回まわって欲しくない関数の上に

```python
@app.before_first_request
```
を追加する。

#Production環境での解決方法

以下のコードをProcfileに追加してからHerokuにデプロイしたら本番環境でもリロードされませんでした。

```python
web: gunicorn app:app --log-file - --workers 1
```




参考URL
https://stackoverflow.com/questions/9449101/how-to-stop-flask-from-initialising-twice-in-debug-mode

https://teratail.com/questions/111071



私はこれを解決するのにものすごく時間がかかってしまったので、誰かの参考になったら嬉しいです😊
Docker Toolbox 起動エラー対処

Windows 10 Homeにdocker toolboxをインストールする手順にて下記エラーが発生する場合、対処法を示す

###Docker インストール
手順は公式を参考 [公式](https://docs.docker.com/toolbox/toolbox_install_windows/)

###エラー
Toolbox起動後、下記エラーが表示される
`looks like something went wrong in step ́looking for vboxmanage.exe ́... press any key to continue`

###対処法
調べるとToolboxフォルダ内のstart.shでdocker-machine.exeを読み込むパスが主な原因らしい

####start.shをデバックする
start.shをvscodeでもメモ帳でもいいから開き、docker-machine.exeのパスを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301446/0142255e-c873-af91-16d9-ba253c005020.png)

次に、start.sh内の`DOCKER_MACHINE`パスを変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301446/e848684b-810d-dd32-4dcb-4590c911ad37.png)

再度Toolboxを起動すると直ります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301446/78a995bf-cd96-18dd-2878-f255cc16cf2e.png)


###忘れがち
virtualBoxをインストールし忘れないように
swift5でdictionaryをソートする

# 初めに
今回はdictionary型の変数をソートする方法を展開します
## dictionaryについて
此奴はハッシュテーブルな為、素早くキー検索ができるといういい点がありますが、格納順序は保証してくれるものではありません。
いいたいことは以下のことを指しています。
何もしないで抽出

```swift:test.swift
let testDict:[String:String] = ["01":"msTest","02":"mrTest","03":"Test"]
for (key, val) in testDict {
    println("key:\(key)\n value:\(val)")
}
```
出力結果

```console
key:02
value:mrTest
key:01
value:msTest
key:03
value:Test
```
こんな風にぐちゃぐちゃに辞書に格納されてしまいます。
## 今回の議題の解決策
順番を保証してくれるデータ型などはありますが、抽出の方法が違かったりと多々問題が出てくるので、dictionaryを手っ取り早くソートして順番通り表示します

```swift:test.swift
let testDict:[String:String] = ["01":"msTest","02":"mrTest","03":"Test"]
//昇順でソート
let sortData = testDict.sorted { $0.0 < $1.0 } .map { $0 }
for (key, val) in sortData {
    println("key:\(key)\n value:\(val)")
}
```
出力結果

```console
key:01
value:msTest
key:02
value:mrTest
key:03
value:Test
```
# 終わり
このように一文追加することでソートされます。
昇順で今回は例に出しましたが、もちろん降順でもソート可能です！
言語が保証してくれない物を無理やりソートするより、保証している物を使った方が楽ですが、dictionaryは扱いやすいし早いしなかなか捨てがたい物ではありますよね！
この記事がどなたかの助けになることを願っております。
MaixCubeを喋らせる

# はじめに

MaixCubeで[音声認識](https://qiita.com/fukuebiz/items/ba03b4a455bf2dbce311)は簡単にできたので、今度は喋らせてみましょう。

# eSpeak NG

オープンソースの音声合成エンジンはいくつかありますが、マイコンで動作させることができそうな軽量の[eSpeak NG](https://github.com/espeak-ng/espeak-ng)を使ってみます。辞書は実行時にファイルから読み込むのではなく、メモリに展開するようにします。

# サンプル

サンプルのコードは[こちら](https://github.com/fukuen/maixcube-espeak-demo)

本文はこんな感じです

```c++
#include <Arduino.h>
#include <MaixCube_eSpeak.h>

MaixCubeESpeak speak;

void setup() {
	pll_init();
	plic_init();
	uarths_init();

	speak.begin();

	sleep(1);
	speak.speak("Hello.");

	sleep(1);
	speak.speak("One two three.");

	sleep(1);
	speak.speak("I'm maix cube.");

}

```

# 最後に

うまくキャッシュできていなくて、若干途切れる感じがします。改良の余地がありますが、ソフトウェアのみで喋らせることができました。
[Android] Waiting For Debuggerが終わらない時の打開策💢

困って調べたのでメモ代わりに載せます

# 何のこと？
デバッグ中に起こる

```
Waiting For Debugger
Application is waiting for the debugger to attach.
```

このダイアログがいつまでも消えない問題。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277107/45ca8e61-d376-934b-a817-31f3e8afada8.png width=464/>
# 解決方法

エミュレーター側で、

1. Settings(設定) -> About emulated device(エミュレートされたデバイスについて) -> Build number(ビルド番号) を7回タップ　→Developer options(開発者向けオプション)が有効になる
2. Settings(設定) -> System(システム) -> Advanced(詳細設定) -> Developer options(開発者向けオプション) -> Select debug app(デバッグアプリを選択)を開き、自分のアプリを選択する

実機でも一緒だと思います。

調査時の環境：Android Studio 4.0 / Android 10
[Cloud Functions] Node.jsのバージョンを10にしたら「TypeError: Cannot read property 'charCodeAt' of undefined」ってエラーが出た

## 発生した問題
FirestoreのバックアップをCloudFunctionsで行っていたのだが、
Node.js 8 ランタイムが非推奨になり10にアップデートしないといけなかったので変更したら
変更後に以下のエラーが発生するようになった。

```
TypeError: Cannot read property 'charCodeAt' of undefined
    at peg$parsetemplate (/workspace/node_modules/google-gax/build/src/pathTemplateParser.js:320:17)
    at Object.peg$parse [as parse] (/workspace/node_modules/google-gax/build/src/pathTemplateParser.js:649:18)
    at new PathTemplate (/workspace/node_modules/google-gax/build/src/pathTemplate.js:32:54)
    at segments.forEach.segment (/workspace/node_modules/google-gax/build/src/pathTemplate.js:103:29)
    at Array.forEach (<anonymous>)
    at PathTemplate.render (/workspace/node_modules/google-gax/build/src/pathTemplate.js:97:23)
    at FirestoreAdminClient.databasePath (/workspace/node_modules/@google-cloud/firestore/build/src/v1/firestore_admin_client.js:792:57)
    at exports.scheduledFirestoreExport.functions.region.pubsub.schedule.timeZone.onRun (/workspace/index.js:11:12)
    at cloudFunction (/workspace/node_modules/firebase-functions/lib/cloud-functions.js:127:23)
    at Promise.resolve.then (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:330:28) 
```

## 解決策
FirestoreAdminClientのdatabasePathのprojectの指定を以下に変更した。
### Before

```javascript
const databaseName = client.databasePath(process.env.GCP_PROJECT, '(default)');
```
### After

```javascript
const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT;
const databaseName = client.databasePath(projectId, '(default)');
```
どうやらGCLOUD_PROJECTを指定するとエラーが消えるよう。

## 参考サイト
* https://github.com/firebase/snippets-node/pull/85
* https://stackoverflow.com/questions/62035940/cloud-function-fails-after-changing-runtime-to-node-js-10
PWAに対応したはずなのに「このサイトをホームに追加」バナーが表示されないときの対処法

ハマったのでメモ。

### 状況
- FCM (firebase cloud messaging) を使ってwebpush機能を実装＆実環境で動作確認済み
- その際によくネットに転がっている以下の書き方でserviceworkerを登録していない（ファイル名を`firebase-messaging-sw.js`にすると自動で読み込んでくれるのでこちらを利用した）

```
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register("/serviceWorker.js");
        }
```

- webpushが動作しているのでpwaには対応しているはずなのに、pcのchromeのアドレスバーにプラスボタンが表示されないし、androidのchromeでは「このサイトをホームに追加」のバナーが表示されない。また、androidのchromeで設定からホームに追加した際にアイコンの右下にchromeのマークが表示されてださい
- 開発者ツールのapplicationのタブにて `"No matching service worker detected. You may reload the page,or check that the service worker for the current page also controls the start URL from the manifest. "`と表示されている。

### 対処法
- `serviceWoker.js`を作成し上記のコードにて読み込む。

```js:serviceWorker.js

self.addEventListener('fetch', function(event) {

});
```

- fetchイベントが登録されていないと認識されないみたいなので空の関数を登録しておく

なぜこれで解決するかはわからないがとりあえず動いた
【AWS】CloudFormationでRoute53 Private Hosted Zoneを構築してみる

皆さんはEC2インスタンスなどAWS上のリソースの名前解決はどのようにしているでしょうか?
オンプレだとInternal DNS構築して管理すると思います
AWS上で管理するならマネージドの方がいいですよね
そこで今回はRoute53 Private Hosted Zoneを利用してマネージドで内部向けのDNS管理してみます
手ポチやawscliで地道に構築するより、CloudFormation (以下CFnと略) で構築した方が早いですしレコードの管理もしやすいので、CFnを使用した構築方法をご紹介します

# CloudFormation

今回はシンプルルーティングポリシーという極一般的なDNSを構築していきます

## テンプレート

Private Hosted Zoneの作成には`AWS::Route53::HostedZone`のVPCsでVPCオブジェクトを指定するだけです

```yaml
AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  HostedZoneName:
    Type: String
  HostedZoneVPCId:
    Type: AWS::EC2::VPC::Id
  FirstServerFQDN:
    Type: String
  FirstServerIPAddress:
    Type: CommaDelimitedList
  SecondServerFQDN:
    Type: String
  SecondServerIPAddress:
    Type: CommaDelimitedList

Resources:
  MyPrivateHostedZone:
    Type: AWS::Route53::HostedZone
    Properties:
      Name:
        Ref: HostedZoneName
      HostedZoneConfig:
        Comment: My Private Domain
      VPCs:
        - VPCId:
            Ref: HostedZoneVPCId
          VPCRegion:
            Fn::Sub: "${AWS::Region}"

  FirstServerRecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      Name:
        Ref: FirstServerFQDN
      Comment: FirstServer
      Type: A
      TTL: "300"
      HostedZoneId:
        Ref: MyPrivateHostedZone
      ResourceRecords:
        Ref: FirstServerIPAddress

  SecondServerRecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      Name:
        Ref: SecondServerFQDN
      Comment: SecondServer
      Type: A
      TTL: "300"
      HostedZoneId:
        Ref: MyPrivateHostedZone
      ResourceRecords:
        Ref: SecondServerIPAddress
```

## 注意点

### VPCの関連付け

Private Hosted ZoneをCFnで構築する際に関連付けられるのは1つのVPCだけです
追加で関連付けを行いたい場合はマネジメントコンソールやawscliなどから操作を行ってください
このようなにCFnでできないことがあるので、実運用ではPrivate Hosted ZoneとRecord setでCFnテンプレートを分けた方がいいかもしれません

また異なるAWSアカウントのVPCを関連付けしたい場合は、awscliやAPIからでしかできないので注意が必要です
手順は[作成済みの Amazon VPC と、別の AWS アカウントで作成したプライベートホストゾーンを関連付ける](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/hosted-zone-private-associate-vpcs-different-accounts.html)を参考にしてください

## 工夫点

### 複数IPアドレスの設定

`AWS::Route53::RecordSet`で複数のIPアドレスを設定できるように、FirstServerIPAddress / SecondServerIPAddressのパラメータタイプで`CommaDelimitedList`を指定します
これで冗長構成でも使えるCFnテンプレートになります

# 参考

- [プライベートホストゾーンの使用](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/hosted-zones-private.html)
- [AWS::Route53::HostedZone](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-route53-hostedzone.html)
- [AWS::Route53::RecordSet](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html)
MacでゼロからのFlutter環境構築

ゼロからFlutterの開発環境を構築するには以下の3つの手順が必要です。

1. Flutterを導入する
2. Xcodeを設定する
3. Android Studioを設定する

# Flutterを導入する
#### Flutterのインストール
[Flutter公式](https://flutter.dev/docs/get-started/install/macos)からインストーラーをダウンロードします。
ダウンロードした`zip`を解答して、`flutter`フォルダを任意の場所に置いてください。
私はアプリケーション直下に配置しました。

#### コマンドの有効化
- flutterフォルダの中にある`flutter_console.bat`を実行します。
これでFlutter Consoleからflutterコマンドが使えるようになります。

#### Pathを通す
`~/.bashrc`または`~/.bash_profile`に以下を記述する。

```console
$ export PATH=$PATH:/Applications/flutter/bin
```

# Xcodeを設定する
#### Xcodeのインストール
App Storeで`Xcode`を検索してインストールします。
Xcodeのインストールにはかなり時間がかかります。時間の余裕がある時にインストールをしておくのをおすすめします。

#### Xcodeの設定を変更する
このコマンドを実装する。これでXcodeが使用できるようになる。

```console
$ sudo xcode-select —switch /Applications/Xcode.app/Contents/Developer
```
ライセンスを表示して同意する。
コマンドから行ってもいいし、Xcodeを起動するでもOK。

```console
$ sudo xcodebuild -license
```

# Android Studio
#### Android Studioのインストール
App Storeで`Android Studio`を検索してインストールします。
こちらもなかなかお時間がかかりましたね。。

#### Flutter Pluginのインストール
`メニュー>Android Studio>Preference...`を選択する。
<img width="365" alt="スクリーンショット 2020-06-26 0.55.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/e24213d7-1cf4-4193-a1e6-def447ae4752.png">

横のメニューから`Plugin`を選択。`Flutter`を検索してインストールする。
※画像はインストール済み
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/3dc3f566-298a-0f10-201d-61334d629e4a.png" width=80%>

#### Android SDK toolsを設定する
`Android SDK tools`のパケージ名が`Android-SDK command line tools`に変わっていて、flutterからAndroid SDKをみにいくのに失敗するようになっていました。
なのでこちらを設定します。

先ほどと同様に`メニュー>Android Studio>Preference...`を選択します。
横のメニューの`Android SDK`を選択した、`SDK Tools`の一覧をみます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/d9e7750b-b36b-4148-ca1c-83aa59e0bf3d.png" width=80%>
こちらしたの方にある`Hide Obsolete Packages`のチェックを外すと`Android SDK tools`が一覧に出てくるのでインストールします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/856822ea-ca27-5d5f-f381-b7ad1fb84802.png" width=80%>

# 動作確認
ターミナルで以下を実行。こんな感じで返ってくれば完了です。
`No devices available`これはシミュレーターを起動していない時に出るので、実際作業するときはお忘れなく。

```console
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.15.4 19E266, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
[✓] Android Studio (version 3.6)
[!] Connected device
    ! No devices available

! Doctor found issues in 1 category.
```
.dll から .lib(import lib) を作成するメモ(MinGW, llvm-dlltool)

## 背景

MinGW で, .dll を使うアプリをビルドするのに, リンク用の .lib(import lib)を作成したい.

## 参考

MS-MPI(Microsoft MPI) の例

https://frontistr-commons.gitlab.io/FrontISTR/manual_en/install/install_11.html

## 手順

* .dll -> .def(テキスト)を作る
* .def から .lib(import lib)を作る

.def を作る方法はいくつかりますが(シンボル数が少なければ手書きという手もある), 今回は gendef(mingw tool)を使います.

## 環境, 必要なツール

Ubuntu 18.04 or later を想定します(e.g. WSL linux)
Linux で完結するようにします.


* gendef(.dll -> .def)
  * apt で `mingw-w64-tools` で入ります  
* llvm-dlltool
  * llvm-mingw などであります.
  * MinGW にも dlltool ありますが, うまくいかないときもあるっぽい?

## 手順

directml.dll を例にとります.

```
$ gendef directml.dll
$ llvm-dlltool -m i386:x86-64 -d directml.def -l directml.lib
```

でいけます!
SQLアンチパターン　ジェイウォーク

# はじめに

今までDBのテーブル設計をする際、業務や個人の学習としてサービスを作成しDBを見て触っていたため、なんとなくこういう設計をすればいいんだという曖昧な知識はあった。

個人の学習としてサービスを作成した際にもそこまで複雑な設計ではなかったため問題なく動くものは作れていた。

ただ、改めて「DBの設計についてちゃんと勉強したことないなぁ....」と思い勉強をしてみることに。

現状、最低限の設計については抑えている**つもり**ではいるので、今回はSQLアンチパターンに焦点を当てて学習をしてみる。

# ジェイウォーク（信号無視）

今回はジェイウォーク（信号無視）について。

ジェイウォークとは、１つの列に複数の値を格納するアンチパターン。
以下のようなパターンが当てはまる。

question

|id|question|choice|
|:---|:---|:--|
|1|問題文１|選択肢１,選択肢２,選択肢３|
|2|問題文２|選択肢４,選択肢５|
|3|問題文３|選択肢６,選択肢７,選択肢８|

# ジェイウォークのデメリット

ジェイウォークを使用することで以下のようなデメリットが発生。

* 特定の値を持つ行の検索時にパターンマッチが必要になる。
* データの更新、削除がしづらい。
* 外部キーを結合していた場合に意図した結果が取得できない。
* 集約クエリの作成ができない。
* 投入データの妥当性が担保されない。
* インデックスのメリットがない。
* データが増えることによる格納制限。

上記で挙げたようなデメリットが発生。

検索時にLIKE演算子が必要、更新には文字列の連結が必要でソートに対応しない、削除には元の値を取得して新しい値を保存、文字列として扱うため数値を扱いたい場合でも意図しない文字列が混入する可能性がある.....etc

# 解決策

**交差テーブル（中間テーブル）を作成する**

言わずもがなだが。
これを踏まえて先ほどのテーブルを再度見てみる。
choice列のデータがジェイウォークに該当する。

question

|id|question|choice|
|:---|:---|:--|
|1|問題文１|選択肢１,選択肢２,選択肢３|
|2|問題文２|選択肢４,選択肢５|
|3|問題文３|選択肢６,選択肢７,選択肢８|

これを修正すると以下のような構成になる。

question

|id|question|
|:---:|:---:|
|1|問題文１|
|2|問題文２|
|3|問題文３|

choice

|id|choice|
|:---:|:---:|
|1|選択肢１|
|2|選択肢２|
|3|問題文３|
|4|問題文４|
|...|...|

question_choices

|id|question_id|choice_id|
|:---:|:---:|:---:|
|1|1|1|
|2|1|2|
|3|1|3|
|4|2|4|
|...|...|...|

これで解決。

# まとめ

* 値は結合して格納せずひとつずつ列、行に格納した方が良い。

# 次回

ナイーブツリー （素朴な木）

# 参考文献

[SQLアンチパターン](
https://www.amazon.co.jp/SQL%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Bill-Karwin/dp/4873115892/ref=sr_1_1?adgrpid=104444684056&dchild=1&gclid=CjwKCAjw4_H6BRALEiwAvgfzqy-f83NTsyQkauo7gn6ysgAPmJvKyvuI5FaXFnxFmhVfCzCRRACsaBoCY-oQAvD_BwE&hvadid=447984765572&hvdev=c&hvlocphy=1009332&hvnetw=g&hvqmt=e&hvrand=13417269104929133208&hvtargid=kwd-335484809678&hydadcr=27264_11561110&jp-ad-ap=0&keywords=sql%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3&qid=1599934568&sr=8-1&tag=googhydr-22)

![参考文献.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257405/b46d45ab-75ec-a620-eeb2-a422f6b1e659.jpeg)
機械学習とFlaskを使ってボートレース3連単予測サイトを立ち上げるまで

#はじめに

この記事は、自身で製作しWeb公開にまで至ったボートレース３連単予測サイト「[きょう、ていの良い予想は当たるだろうか](https://youhaveniceboat.pythonanywhere.com)」の内部コード解説記事をまとめたものになります。

## データ取得編

* [Webスクレイピングでボートレース試合情報を取得する](https://qiita.com/NGOhiroshi/items/a9b22a7c5547c2f775be)

## データ整形編

* [取得した競艇テキストデータからデータフレームを作成する](https://qiita.com/NGOhiroshi/items/2373b8aaffd028c7e583)

## 機械学習で予測モデル作成編

* [ボートレースの3連単をランキング学習で予測してみる](https://qiita.com/NGOhiroshi/items/d841795e395791cf847c)

## FlaskでWebアプリ作成編
~~まだ未完成なので、出来上がり次第差し替えます。~~
↓記事できあがりました！(2020/6/27)
* [Flaskでオシャレなボートレース予想サイトをつくりあげる](https://qiita.com/NGOhiroshi/items/82a7342098bc1acc4eec)

## PythonAnywhereでLaunch編

~~未投稿~~
↓記事できあがりました！(2020/6/29)
[PythonAnywhereでFlaskアプリをLaunchする](https://qiita.com/NGOhiroshi/items/9e4ed09cd40b54373524)

## その他 Tipsなど

* [globで複数のエクセルを一挙取得する（ボートレース機械学習予測結果　6月分の確認）](https://qiita.com/NGOhiroshi/items/db9a5ac910d8ac1a521a)
* [Twitterにて競艇の3連単予想をつぶやく](https://qiita.com/NGOhiroshi/items/9d7a7080683ec02af96d)　(2020/7/19追加)