OmniAICreator/Qiita-1.07M huggingface dataset:
AWS fargateでkotlin(java)アプリをデプロイする方法

# ポイント
- fargateのタスク定義の「タスクメモリ」で指定したメモリ量を超えた場合、タスクは強制終了されます。
- 従って、タスクメモリを超えないように最大ヒープサイズ等を調整する必要があります。

# 環境
- 言語: Kotlin
- フレームワーク: ktor
- dockerイメージ: openjdk:8-jre-alpine

# Dockerfile

```Dockerfile
FROM openjdk:8-jre-alpine

ENV APPLICATION_USER ktor
RUN adduser -D -g '' $APPLICATION_USER

RUN mkdir /app
RUN chown -R $APPLICATION_USER /app

USER $APPLICATION_USER

COPY ./build/libs/my-application.jar /app/my-application.jar
WORKDIR /app

CMD ["java", "-server", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-XX:InitialRAMFraction=2", "-XX:MinRAMFraction=2", "-XX:MaxRAMFraction=2", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-XX:MaxMetaspaceSize=256M", "-XshowSettings:vm", "-jar", "my-application.jar"]

```

基本的には[ktorのドキュメント](https://jp.ktor.work/quickstart/quickstart/docker.html#docker%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E6%BA%96%E5%82%99)を元にしていますが、以下のjavaのオプションを追加しました。

- `-XX:MaxMetaspaceSize=256M` : メタスペースの最大値を256MB確保して、それ以上増やさない設定です。 デフォルトでは無制限に拡張できてしまうので、念のため最大値を設定しました。
- `-XshowSettings:vm` : 起動時にVMの設定を出力します。

# fargateのタスク定義

コンテナの定義で、メモリのハード制限を必ず指定してください。
ここで指定した値が、 `docker run` の `--memory`オプションに渡されます。
通常は、タスクメモリと同じ値を指定してください。

![スクリーンショット 2020-08-27 16.08.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9875/9c10efd2-022f-067a-f4e3-c32e627308b6.png)

# タスクのログの確認

Fargateのタスクのログを表示し、`Max. Heap Size`が想定した値になっていることを確認してください。
今回の場合は、ハード制限が1000MiBで、javaのオプションが "-XX:MaxRAMFraction=2" なので、500Mとなるのが正しいです。


![スクリーンショット 2020-08-27 15.39.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9875/15658c35-8e8d-df78-dd6c-a1c72537e067.png)

# 参考
- [Ktorクイックスタート: Docker](https://jp.ktor.work/quickstart/quickstart/docker.html)
- https://github.com/ktorio/ktor/issues/1059
- [fargate タスク定義パラメータ](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html)
- [JVMのヒープサイズとコンテナ時代のチューニング](https://i-beam.org/2019/08/15/jvm-heap-sizing/)
DockerをPokemonでわかりにくくして、取っつきやすくしてみる

# マッピング

| Pokemon | Docker |
| --- | --- |
| 敵 | アクセス数 |
| ポケモン | コンテナ |
| モンスターボール | コンテナイメージ |
| パソコン | コンテナレジストリ、DockerHub ...etc |
| バトルフィールド、ポケモンリーグ | Dockerエンジン、Fargate |
| ポケモントレーナー | Kubernetes |

# 例文

## 例文１
Pokemon
* 敵が強いので、ポケモン（ピカチュウ）の２体目を召喚した

Docker
* アクセス数が多いので、コンテナを２つにスケールアップした


## 例文2
Pokemon
* ポケモンがある程度強くなったので、モンスターボールに入れた

Docker
* コンテナの設定が完了したので、コンテナイメージを作成した
 
## 例文3
Pokemon
* モンスターボールがいっぱいになったので、パソコンに転送した

Docker
* コンテナイメージが邪魔なので、コンテナレジストリに登録した
 
## 例文4
Pokemon
* 通信で、他の人のモンスターボール（ルージュラ）を取り出して、育成した

Docker
* Docker Hubから、CentOSのイメージをPullして、Nginxをインストールした

## 例文5
Pokemon
* ポケモンリーグに出場するので、バトルフィールドに、ピカチュウを召喚した

Docker
* 本番環境に公開するので、Dockerエンジンににコンテナを展開した

## 例文6
Pokemon
* 敵が弱ってきたので、ポケモントレーナーはポケモンを戻して１匹にした

Docker
* アクセス数が減ってきたので、Kubernatesは１コンテナにスケールダウンした

# 余談
Dockerを何か身近に感じてもらうために、雑談中に思いついた内容ですが、
案外的を得ているのかと思って投稿しました。

こんな、変換もできるとか、コメントもらえると嬉しいです。
nteractのインストール

# nteractとは？
- Netflixなどで利用されてるjupyter環境
- デスクトップ版と通常のjupyterのようなweb版がある
- ビジュアライズ機能に特化してる
- csv取り込んでDataFrameにするだけで色々なグラフを描画してくれる
- jupyter環境なのでpythonを使える

# web版のインストール
```
pip install nteract_on_jupyter
```
anaconda環境があればこれで基本は入るはず

# 起動
```
jupyter nteract
```
consoleでこれを叩けば起動する

# 起動画面
![スクリーンショット 2020-08-27 16.06.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315596/934a318b-5d8e-574c-8995-c147c37f4c05.png)

こんな感じのがブラウザに立ち上がる
pythonのマークをクリックするとファイルが作成される

# 
```python:test.ipynb
import pandas as pd
df = pd.read_csv("data.csv")

pd.options.display.html.table_schema = True #Data Explorer有効化
pd.options.display.max_rows = None #全行表示

df
```
pandasでcsvを読み込み、optionを設定する

![スクリーンショット 2020-08-27 16.11.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315596/098f4f5c-d4e5-7543-2d8e-8e8ac56e5a3a.png)


dfを叩くと表示される

![スクリーンショット 2020-08-27 16.18.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315596/93e56bd7-10fb-ecd3-d4d0-21915728d18d.png)

グラフはこんな感じ

# まとめ
インストールは簡単だったけど情報が思っていたよりすくなかった。
ボタンをクリックしたら端からプロフィールが出てくるアニメーション

#はじめに
ブログでよくある最初は隠れていてボタンを押すとプロフィールがヌッと出てくるアニメーションを作りました。
最初からプロフィールを表示しているサイトもありますが、トップページの面積を大きく使いたいときに便利です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597972/467f5d21-eab9-c4c4-3ebb-bda54a2d8e0c.gif"width=50% height=50%>
#ポイント
<h5>・端から出したい要素を画面の外に隠す</h5>
```html
.profile{transform: translateX(-100vw);} //左に隠す場合
.profile{transform: translateX(100vw);} //右に隠す場合
```
transformを使ってCSSだけで隠すとjQueryでhideやfadeOutを書く手間が省けます。

<h5>・隠した要素を表示するためのclassを記述</h5>
```html
.profile.active{transform: translateX(0%);}
```
transformで画面の外に隠した要素のtranslateXを0%にすることで画面内に表示させることが可能です。
このあとアニメーションを出し入れするためにjQueryでtoggleClassメソッドを使うので、出し入れ用のクラスをactiveと命名してます。
ちなみにSCSSを使用する場合、入れ子の中にいれると動作してくれなくなるので僕はこのコードだけ入れ子の外に書いています。なんでかは分かりません。今度調べます。
<h5>・toggleClassメソッドで出し入れ</h5>
ボタンをクリックしたら先程のactiveクラスのstyleをprofileクラスに追加、追加されている状態でもう一度押したらactiveクラスが消える動作をtoggleClassメソッドで書きます。

```javascript
jQuery(function ($) {
  $(".profileButton").on("click", function () {
    $(".profile").toggleClass("active");
  });
});
```

ただ、このままではヌッというよりボンッという感じなので、profileクラスに

```css
.profile{transition: all 0.3s linear;}
```
こうすればOKです。
残りの詳しい設定はCodepenでご確認ください。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="hato0317" data-slug-hash="GRZmZVV" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="GRZmZVV">
  <span>See the Pen <a href="https://codepen.io/hato0317/pen/GRZmZVV">
  GRZmZVV</a> by hato0317 (<a href="https://codepen.io/hato0317">@hato0317</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
【Railsでhamlに動画を挿入する方法】

動画が挿入できると、webサイトをお洒落でカッコよく装飾できます。
今回はRailsでhamlに動画を挿入する方法を詳しく解説していきます。

# publicフォルダにvideosフォルダを作成
テキストエディタで新しいフォルダを作成をクリックし、public下にvideoフォルダを作成します。

# videoフォルダ下に挿入したい動画ファイルを入れる
使用したい動画ファイルをvideoフォルダ下に持ってきます。

この時、**動画ファイルの拡張子は<font color="red">mp4</font>**を使用してください！
なぜなら、現在mp4をほとんどのブラウザが対応しているからです。
今回は拡張子mp4のファイル、sample_video.mp4を用います。

# hamlに以下を記述
```ruby:◯◯.html.haml
= video_tag("/videos/sample_video.mp4", autoplay: true, loop: true, muted: true, class: 'video')
```

1つずつ解説していきます。
**= video_tag**
ビデオタグを用いて動画ファイルを呼び出すことが可能になります。

**/videos/sample_video.mp4**
参照するフォルダを指定します。

**autoplay: true**
ページ更新時に自動的に再生させることが可能になります。

**loop: true**
動画終了時に、初めから繰り返し再生してくれます。

**muted: true**
無音で再生されます。

すると、このように動画がwebサイトに表示されます！
![sample_video.mp4](https://i.gyazo.com/download/6fd0691f74838e4a680cc9d9622b21e2.gif?_ga=2.264337359.1717640144.1598501476-1272755455.1591584920)

今回のように、classを指定すればscssにて動画のレイアウトを変更することも可能です！

# 終わりに
動画挿入は比較的に簡単でしたが、初めてだったので動画作成するのに時間がかかりました笑
動画はMacのiMovieで作成しました！

**注意点として、
動画ファイルの容量が大きすぎると表示がされなかったのでなるべく小さく保存してください。**

お洒落でかっこいいwebサイト作成のために、ぜひこの記事を参考に動画を挿入してみてください！

参考にした記事
【videoタグ】HTMLで動画を埋め込む方法を徹底まとめ(サイトはHTML表記）
https://webliker.info/52510/
【個人メモ】画像ファイルの白い部分を透過させる

# 初めに
発表スライドに使おうと思った画像が透過しないもので，かっこ悪かったので白い部分を透過させたい．

# やり方
白はRGB値が(255,255,255)．
画像を読み込んで，RGB値が(255,255,255)のピクセルに対して透過度が0になるようにしてあげて，最後に透過度のデータを含んだ形で保存してあげる．

```matlab:white2transparency.m
% read imagefile
[file,path] = uigetfile('*.*');
filepath = sprintf('%s/%s',string(path),string(file));
image = imread(filepath);

% add alpha info
[L M N] = size(image);
Alpha = ones(L,M);

for i=1:L
    for j=1:M
        if image(i,j,:) == [255 255 255] % RGB value
            Alpha(i,j) = 0;
        end
    end
end

% savefile
filter = {'*.png';'*.*'};
[file2, path2] = uiputfile(filter);
imwrite(image,string(file2),'Alpha',Alpha);
```

RGBの値を任意の色に変えれば他の色を透過させることもできる．


ファイルはファイル選択ダイアログから選択できるようにしてある．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647345/1da0ced3-be6f-d4d2-9c8a-b2030451cebc.png)


RGB値で選択しているので，複雑な形状であってもきれいにくりぬけるのが良いですね．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647345/600cc471-f35b-d74a-7de9-56743fac73fe.png)


# 〆
同じことができるアプリはたくさんありそうですが，こうした簡単な加工は自分でできるようになりたいと思っています．
nautilus(ファイル)の右クリックメニューから「消去したファイルを復元...」を消す

# はじめに
UbuntuなどのGNOMEデスクトップ環境上で、以下のように「消去したファイルを復元...」というメニューが出る場合があります。
「端末で開く」の下に出てくるせいで間違えて押すことが多くて鬱陶しいので、これを非表示にしたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192805/85b42a10-85ee-e1dd-076e-43cc4063907a.png)

# やり方
この項目が表示されるのは、Deja Dupというバックアップ用ソフトウェアがインストールされていることが原因です。
Ubuntu等のDebian系Linuxの場合、以下のコマンドでアンインストールできます。

```
$ sudo apt remove deja-dup
```

これで表示されなくなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192805/2d63ecf0-e28e-6c65-6e8c-4249bc8492b2.png)

# 参考
["Remove “Restore Missing Files…” from my context menu in Nautilus?" - Ask Ubuntu](https://askubuntu.com/questions/632819/remove-restore-missing-files-from-my-context-menu-in-nautilus)
CakePHPにおけるrenderメソッド

#プログラミングの勉強日記
2020年8月27日
Railsではrenderメソッドを使ったことがあったけど、CakePHPでも使えたのでrenderメソッドについてまとめる。

#renderメソッドとは
　別のビューファイルを描画したいときに便利なメソッド。Controller::render()メソッドは各アクションの最後に自動的に呼び出されて、ビューを描画する。なので、別のビューファイルを指定するときには、renderメソッドを使用すると非常に便利。

#使い方
　renderメソッドに引数を指定しない場合は、通常通りにビューファイルが呼び出される。引数を指定しない場合はrenderメソッドを使用しなくてもビューファイルは自動的に呼び出されるのであまり必要ない。

```php
$this->render();
```
　renderメソッドに引数を指定すると、引数で別のビューファイルを指定することができる。この引数で指定したビューファイルが表示される。

```php
$this->render('/test/testSample');
```

#注意点
　renderメソッドはsetメソッドで渡したデータを使ってビューファイルを描画する。そのため、renderメソッドを先に指定してしまうと、以降の処理は実行されないので書く順番に注意する。

　
#参考文献
[【CakePHP入門】render()メソッドで任意のViewファイルを指定する
](https://www.sejuku.net/blog/28847)
VScode カスタマイズ 【色】

 
##こういう人向けの記事

- プログラミング初学者で、VScodeのデフォルト設定に少し飽きてきた人

- ファイル毎に色分けして作業・管理したい人

- 変数や関数・文字列・コメントアウトの色を個別にカスタマイズしたい人


##【手順】
- 色の設定は、基本```"editor.tokenColorCustomizations"```で行う

- 設定画面から検索 →　setting.jsonで編集

- 全体の設定は「ユーザー」、ファイル個別の設定は```<b><font color="orange">「ワークスペース」</font></b>で行う

<img src= https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696481/16c8d866-3aa5-1310-7696-76b4b377773b.png width= 60% >


##タイトルバー（上）とステータスバー（下）の色を変更

<details><summary></summary><div>

```java

    "titleBar.activeBackground": "#ff7f50", //タイトルバーファイル展開
    "titleBar.activeForeground":"#fff", //タイトルバーの文字色

    "statusBar.background":"#00ada9", //ステータスバー（ファイル展開時）
    "statusBar.foreground": "#fff", // ステータスバー文字色
```
</div></details>


##関数・変数・文字列・コメントアウトの色を変更

<details><summary></summary><div>

```java

 "editor.tokenColorCustomizations": { 

    "comments": "#719bad",   //コメントアウトの色 
    "keywords": "#20b2aa",// 定数・変数宣言 const let
    "functions": "#e3e548", //関数 メソッド
    "numbers": "#e7e7eb", //数字
    "strings": "#b28c6e",//文字列
    "variables": "#e3acae",//変数の色とスタイル
}
```
</div></details>

####興味があれば、公式サイトへ。 無限にカスタマイズできます。
<b>[公式サイト] https://code.visualstudio.com/api/references/theme-color

####色をお探しならコチラ。　選ぶだけで1日終わる。
<b>[洋色大辞典] https://www.colordic.org/y
vue.js 画像遅延ロード

vue.jsの画像遅延ロードを色々使ってみたが、
画像を div で囲わなきゃいけなかったりで面倒。

ということで

https://github.com/aFarkas/lazysizes

を使ってみる

参考
https://www.kabanoki.net/6997/

インストール

```

npm install lazysizes --save

```

インポート

```app.js

import 'lazysizes';
import 'lazysizes/plugins/parent-fit/ls.parent-fit';

```



```hoge.vue

<img data-src="/img/mypage-banner.png" class="lazyload">

```

これで 読み込まれた後に
class が `lazyload` から `lazyloaded` に変わっていればOK


# 動的に lazyload したいんだけど
動的に生成しようとするとうまくいかない。
ということでこういう場合はelmentuiのel-imageを使って
computed を使って画像の url を返しましょう

```

<style type="text/css">

//画像がにじむのでスタイルを解除しておく
    .answer-show .el-image__inner {
        width: auto;
        height: auto;
    }

</style>

<template>

    <div>

        <div class="article-show answer-show" style="max-width: 620px;margin: auto;">


            <el-row v-for="(v,key) in list" :key="key" :to="{ path: '/'}">
                <el-col :span="20">
                    <el-image :src="getImg(v.question_id)" lazy></el-image>
                </el-col>
            </el-row>


        </div>






    </div>


</template>

//略

        computed: {
            // 算出 getter 関数
            getImg() {
                return function(value) {

                    var res = 'https://twi.ski/gcp-storage/ogp-question-'+value+'.png';
                    return res;
                }
            }
        },


```

こんな感じ。
WSL2で、`docker-compose up` したら、shファイルは見当たらないというエラーが出た

----
[追記]
環境構築手順のまとめを [Windows 10 Home WSL2でDockerを使う](https://qiita.com/wakki_haya/items/da1a4e15b1d347ef3c1e) に更新しました

----

### 環境
- WSL2 (windows 10 Home)
- ubuntu 
- Docker for Windows を使用

### 手順
```docker-compose.yml
services:
  rails:
    <<: *app_base
    shm_size: 2G
    command: bin/start_dev_server.sh
```

で、 `docker-compose up` をした。



### エラー内容
```
ERROR: for rails  Cannot start service rails: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"bin/start_dev_server.sh\": stat bin/start_dev_serversh: no such file or directory": unknown
```

「shファイルが見当たらない/unknown だよ」というエラーが出た。

### 原因
WSL2では、`mnt/c`の絶対パスが適用されるが、
Docker for Windows のVMでは、 `c` の絶対パスが適用されるので、そもそものルートパスが違かったのが原因ぽい。

詳しくは、[Docker-compose and incorrect absolute paths for volumes](https://github.com/microsoft/WSL/issues/1854)


### 解決策
```
$ sudo mkdir /c
$ sudo mount --bind /mnt/c /c
$ cd /c/path/to/project
$ docker-compose ...
```

Ubuntu上でWindows配下( `/mnt/c` ) のファイルをmountする
JenkinsのPipeline script from SCMのスクリプトから別のgroovyを読み込む

## はじめに

GitHubでJenkinsのPipeline scriptを管理している中で、
共通処理なんかをまとめて呼び出したくなったので色々調べたり実行したりした内容のまとめ

## 環境・前提

- Jenkins 2.235.5
- SCMはgit（GitHub）
- パイプラインの記述はDecrarative Pipeline
- ここに記載したコード等は仮で記述しているので動作確認はしていません

### ディレクトリ構成

```
repository-root
└─jenkins-pipeline
   ├─main.groovy
   └─partials
     ├─fuji.groovy
     └─kiku.groovy
```

- jenkins-pipeline配下にスクリプトを配置している
- `jenkins-pipeline/main.groovy` をScript Pathに指定している

## main.groovyから別のscriptを読み込む

- script内で `load` を行うだけでOK
- 読み込まれる対象のスクリプトは最後に `return this` を記述
- 途中でworkspace内のブランチ変更などが行われたときにエラーにならないように事前に読み込んでおくのが良さそう
- `pwd()` はジョブのworkspaceが返却される
  - e.g.) makai-jobの場合
    - `/path/to/jenkins/workspace/makai-job`


```groovy:jenkins-pipeline/main.groovy
pipeline {
    agent any
    stages {
        stage('Initialize') {
            steps {
                script {
                    fuji = load "${pwd()}/jenkins-pipeline/partials/fuji.groovy"
                    kiku = load "${pwd()}/jenkins-pipeline/partials/kiku.groovy"
                }
            }
        }
        stage('exec fuji') {
            steps {
                script {
                    fuji.say()
                    fuji.sing("Lemon")
                }
            }
        }
        stage('exec kiku') {
            steps {
                script {
                    kiku.say()
                }
            }
        }
    }
}
```


```groovy:jenkins-pipeline/partials/fuji.groovy
def say() {
    echo "I'm fuji aoi!"
}

def sing(String title) {
    script {
        print "Sing th ${title}"
    }
}

return this
```


```groovy:jenkins-pipeline/partials/kiku.groovy
def say() {
    script {
        print "I'm kikunojo!"
    }
}

return this
```

## おわりに

はまったのはgit branchの切り替え前にスクリプトをロードしておかないと対象のブランチの状態によってはスクリプトが存在せずにFile Not Foundになってしまうところ。
解決してみればそりゃそうだって感じですけど挙動を知っていないとこういうところでハマってしまいますね……

もっと良い方法などあれがご指摘いただけると助かります。
【Kotlin】Listの中身のnameをコンマ区切りで表示したい

```kotlin
class Person(
    val id,
    val name,
)
```

上記のようなリストがあり、`name`をコンマ区切りで一覧表示したい場合、

```kotlin
val personList: List<Person> = listOf(Person("01", "西野"), Person("02", "齋藤"))

personList.joinToString(",") { it.name }
```
となる。

### 補足

リストが空の時、`参加者なし`と表示したい場合、

```kotlin
personList.joinToString(",") { it.name }.ifEmpty{ "参加者なし" }
```
とすれば良い。
RedBearLab nRF51822へのスケッチ書き込み手順

## はじめに
４年ぶりに、RedBearLab nRF51822 にプログラムを書き込もうとしたら、前回書き込んだ時の記憶が全くなくて、なかなかうまく行かなかったので備忘録を残します。

## 現象
WindowsPCから書き込むので[こちら](https://github.com/RedBearLab/nRF51822-Arduino#getting-started)のサイト通りにセットアップしました。
スケッチの書き込みでは正常終了のログが表示されるにも関わらず動作しません。
サンプルのBlinkすら動かないので何も書かれていないように見えます。

## 原因と対応
IDEやボードのバージョンを色々と変えてみても状況変わらず。
工場出荷時のブートローダーを上書きすることで解決しました。

### ブートローダーの書き込み
[GitHub](https://github.com/RedBearLab/nRF51822-Arduino)からZIPをダウンロードし解凍します。
マイコンボードをPCにUSBで接続し、表示されたMBEDドライブに以下のファイルをドラッグします。

* nRF51822-Arduino-S130&yen;bootloader&yen;bootloader.hex
![WS000172.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/f9d1209f-686a-5068-3ad5-7956a6138f08.jpeg)
※[こちら](https://os.mbed.com/blog/entry/DAPLink-bootloader-update/)によるとWindowsのStorage Serviceを停止する必要があるようです。

### ファームウェアの書き込み
ブートローダー更新で直らない場合はファームウェアも更新してみます。
マイコンのリセットスイッチを押しながらマイコンボードをPCにUSBで接続し、スイッチを離します。
表示されたBOOTLOADERドライブに以下のファイルをドラッグします。

* nRF51822-Arduino-S130&yen;interface&yen;mk20&yen;board_v1.5&yen;cmsis-dap&yen;RBL_nRF51822_MK20.bin
![WS000170.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/8fa3934c-6be2-d2e7-6ad1-09bb0399067d.jpeg)

## 成功したときの環境

|項目|内容|
|---|---|
|IDE|Arduino version 1.8.13|
|ボード|RedBearLab Boards(32-bits ARM Cortex-M0) by RedBear バージョン1.0.7<br>RBL nRF51822(V1.5 32KB)|
|書込装置|DAPLink|

## 備考
マイコンボードをPCにUSBで接続していると、定期的にストレージとして認識しているドライブが再接続されて鬱陶しいですが、書き込みには影響ないようです。

## さいごに
RedBearLabのサイトがなくなっているのでメーカーからは入手出来ないようです。
このボードも千石電商さんの在庫限りのようなので、今後は Bluno か ESP32 などに移行する予定です。

## 参考にしたサイト
* [RedBearLab BLE Nano v1.5 をBLE Snifferとして試す](https://kunsen.net/2018/07/08/post-536/)
* [BLE経由で組み込みソフトのアップデートができるなんてそんな夢みたいな話…あったわ！](https://www.dorapro.co.jp/engineerblog/?p=1067)
Railsの環境構築でハマったのでメモ

環境ぶっ壊れてrailsの環境構築し直したら色々エラーに悩まされたので自分用にメモ
詰まるポイント全部乗せみたいな感じで解決まで時間がかかってしまった...
なんだかんだこのエラーぶち当たること多い気がするので次はすぐできるようにメモしておこうかなと

# 最初のエラー
最初はlibv8のエラーから始まり...(他のエラーとか全然残していなかった...)

```
An error occurred while installing libv8 (3.16.14.19), and Bundler cannot continue.
Make sure that `gem install libv8 -v '3.16.14.19' --source 'https://rubygems.org/'` succeeds before bundling.
```

```
 libv8対策
bundle config --local build.libv8 --with-system-v8 
bundle config --local build.therubyracer --with-v8-dir=$(brew --prefix v8-315)
```

```
mysql2対策
$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl/include"
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
```

```
therubyracer対策
$ brew install v8@3.15
$ bundle config build.libv8 --with-system-v8
$ bundle config build.therubyracer --with-v8-dir=$(brew --prefix v8@3.15)
```

これでbundle installで解決しました
【Ruby on Rails】redirect_toメソッドの使い方まとめ

#【Ruby on Rails】redirect_toメソッドの使い方まとめ

Railsにビルドインされているredirect_toメソッドを使うことで、**action内**でページ遷移の設定をすることができる。



**▼記述**
`redirect_to パス`

パスの指定方法は複数ある。


1. [pathで指定](#1-pathで指定)
2. [アクション名で指定](#2-アクション名で指定)
3. [コントローラー名で指定](#3-コントローラー名で指定)
4. [コントローラー名とアクション名で指定](#4-コントローラー名とアクション名で指定)
5. [コントローラー名とアクション名とid名で指定](#5-コントローラー名とアクション名とid名で指定)
6. [URLで指定](#6-urlで指定)
7. [model名（クラス）で指定](#7-model名クラスで指定)
8. [パラメータで指定](#8-パラメータで指定)
9. [メッセージを指定](#9-メッセージを指定)
10. [ステータスを指定](#10-ステータスを指定)


＞[公式ページ](https://railsguides.jp/layouts_and_rendering.html#redirect-to%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B)



<br>
##1. pathで指定

`redirect_to XXX_path`
　┗ XXX: パスのprefix

```rb:例
redirect_to articles_path
```


<br>
パスの確認は、`rails routes`で可能。

```:terminal
$ rails routes
      Prefix Verb   URI Pattern                  Controller#Action
welcome_index GET    /welcome/index(.:format)     welcome#index
     articles GET    /articles(.:format)          articles#index
              POST   /articles(.:format)          articles#create
  new_article GET    /articles/new(.:format)      articles#new
 edit_article GET    /articles/:id/edit(.:format) articles#edit
      article GET    /articles/:id(.:format)      articles#show
              PATCH  /articles/:id(.:format)      articles#update
              PUT    /articles/:id(.:format)      articles#update
              DELETE /articles/:id(.:format)      articles#destroy
         root GET    /                            welcome#index
```


<br>
##2. action名で指定
コントローラーを指定せず、アクション名のみを指定した場合、現在のコントローラーの該当するアクションにリダイレクトされる。

`redirect_to action: :アクション名`

```rb:例
redirect_to action: :new
```



<br>
##3. コントローラー名で指定
アクションを指定せず、コントローラー名のみ指定した場合は、**指定したコントローラーのindexアクションに飛ぶ**

`redirect_to controller: :コントローラー名`

```rb:例
redirect_to controller: :welcome
```




<br>
##4. コントローラー名とアクション名で指定
条件を複数つなげる場合は**カンマで繋ぐ**

`redirect_to controller: :コントローラー名, action: :アクション名`



```rb:例
redirect_to controller: :welcome, action: :index
```



<br>
##5. コントローラー名とアクション名とid名で指定
id番号を使って表示するページの場合は、id番号も合わせて指定する。

`redirect_to controller: :コントローラー名, action: :アクション名, id: id番号`



```rb:例
redirect_to controller: :articles, action: :show, id: article.id
```


<br>
##6. URLで指定
URLを直接指定する。相対パスでもOK。

`redirect_to "URL"`



```rb:例
redirect_to "https://railsdoc.com
```



<br>
##7. model名（クラス）で指定
model名を指定すると、そのmodelと対応するコントローラーのindexアクションのページに遷移する。

`redirect_to モデル名`



```rb:例
redirect_to Article
```


<br>
##8. パラメータで指定
DBから取得したデータを指定すると、そのコントローラーのshowアクションに該当するページに遷移する。

`redirect_to パラメータ`



```rb:例
@article = Article.new(article_params)
redirect_to @article

  private
    def article_params
      params.require(:article).permit(:title, :text)
    end
```



<br>
##9. メッセージを指定
オプションでnoticeを使うと、指定したテキストを遷移先ページに送ることができる。

viewページの`<% notice %>`とセットで使用する。

`redirect_to パス, notice: "テキスト"`

```rb:例
redirect_to articles_path, notice: "成功しました"
```

```erb:ビュー(.erb)
<%= notice %>
```



<br>
##10. ステータスを指定
ページに遷移した際に、ステータスを指定することができる。

`redirect_to パス, status: :シンボル`

＞[Railsドキュメント シンボル一覧](https://railsdoc.com/page/redirect_to)
git の .gitmodule で url を https で指定したときに怒られない方法

## .gitmodule

```
[submodule "submodules/hoge"]
        path = submodules/hoge
        url = https://github.com/[example.com]/hoge.git
```

## ~/.gitconfig

```
[url "ssh://git@github.com:"]
    insteadOf = https://github.com
```
温度センサーデータをS3へ

#温度センサーデータをオブジェクトストレージへ蓄積させたい。

前回まででセンサーデータを取得できた。
ラズパイ＋DHT22で時間と温度をひたすら書き出す。
https://qiita.com/qiitaroi/items/ac51ca2f636f422cced6

今度はこれを定期的に実行して、オブジェクトストレージと同期する。

#準備

１、センサーデータ取得
２、S3同期用スクリプト
３、crontab設定

---

１、
センサーデータ取得
$vi s3temp.py

```
s3temp.py
#!/usr/bin/python
import Adafruit_DHT
import datetime

sensor = Adafruit_DHT.DHT22
# connected to GPIO4.
pin = 4

date = datetime.datetime.now()
print(date)

humidity, temperature = Adafruit_DHT.read_retry(sensor,pin)
if humidity is not None and temperature is not None:
    print('Temp={0:0.1f}*C  Humidity={1:0.1f}%'.format(temperature, humidity))
else:
    print('Failed to get reading. Try again!')
```

それを実行して/data/tmp.logに追記していく。
pythonでそのまま書き出せばいいのかもしれないけど実行ファイルは全部シェルスクリプトが良いので。
$vi temp.sh

```
#bin/sh
cd ~/Adafruit_Python_DHT/examples
python3 s3temp.py >> ~/data/temp.log
```

---
２、
S3へ同期するスクリプト　（と言うほどの物でもない。）
今回の温度データ以外にもパケットキャプチャデータとかも同期するのでdata/*にしています。
$vi s3sync.sh

```

#bin/sh
s3cmd sync data/* s3://testbucket
```
---
3,
crontabに追記
1分おきに温度データを測定し
1時間おきにS3と同期する

```
$crontab -e 
*/1 * * * * ~/temp.sh
* */1 * * * ~/s3sync.sh
```

#結果
無事AWSのサイトからもファイルを確認できました。
![aws2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/a1c73a2b-8e07-56ad-34f2-48eb7fc60dcb.png)
AWS LambdaのqueryStringParametersとmultiValueQueryStringParametersの違いについて


## 環境
Python3.7
プロキシ統合あり

## queryStringParametersを使う
API GatewayからLambdaに渡されたペイロードからパラメータを取得できます。


リクエスト
https://XXXX/XXXX/XXXX?id=1&value=foo

```python

response = event.get('queryStringParameters')

return {
    'statusCode': 200,
    'body': json.dumps(response)
}
```

結果

```json
{
    "id": "1"
    "value": "foo"
}
```

パラメータ名で値を取得できます。

リクエスト
https://XXXX/XXXX/XXXX?id=1&value=foo

```python

response = event.get('queryStringParameters').get('value')

return {
    'statusCode': 200,
    'body': json.dumps(response)
}
```

結果

```json
"foo"
```

指定したパラメータ名が存在しなければNoneとなります。


## multiValueQueryStringParametersを使う
こちらもパラメータを取得することができますが、
同じパラメータ名が複数(array)ある場合に使用します。

リクエスト
https://XXXX/XXXX/XXXX?id=1&value=foo&value=bar&value=baz


```python

response = event["multiValueQueryStringParameters"].get("value")

return {
    'statusCode': 200,
    'body': json.dumps(response)
}
```

結果

```json
{
    "id": [
        "1"
    ],
    "value": [
        "foo",
        "bar",
        "baz"
    ]
}
```


気をつけなければいけないのが、
存在しないパラメータ名を指定した時に、
そのまま配列の中身まで取得しようとするとエラーとなります。


リクエスト
https://XXXX/XXXX/XXXX?id=1

これは大丈夫(Noneになる)

```python

response = event["multiValueQueryStringParameters"].get("value")

return {
    'statusCode': 200,
    'body': json.dumps(response)
}
```

下記はエラー
こういう取り方はやめましょう。


```python
response = event["multiValueQueryStringParameters"].get("value")[0]

return {
    'statusCode': 200,
    'body': json.dumps(response)
}
```


### 同じパラメータ名が複数(array)のものをqueryStringParametersで取得する場合

リクエスト
https://XXXX/XXXX/XXXX?id=1&value=foo&value=bar&value=baz

```python

response = event.get('queryStringParameters')

return {
    'statusCode': 200,
    'body': json.dumps(response)
}
```

結果

```json
{
    "id": "1"
    "value": "baz"
}
```

最後の値で上書きされて、bazが取得されます。

## まとめ
渡されるパラメータによって用途にあった取り方をしましょう。
phpでauカブコム証券のkabuステーションAPIをたたく！

トークン取得のところまで作成。

パスワードをpostするのだけど、JSONで送るのがミソ。ここを普通にクエリパラメータで送ると4001005パラメータ変換エラーになるので注意。


```php
        $url = "http://localhost:18081/kabusapi/token";
        $data = ['APIPassword' => 'mypass'];
        $opts = [
            'http' => [
                'method' => "POST",
                'header'=> "Content-type: application/json\r\n" . "Accept: application/json\r\n",
                'content' => json_encode($data),
                'ignore_errors' => true,
                'protocol_version' => '1.1'
            ]
        ];
        $context = stream_context_create($opts);
        $json = file_get_contents($url, false, $context);
        if (isset($http_response_header)) {
            $pos = strpos($http_response_header[0], '200');
            if ($pos === false) {
                // エラー処理
                exit;
            }
        }
        if (!$json) {
            // エラー処理
            exit;
        }

        $response = json_decode($json, true);
        if ($response['ResultCode'] === 0) {
            $apikey = $response['Token'];
        } else {
            // エラー処理
            exit;
        }

```

API銘柄登録全解除。

Content-Length: 0　を送るのがミソ。

API銘柄が一件も登録されていない状態で実行すると確かエラーになった。

portが18080だと本番だが、確か、検証環境だとそもそも銘柄登録できないんじゃないかな。

```php
        $url = "http://localhost:18080/kabusapi/unregister/all";
        $opts = [
            'http' => [
                'method' => "PUT",
                'header'=> "Content-type: application/json\r\nContent-Length: 0\r\n"
                . "X-API-KEY: " . $apikey ,
                'ignore_errors' => true,
                'protocol_version' => '1.1'
            ]
        ];
        $context = stream_context_create($opts);
        $json = file_get_contents($url, false, $context);
        if (isset($http_response_header)) {
            $pos = strpos($http_response_header[0], '200');
            if ($pos === false) {
                // エラー処理
            }
        }
        if (!$json) {
                // エラー処理
        }

        $response = json_decode($json, true);

```
FlutterのAndroidアプリを開発するときの備忘録

Androidアプリを開発したくて、Flutterを勉強中です。
VSCodeを使って開発しているのですが、
毎回、ビルドして、実機にインストールするときの作業手順を忘れてしまうので、
自分向けの備忘録としてまとめます。

# ビルド  
```
flutter build apk --split-per-abi
```  


# 実機インストール
```
adb -d install -r build/app/outputs/apk/release/app-arm64-v8a-release.apk
```
【Heroku】で出たエラー：was loaded over HTTPS, but requested an insecure stylesheet

###Herokuにデプロイしたアプリの最初の画面でCSSが適用されない

`was loaded over HTTPS, but requested an insecure stylesheet`のようなエラ〜メッセージがコンソールに表示されていました。

HTTPSで読み込まれていて、安全でないCSSを読み込まれようとしてて危険が危ない、みたいなところかと思います。

https://laravel.com/docs/6.x/requests#configuring-trusted-proxies

```php5:app/Http/Middleware/TrustProxies.php
<?php

namespace App\Http\Middleware;

use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var string|array
     */
    protected $proxies = [
        '192.168.1.1', // これと
        '192.168.1.2', // これを追記するというような内容
    ];

    /**
     * The headers that should be used to detect proxies.
     *
     * @var string
     */
    protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
```
あるいは

```php5:app/Http/Middleware/TrustProxies.php
// $proxiesの部分は＊で渡してもいいらしい
    protected $proxies = '*';
```


###とりあえず$proxies = '*'にしたら解決しました

英語の説明でよくわからなかった、というのは言い訳で、多分日本語で説明が書いてあってもわからない。

しかし
>
 you may notice your application sometimes does not generate HTTPS links. 

という記述から、CSSなどのリンクを生成するときにHTTP：〜みたいな感じになると、HTTPSじゃないとあかんでってことでCSSが読み込めないのかなと。

HTTPSで読み込んだらHTTPSのリンクしか読み込めへんよってことですかね。

ということで、

```
$proxies = '*';
```

とすることでCSSが読み込めるようになりました。
Node.jsでGoogle Drive上のファイルをコピーする (Google Drive API v3)


Google Drive上でのファイルコピーを試します。

* 参考記事
	* [Node.jsでGoogle Drive上のファイルを削除する (Google Drive API v3)](https://qiita.com/n0bisuke/items/a1b39635029242f31713)
	* [Node.jsでGoogle Drive上のファイルをリネームする (Google Drive API v3)](https://qiita.com/n0bisuke/items/dcc7be337a555b018b19)
	* [Node.jsでGoogle Drive上のファイルを指定フォルダに移動する (Google Drive API v3)](https://qiita.com/n0bisuke/items/8f108408a9e1067b9225)
	* [Node.jsでGoogle Drive上のファイルを複製（copy）する (Google Drive API v3)](https://qiita.com/n0bisuke/items/6d73bb6e1af123db9a9b)
	* [Node.jsでGoogle Driveの指定フォルダからファイル一覧を取得メモ (Google Drive API v3)](https://qiita.com/n0bisuke/items/ff1479cd14e7a0c0be0c)
	* [Node.jsでGoogle Drive上のファイルをダウンロードする (Google Drive API v3)](https://qiita.com/n0bisuke/items/61e037deb1926df5427c)
	* [Node.jsでGoogle Driveにファイルをアップロードする (Google Drive API v3)](https://qiita.com/n0bisuke/items/776c92bc7d975df3b50a)

メソッドは[Files: copy](https://developers.google.com/drive/api/v3/reference/files/copy)になります。

ライブラリの書き方だと`drive.files.copy()`です。

## スコープ指定

```
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.file
https://www.googleapis.com/auth/drive.appdata
https://www.googleapis.com/auth/drive.photos.readonly
```

## Google Drive上のファイルのコピー

[チュートリアル](https://developers.google.com/drive/api/v3/quickstart/nodejs)の`function listFiles`の箇所を書き換えて利用してみます。

> 機能的には`function copyFile`とかにリネームした方が良いでしょうが一旦動かす体なのでスルー

`folderId`にGoogle Driveのアップロード先のフォルダのIDを指定しましょう。

```copy.js
//省略

async function listFiles(auth) {
  const drive = google.drive({version: 'v3', auth});
  const params = {
  	fileId: `xxxxxxxxxxx` //ここにコピーしたいファイルのIDを指定
  }; 

  try {
      const res = await drive.files.copy(params);
      console.log(res.data);
  } catch (error) {
      return error;   
  }
};
```

実行すると指定したファイルがGoogle Driveのフォルダ同じフォルダ上でコピーされます。

## 別のフォルダにコピー

`drive.files.copy()`をパッとみた感じフォルダのparents指定ができそうでした。

> 参考: https://github.com/googleapis/google-api-nodejs-client/blob/master/src/apis/drive/v3.ts#L4136-L4189

```js
//省略

  const params = {
    fileId: `xxxxxxxxxxx`, //ここにコピーしたいファイルのIDを指定
    requestBody: {
      parents: [`xxxxxxxxxxx`] //ここにコピー先のフォルダIDを指定
    }
  };
 
//省略
```

これで元々のフォルダにファイルを残しつつ、別のファイルとして別のフォルダにファイルをコピーすることができます。

## よもやま

`.update()`で複数ペアレントを指定したり、ペアレントを削除したりすることでファイルの移動ができますが、この場合はコピーではなく同じIDのファイルを複数フォルダから参照している状態になります。

今回の`.copy()`は全く別のファイルを作成する形です。
IDが異なるものができるので扱う際には違いの注意をしましょう。
VisualBoxが起動しない「VirtualBoxClient COMオブジェクトの作成に失敗しました」

VisualBoxが起動しない

エラー「VirtualBoxClient COMオブジェクトの作成に失敗しました。 アプリケーションを終了します」が出て起動しない

何故か管理者権限で1度起動したら以降使えるようになりました。なぜ・・・？
https://blogger.zatsuroku.net/2018/05/virtualboxclient-com-rc.html
こんな方もいらっしゃったので、もしかしたらまた起動しなくなるかもしれないです。
WSL上にドライブをマウントする

# はじめに

DropboxだったりpCloudだったりWSL側からも使いたいよね！

- Linux側にクライアントは要らない。
- Windows側にクライアントをインストールして使えるようにしておく。

# 呪文

- WSLのデフォルトユーザ(uid=1000, gid=1000)でマウント
- Windows側ではP:
- マウント先は/mnt/p
  - 先に/mnt/pという空ディレクトリ作っておくこと

```bash
$ sudo mount -t drvfs -o noatime,uid=1000,gid=1000 p: /mnt/p
```
Windows Subsystem Linux 2 の導入

# はじめに
長らくUbuntuとDebianを使ってきたが機器の更新のたびにWindowsを駆逐して入れなおすのが億劫になった。  
VirtualMachineを持って歩くのも面倒だし…WSLでよかろう。

# env
- Windows 10 Home

# 手順
## BIOSの設定
CPUの”Virtualization”機能をEnableにしておくべし

- WSL1はdisableでもOK
- WSL2はEnableする必要あり

## Windows 10 May 2020 update を適用
https://www.microsoft.com/en-us/software-download/windows10

しめやかにアップデート実施。

## Windows側の設定
- 設定>アプリと機能>オプション機能>Windowsのその他の機能
  - ”Linux用Windowsサブシステム”にチェック
  - ”Hyper-V”にチェック
  - ”仮想マシンプラットフォーム”にチェック
- 再起動される
- Windows PowerShell(管理者)で設定
  - https://docs.microsoft.com/en-us/windows/wsl/install-win10

```powershell
> dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
> wsl --set-default-version 2
```

ここで

```powershell
WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。詳細については https://aka.ms/wsl2kernel を参照してください
```
と言われたら https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel からカーネル更新プログラムパッケージをインストールする

## ディストリビューションをインストール
- Microsoft Storeを起動
  - ”WSL”で検索するといくつか出てくる
  - ここでは”Ubuntu 20.04 LTS”を選択してインストール

## 初回起動
インストールしたディストリビューションを起動する。  
しばらく待たされたあと、 デフォルトユーザとそのパスワードを入力するとめでたくログインする。  
逸る気持ちを抑えて一度exit。

## Windows PowerShellでWSLのバージョンを確認
```powershell
> wsl -l -v
```

2になっていなければ

```powershell
> wsl --set-version Ubuntu-20.04 2
```

## Windows Terminalを導入
WSLだけだと端末1つで使いにくいので端末アプリをいれておく。  
(GNU screenやtmuxを使いこなしてるならいらないかもしれないが…)

- Microsoft Store を起動
  - ”Terminal”を検索すると出てくるのでインストール
- Windows Terminalを起動
  - 設定を開いてデフォルトを”Ubuntu 20.04”に変更する
    - UUIDで指定するが、そのUUIDは設定ファイルの下のほうにある

```powershell
    //"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", ← デフォルトのPowerShellのUUID、コメントアウト
    "defaultProfile": "{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}", ← UbuntuのUUID
```

# どうなった？
- Windows Terminalを起動するだけでUbuntuにログインしたところから始まる
  - telnetやsshでログインした状態に等しい
  - ”＋”ボタンで増やせるので楽
- WSLを直接起動する必要はない(ここ重要)

あとはX Window SystemのないUbuntuと思えばよろし。
Windowsフォーム　コンボボックスのSelectIndexの不思議な動き

以下のような単純なコンボボックスで、「千葉」を選び・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249926/8d0cce8e-8e4c-1667-e42a-a1ba9722390b.png)

閉じて・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249926/94b1da4c-dd5a-f60c-f081-8447ee6b0e02.png)

▼を押して開くと・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249926/0e095974-301e-aa1f-eb62-36578aa2fd36.png)

なぜか、「千葉県」が選択されています。
「千葉」を内包するアイテムが「千葉」より前にある場合（この場合
「千葉県」「千葉市」）に、そのアイテムが選択されてしまうようです。

しかし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249926/8a069b0d-f9ef-445c-e12b-1ba2c8f6fee1.png)
「真一千葉」は選択されません。

このことから「千葉」を前方一致で内包するアイテムが選択されてしまうということがわかります。

.NET 4.8 系で検証しました。

```
Public Class test
    Private Sub ComboBox1_DropDown(sender As Object, e As EventArgs) Handles ComboBox1.DropDown
        Console.WriteLine("DropDown " & ComboBox1.SelectedIndex)
    End Sub

    Private Sub ComboBox1_DropDownClosed(sender As Object, e As EventArgs) Handles ComboBox1.DropDownClosed
        Console.WriteLine("DropDownClosed " & ComboBox1.SelectedIndex)
    End Sub

    Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
        Console.WriteLine("SelectionChangeCommitted " & ComboBox1.SelectedIndex)
    End Sub
End Class
```

前述した動作をすると、コンソールには

```
SelectionChangeCommitted 7 // 千葉
DropDownClosed 7
DropDown 7
DropDownClosed 3 // 千葉県
```

と出力されます
Docker のマルチステージビルド (Multi Stage Build) で Symbolic Link を使う

Dockerはサイズを小さくするために、builderと実際使うイメージでステージを分けて書くマルチステージビルド(multi-stage builds)がよく使われています。このマルチステージビルドを使う時、builderでライブラリをインストールし、実際使うイメージにライブラリをADDやCOPYで追加して使いたい場合があります。

ライブラリにはSymbolic Linkがよく含まれるのですが、DockerのADDやCOPYコマンドはSymbolic Linkを追加することは出来ません。

この問題は、builderで必要なSymbolic Linkをtarで固め、次のステージでtarファイルを展開することで意外と簡単に解決できます。

実際のDockerfileの例で詳しく見てみましょう。

### Dockerfileの例と解説

```dockerfile

FROM debian:latest as builder
RUN tar czf testlib.tar.gz /usr/local/lib/test.so.* \  
            /usr/local/lib/test1.so.* \
            /usr/local/lib/test2.so.* # 必要なSymbolic Linkをtarにする

FROM debian:latest
COPY --from=builder /testlib.tar.gz /testlib.tar.gz  # 固めたtarファイルをコピー
RUN cd / && tar xzf testlib.tar.gz # 固めたSymbolic Linkを展開
```

この方法を知るまでADDやCOPYでSymbolic Linkを追加しようと苦労したことが夢のようです。


#### 参考
- [香川研究室でのDockerの使い方: シンボリックリンクに関する Tips] (http://guppy.eng.kagawa-u.ac.jp/Seminar/docker.html)
- [How to make a symlinked folder appear as a normal folder](https://superuser.com/questions/842642/how-to-make-a-symlinked-folder-appear-as-a-normal-folder)
typescriptメモ

typescriptを学ぶにあたって事前知識を調べてきたのでメモ代わりに残しておきます。

---

## typescriptとは

---

マイクロソフト社が開発したjavascriptを拡張して作られた静的型付け言語です。

---

### 静的型付けとは？

---

typescriptは静的型付け言語と言われていますが、javascriptは動的型付け言語と言われています。
動的型付けと静的型付けとは、何が違うのかというと

---

動的型付けとはプログラム実行時に変数や関数に勝手(いい感じ)に型を当てはめてくれることをいい、

---

静的型付けとは実装者が予め、変数や関数に型を指定することをいいます。

---

## typescriptの動き

---

typescriptはブラウザで実行するときtypescriptで書いたものをjavascriptに変換して実行されます。

---

## なぜJavaScriptに型を追加する必要があるのか？

---

型はコードの品質や読みやすさを保証してくれます。
大規模なプロジェクトになった時や、新しく入ってくる人たちにとってもメリットがあります。

---

### メリット

---

#### 型があるから開発スピードが早い,リファクタが早い

---

型があるとエラーが確認できるのと、その変数、関数にどの型が入るかがわかるので開発スピードが上がります。

---

#### 型を利用するかどうかは任意

---

typescriptを導入したからといって型を絶対使わなくてはいけないということはない。
型を利用するかどうかは任意なので.jsのファイルを.tsに書き換えてコンパイルしても有効な.jsファイルを出力します。

---

なので既存のjavascriptをtypescriptに載せ替える時なども一気にtypescript用に書き換えず、少しずつ対応していくことも可能。

---

## 型推論

---

typescriptには型推論というものがあります。
typescriptを調べていると型推論というワードをよく聞くのですが、型推論とは
typescriptがソースコードを解析し、コードの流れから変数や関数がどの型なのかを推測してくれる仕組みのことみたいです。

---

### 例

---

```ts
var sample = 123;
sample = 'ハロー'; //エラーstringをnumberに代入できません
```

---

これは最初に変数sampleを宣言したときにnumber型で値を代入しているのに対して
2行目でstring型を代入しているため型が違うよと怒られています。

---

ちなみに型推論でエラーは吐かれますが、typescriptのコンパイルでは型チェックエラーが起きても有効なjavascriptが出力されます。

---

##  型指定

---

型推論の結果が正しくない場合や正確でない場合は明示的に型指定することで
コンパイラが理解するのを助けたり、他の開発者のドキュメント代わりになったりとメリットがあります。

typescriptでは以下のように型指定ができます。

---

```ts
var sample: number = 123;

// 型が一致しない場合はエラーになります。
var sample: number = 'ハロー'; // エラー
```

---

## まとめ

---

こんな感じでtypescriptのメリットが伝わった?かと思います。
まだ自分もtypescriptにガッツリ触れていないので今後も引き続き触っていきたいと思います。
簡単に Mac mini に ssh 接続する方法

MacBook から Mac mini に ssh 接続できるようにする方法は、思ったよりも簡単でした。

というか、基本的には Mac mini の「 システム環境設定 ＞ 共有 」で「 リモートログイン 」を「 オン 」にするだけです。
![スクリーンショット_2020-08-27_12_18_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109175/9515f55e-d4cc-9c4b-621f-5187dd4dde0d.png)
これで、Mac mini の「 ユーザー名 」と「 IP アドレス 」で、例えば、次のように MacBook から接続できます。

```
% ssh username@192.168.100.100
```

ただ、毎回、これを打って、パスワードを入力するのは面倒ですし、RSA 公開鍵認証も設定しておきましょう。

まず、MacBook 側で、鍵を作成します。

```
% cd ~/.ssh
% ssh-keygen -b 4096 -f mini
```

この場合、生成された `mini.pub` というファイル（ 公開鍵 ）を、次のようにして Mac mini に配置すればいいのですが、

```
% scp mini.pub username@192.168.100.100:~/.ssh
```

まだ、Mac mini には .ssh ディレクトリすらない、という場合は、いったん ssh 接続して `mkdir ~/.ssh` しておきましょう。

公開鍵を Mac mini に配置できたら、もう一度、普通に ssh 接続して、次のようなコマンドを実行します。

```
% cd ~/.ssh
% touch authorized_keys
% cat mini.pub >> authorized_keys
```

これで、Mac mini 側の設定は、一応、終了です。

最後に、MacBook 上の `~/.ssh/config` を、例えば、以下のように、編集（ 追記 ）しましょう。

```~/.ssh/config
Host mini
HostName 192.168.100.100
User username
IdentityFile ~/.ssh/mini
```

これで、簡単に ssh 接続できるようになりました。

```
% ssh mini
```

もちろん、セキュリティに関しては、自己責任で。

ちなみに、同一ネットワークにおける Mac 同士の ssh 接続は、ちょっと例外的かもしれないので、通常の場合は「 [RSA 公開鍵認証による SSH 接続でエラーが出る場合の対処法](https://qiita.com/normalsalt/items/67c1cae55d16ca449122) 」なども参考にしてみてください。
🔰【C#】基本的なプログラム(解答1-3)

## この記事の注意事項
この記事に記載の内容(解答)が模範解答というわけではありません。
あくまで自身の学習の過程での足跡的な内容で記載するものです。
そのため、記述が汚い箇所もあるかと思いますので悪しからず。

## 開発環境
OS:Windows10 Pro 64bit
IDE:VisualStudio Community 2015

---
###問題
以下のプログラムは、「こんにちは」という文字列を表示するプログラムである。ただし、このプログラムには、間違いがある。間違いを修正し、期待される実行結果が得られるように、プログラムを修正しなさい。

```C#:Pro1_3
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Problem1_3
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WritLine("こんにちは");
        }
    }
}
```
```:コンソール
こんにちは
```
###解答
```C#:Ex1_3/Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ex1_3
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("こんにちは");
        }
    }
}
```

```:コンソール
こんにちは
続行するには何かキーを押してください . . .
```
## 参考記事
[1週間で身につくC#言語の基本](https://csharp.sevendays-study.com/index.html)
gatsby.jsのブログにGoogleアドセンス広告を貼る方法

### headにコードを埋め込む

アドセンスに申請するとheadタグ内にコードを貼るように指示される。

![スクリーンショット 2020-08-27 13.27.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558877/d131c7ec-8ebb-6df2-a35c-e561269fd914.png)

他にも方法はあるみたいだけれど、うまくいかなくて最終的にプラグインを選択している人が多かったので、今回は`gatsby-plugin-google-adsense`というプラグインをインストールしてheadタグ内にコードを貼ってもらう。

```
$ yarn add gatsby-plugin-google-adsense
```

gatsby-config.jsに以下のコードを追加

```gatsby-config.js
plugins: [
  // 省略
  {
    resolve: `gatsby-plugin-google-adsense`,
    options: {
      publisherId: process.env.GOOGLE_ADSENSE_ID,
    },
  },
```

GoogleAdSenseに審査を申請する。

![スクリーンショット 2020-08-27 13.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558877/170c1971-5d7d-dfb7-b405-ab55a87e1a0b.png)

ところがコロナの関係で、、、と7月の後半くらいから５回位申請したが、すべて審査に落ちてしまっていたが、8月後半になってようやく審査に通りました。

![スクリーンショット 2020-08-27 13.24.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558877/ce4dd1f8-17a2-89da-5b6a-1e1a99a84f9f.png)

### ads.txtファイルをアップロード

やっと広告を貼れると思いきや、以下のようなメッセージが。

![スクリーンショット 2020-08-24 21.06.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558877/95ed8010-7f1e-7a3b-8957-b5d7b4a59363.png)

gatsbyプロジェクトのルート直下にstaticフォルダを作成して`ads.txt`を設置。buildしてアップロードします。

![スクリーンショット 2020-08-27 13.37.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558877/c01b9aef-6139-3d3c-809e-50b69a21b4e6.png)

エラーが解消されるまで待ちましょう。解消までに数日かかるみたいです。ちなみに自分は2日くらいで解消されました。

### 広告を貼る

やっと広告を貼れます。

アドセンス広告をreactに対応させる為に`react-adsense`プラグインをインストールします。

```
$ yarn add react-adsense
```

`.cache`フォルダにある`default-html.js`を`src/html.js`にコピーします。

```
$ cp .cache/default-html.js src/html.js
```

`html.js`のhead内にscriptを追加

```html.js
import React from 'react'
import PropTypes from 'prop-types'

export default function HTML(props) {
  return (
    <html {...props.htmlAttributes}>
      <head>
        <meta charSet="utf-8" />
        <meta httpEquiv="x-ua-compatible" content="ie=edge" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />

        {/* GoogleアドセンスのJSを読み込む */}
        <script
          async
          src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
        ></script>

        {props.headComponents}
      </head>
```

広告のコンポーネントを作成します。。

```src/components/adsense.js
import React from 'react'
import AdSense from 'react-adsense'

const Ad = () => (
  <div className="ad">
    <AdSense.Google
      client={process.env.GOOGLE_ADSENSE_ID}
      slot=""
      style={{ display: 'block' }}
      responsive="true"
      format="auto"
    />
  </div>
)

export default Ad

```

あとは広告を表示したい場所にAdタグを貼り付けて、build後アップロードすれば完成！

貼った後すぐはアドセンスのスクリプトが403エラーになってしまっていて何も表示されなかったのですが、少し経ったら表示されるようになりました。
～memo～ Rspecでraise_errorのメッセージをテストする

raise_errorをした後のメッセージが正しいことを検査したかったのですが、色々探してやっとやり方が見つかったので忘れないようにメモします。

```ruby
example "RecordInvalidが発生し、エラーメッセージが正しくセットされる" do
  expect { service }.to(raise_error { |e|
    expect(e.error_message).to(eq("hogehoge_error"))
  })
end
```

ブロック取って中で比較できるとは全然知りませんでした・・・

＜追記＞

```ruby 
example "RecordInvalidが発生し、エラーメッセージが正しくセットされる" do
  expect { service }.to(raise_error(RecordInvalid) { |e|
    expect(e.error_message).to(eq("hogehoge_error"))
  })
end
```

として、Errorクラスも一緒に確認することも可能でした！
🔰【C#】基本的なプログラム(解答1-2)

## この記事の注意事項
この記事に記載の内容(解答)が模範解答というわけではありません。
あくまで自身の学習の過程での足跡的な内容で記載するものです。
そのため、記述が汚い箇所もあるかと思いますので悪しからず。

## 開発環境
OS:Windows10 Pro 64bit
IDE:VisualStudio Community 2015

---
###問題
以下のプログラムを変更し、実行結果は同じでも、処理が一行しかないような形にプログラムを変更しなさい。

```C#:Pro1_2/Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Problem1_2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("123");
            Console.Write("456");
            Console.WriteLine("789");
        }
    }
}
```
```:コンソール
123456789
```
###解答
```C#:Ex1_2/Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ex1_2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("123456789");
        }
    }
}
```
```:コンソール
123456789
続行するには何かキーを押してください . . .
```
---
## 参考記事
[1週間で身につくC#言語の基本](https://csharp.sevendays-study.com/index.html)
[自分用]npm -gしたくないとき


例えばvue-cliをプロジェクト単位で入れたいとする。


`npm i --save-dev vue-cli`

でインストールしちゃう

入れたモジュールのパスは
`node_modules/.bin`
に叩けるコマンド名でファイルが入ってます。
これを
`$(npm bin)`
こうも書けます。

コマンドが使えるように、package.jsonのscriptsの部分を編集します。

```package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "vue": "$(npm bin)/vue -V",
    "contentful": "$(npm bin)/contentful"
  },
```


scriptsは
`npm run`
で走らせることができます。

上のpackage.jsonの記述で`npm run vue`をすると
vue-cliのバージョンが返ってきます。



`"create": "$(npm bin)/vue init nuxt/starter ."`

してカレントディレクトリにnuxtインストールしたら
書いてたscripts全部消えた泣くTT
追記した。
こうやってプロジェクト作っていくんかな
🔰【C#】基本的なプログラム(解答1-1)

## この記事の注意事項
この記事に記載の内容(解答)が模範解答というわけではありません。
あくまで自身の学習の過程での足跡的な内容で記載するものです。
そのため、記述が汚い箇所もあるかと思いますので悪しからず。

## 開発環境
OS:Windows10 Pro 64bit
IDE:VisualStudio Community 2015

---
###問題
Console.WriteLine()を用いて、自分の名前を表示するプログラムを作りなさい。
###解答
```C#:Ex1_1/Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ex1_1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("山田太郎");
        }
    }
}

```
```:コンソール
山田太郎
続行するには何かキーを押してください . . .
```
---
## 参考記事
[1週間で身につくC#言語の基本](https://csharp.sevendays-study.com/index.html)
Pythonで日付のタイムゾーン（時差）を変換（文字列から）

思いがけずどツボにハマったので忘備録です。もっと楽なのありそうですがいったんこれで。

やりたいこと→文字列の日付（標準時間）を日本時間に直したい

```python
#importするのはこれだけでOK
import datetime

#元の日付（標準時間）
hiduke = '25/Aug/2020 11:01:52'

#1. 日付型に変換
hiduke = datetime.datetime.strptime(hiduke, '%d/%b/%Y %H:%M:%S')

#2. タイムゾーンの情報を付与（ここではUTC）
hiduke = hiduke.replace(tzinfo=datetime.timezone.utc)

#3. タイムゾーンを日本時間に変換
（+9時間）
hiduke = hiduke.astimezone(datetime.timezone(datetime.timedelta(hours=+9)))

#4. タイムゾーン表記を消去
hiduke = hiduke.replace(tzinfo=None)

```

# 1.日付型に変換
- strrptime = String (to be) Replace(ed by) Time をつなげたものかと思われます。
- 引数には、変換したい日付（文字列）、およびその日付がどんな表記で書かれているのかを明記します。
- %d = 日
- %b = 月(Aug）。月の名前の省略形。なお、数字の月の場合は %m, Augustの場合は %B
- %Y = 年
- 2020-08-26　であれば、 `%Y-%m-%d`と表記。
- 表記一覧はこちらに載っています。 
[Pythonのdatetimeで日付や時間と文字列を変換（strftime, strptime）](https://note.nkmk.me/python-datetime-usage/)

#2. タイムゾーンの情報を付与（ここではUTC）
tzinfo = timezone info.

#3. タイムゾーンを日本時間に
日本時間は標準時間+9時間のため。 `hours=+9` となります。実際の表記は `datetime.timedelta(hours=+9)`

#4. タイムゾーン表記を消去
③のままだと日付の後ろに `+09:00`　（タイムゾーン表記）がくっついてしまうので、`tzinfo=None`にすることで消すことができます。
これで、 `25/Aug/2020 11:01:52`　が `2020-08-25 20:01:52` となります。


####参考
[Python, datetime, pytzでタイムゾーンを設定・取得・変換・削除](https://note.nkmk.me/python-datetime-pytz-timezone/)

[Pythonで文字列 <-> 日付(date, datetime) の変換](https://qiita.com/shibainurou/items/0b0f8b0233c45fc163cd)
プログラミング初心者に気をつけなければならないことまとめ

いきなりひっかけのようで大変申し訳ありませんが，この記事は，プログラミング初心者**が**気をつけなければならないことまとめ，**ではありません**．プログラミングに長年携わってきた人々が，プログラミングを学び始めたという方，あるいは，プログラミングに関心があって学びたいという方に接する際に気をつけなければならないことのまとめ，です．

個人的な経験に基づくケースバイケースのようなものであるため，どれだけお役に立てるかわかりませんが，参考程度に見ていただけますと幸いです．なお，プログラミング初心者御本人が読まれてももちろん構いませんが，もしかしますと，**プログラミング学習をやめたくなる**かもしれません．御了解いただけますと幸いです．

#（１）最初に，コンピュータハードウェアが『プログラムに沿って動く機械』であることを把握しているかを確認した方が良い

まず，世の中の圧倒多数の人々は，**プログラムの存在を知りません**．ソフトウェア（『アプリ』や『ソフト』と呼称されるもの）にしても，画像データとか，数値データとか，表示テキストとか，マニュアルとか，そういった素のデータの集まり程度の認識しかありません．

それ以外の，コンピュータならではの機能は全て，電気回路，電子回路などの物理的な部品を直接構成して出来上がっている，すなわち，実際にはプログラムで実現されているはずの機能のほとんどが，最初からコンピュータ（ハードウェア）という機械に回路として組み込まれていると捉えている…というか，信じています．

その場合，プログラムという言葉をどのように捉えているかといえば，多くの場合，**設定情報の一種**という認識です．ある意味間違いではないのですが，『デスクトップ環境くらいはメモリやディスクにプログラム（という名の設定情報）が全くなくても電源さえ入れれば動く』と思い込んでいると考えてほぼ間違いはないほどです．

そして，プログラミングを学び始めたという人は，そのような人々の延長である可能性が高いという状況です．『GUIの部品だってプログラムでできているんだよ』と生コードを見せて実際に動かしてみせると，**腰を抜かすほど驚きます**．プログラムやソフトウェアによっていろんなことができるのがコンピュータなのに，今まで気づかなかったの？と聞けば，『コンピュータに詳しくなかったし』という反応がほとんどです．

#（２）（追記）
すみません，（１）でほぼ語りました．もし実際に（１）のような状況であれば，そのままでは問題ですので，あらためてコンピュータの原理の概要を説明するなり，引き続き他の生コードで実演するなりして『誤解を解く』必要があります．

そして，当方の経験上，その辺の誤解を解くと，多くのプログラミング初心者は**プログラミングの学習意欲を失います**．なぜかといえば，プログラミングを学びたかった理由のほとんどが，有用なWebサービスを構築したいとか，実用的なデータ分析を行いたいとか，面白いゲームソフトを作りたいとか，そういったことを行うための**設定方法**を知りたかっただけだからです．

なお，誤解を解かないままでいると，プログラミング学習を進めていくうちに『いや，知りたいのはアルゴリズムとかクラス定義とか内包表記とかラムダ計算とかじゃない，もっとすぐに役に立つ具体的な技術（といってもtechnologyの方ではなく，techniqueの方の意）なんだ！』となって途中で基礎学習をやめ，ライブラリの活用方法に走り，サンプルコードをよくわからないまま修正して実行を確認することを繰り返し，そしてたまたま動くようになったものをローンチしてしまうという，**プログラミング初心者のままのプロのプログラマ**が誕生してしまうかもしれません．ああ，恐ろしい…．

#備考

##記事に関する補足
* 大げさに聞こえる内容かもしれませんが，当方の立場上，毎年悩んでいる事柄だったりします．『誤解を解く』ことが必ずしもうまくいくとは限らず，初心者と自称プロのプログラマからの『理屈こねてないで役に立つギジュツをさっさと教えろ！』というプレッシャーは常にあり…．プログラミングは理屈の塊というか理屈そのものなんだよー，よー．

##更新履歴
* 2020-08-27：初版公開