OmniAICreator/Qiita-1.07M huggingface dataset:
【AR】Vuforia Studioで作った画面を少し飾り付けたい

いつもお世話になっております。
先日、Vuforia Studioを使ってビューア（Vuforia View）で表示するARエクスペリエンスを作成する機会を頂きました。
試してみるといろいろとできたので、今後のヒントになればと思いメモを残します。

# はじめに
使った環境は以下です。

 - Vuforia Studio : Version 8.4.7 (8.4.7.4459)
 - Vuforia View :  Version 8.4.60(1729)
 - iPad Pro (10.5 inch)

# わかったこと
Vuforia StudioのMobile向けのARコンテンツではIonic framework 1.3.3の機能を使って装飾を変更できました。
例えば、ボタンのTextを文字ではなくアイコンで表現したいといった場合は、Ionicons CheatsheetにあるClassnameをClassに記述するだけでOKでした。

1. **Vuforia Studio標準のボタンを配置した状態**
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449477/487cbffa-731a-51e0-20ee-333b0297d6bc.jpeg)
※デフォルトのボタンをそのまま使うとこんな感じです。

2. **文字の代わりにIonicのアイコンを使う**
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449477/87f1fbc7-56a5-8ddb-766b-2695383a7cac.jpeg)
※*ion-beer*を追加することでジョッキが表示され、*iconBtn*ではフォントサイズを指定してます。

3. **Ionicでボタンの色や表現を装飾する**
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449477/12c8c771-268c-1d8b-2480-74b4c0c94a45.jpeg)
※ビールは黒よりラガーが好きな人もいるので色も変えてみます。
　ここではIonicで用意されている*button-energized*で色を、*button-outline*でアウトライン型のボタンスタイルを適用しました。

# まとめ
色とかならCSSを自分で書いても変更できますが、Ionicで定義されている内容をClassに指定するだけで変更できるなら楽です。
後述のリンクからIonic frameworkのCSS Componentsを参照すると、利用できるサンプルが詳しく説明されているのでわかりやすいです。

準備されているアイコンに気に入るものがない場合、*Image Widget*を使ってアイコン画像を指定するという手もあります。
その場合は以下のを*STYLES > Application*に記述し、*Image Widget*のClassにimgButtonを記述すればボタンのような動きをつけることができます。

>/* 画像をホバーした */'
.imgButton:hover{
	/* 透明度を上げることで、画像の色を薄く見せる。*/
	opacity:0.5;
	/* リンクをホバーしたときのカーソルにする。*/
	cursor: pointer;
}
/* 画像をクリックした瞬間 */
.imgButton:active{
	/* 要素を若干下に下げることで、押した感じを出す。*/
	/* 今いる位置から相対的に3px下に配置する。*/
	position: relative;
	top: 3px;
}

# リンク
**Ionic frameworkのドキュメントへのリンク**
https://ionicframework.com/docs/v1/overview/#css-sass

**Ionicon Cheatsheetへのリンク**
https://ionicons.com/v1/cheatsheet.html
Homebrewの基本操作

##Homebrewの基本操作
###インストール可能なパッケージを確認する

```
$ brew search wget
==> Formulae
wget ✓   wgetpaste
```
上記のコマンドでwgetが含まれるパッケージが表示されます。
「✔︎」がついてるものはすでにインストールされているということになります。逆についてないと、未インストールということになります。
ちなみに、ログに記載のあるFormulaeはHomebrewの用語でパッケージのことをさします。

###異常確認

```
$brew doctor
Your system is ready to brew.
```
Homebrewに異常がないかを確認するためのコマンドです。
上記のような表示だと問題ありません。
異常がある場合は指示がログに残るので、その時は確認してください。

###バージョンを確認する

```
$ brew --version
Homebrew 2.0.6
Homebrew/homebrew-core (git revision 4050; last commit 2019-04-03)
```
上記のコマンドでHomebrewのバージョンを確認できます。

###インストール済みのパッケージ一覧を確認

```
$ brew list
gettext     libidn2     libunistring    openssl     wget
```
上記のコマンドでパッケージの一覧を確認できます。
いくつかパッケージが確認できますが、これはwgetをインストールした際に依存関係にあるパッケージが自動インストールされたものも含まれます。

###インストール済みのパッケージの起動状況を確認

```
$ brew services list
Name         Status  User         Plist          
postgresql   started (ユーザー名) /Users/(ユーザー名)/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
redis        stopped
```
上記のコマンドを実行すると、現在バックグラウンドで起動しているようなものの起動状況が確認できます。

###パッケージ情報を確認

```
$ brew info wget
wget: stable 1.20.1 (bottled), HEAD
Internet file retriever
https://www.gnu.org/software/wget/
/usr/local/Cellar/wget/1.19.5 (50 files, 3.7MB) *
  Poured from bottle on 2018-06-08 at 17:04:24
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/wget.rb
==> Dependencies
Build: pkg-config 
Required: libidn2 ✘, openssl 
==> Options
--HEAD
    Install HEAD version
==> Analytics
install: 134,032 (30 days), 480,367 (90 days), 1,454,711 (365 days)
install_on_request: 120,534 (30 days), 421,140 (90 days), 1,275,412 (365 days)
build_error: 0 (30 days)
```
上記のようにこのコマンドを叩くことで、パッケージ情報を確認することができます。

###更新のあるパッケージを確認

```
$ brew outdated
```
上記のコマンドでアップデートが溜まっているパッケージを確認できます。

###パッケージを更新

```
//パッケージ全部
$ brew upgrade

//パッケージ指定
$ brew upgrade パッケージ名
```
上記のコマンドでパッケージを更新できます。

###古いバージョンのパッケージの削除

```
//古いバージョンのパッケージの削除
$ brew cleanup

//削除対象のパッケージと容量を確認
$ brew cleanup -n 
```
上記のコードで古いバージョンのパッケージの削除や確認を行います。

###パッケージのアンインストール

```
$ brew uninstall パッケージ名
```
上記のコマンドでパッケージをアンインストールできます。

###Homebrewのアンインストール

```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"
```
上記のコードを実行することで、Homebrewとインストールしたパッケージも同時にアンインストールできます。
このコマンドを実行すると、アンインストールするファイルの一覧が表示されてから確認を挟んでくれます。
Put a semicolon there

備忘録です。

```.js
'use strict';

let range = {
  from: 1,
  to: 5,

  [Symbol.asyncIterator]() {
    return {
      current: this.from,
      last: this.to,
      async next() {
        await new Promise(resolve => setTimeout(resolve, 1000));
        if (this.current <= this.last)
          return { done: false, value: this.current++ };
        else
          return { done: true };
      }
    };
  }
}; // here

(async () => { for await (const value of range) console.log(value); })();
```

**here** のセミコロンを忘れると、 `TypeError: {(intermediate value)(intermediate value)(intermediate value)} is not a function` というエラーになります。

javascript の行解釈のヤなところorz

- 元ネタ: [非同期イテレーションとジェネレータ](https://ja.javascript.info/async-iterators-generators)


# 参考にしたページ

[文法 | JavaScript プログラミング解説](https://so-zou.jp/web-app/tech/programming/javascript/grammar/#no4)
【Vue.js】Vue.js サンプル「シャフル選択」



↓↓完成動画
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">⛱️Vue.js⛱️CodePen⛱️<br>💕Vue.js シャッフル選択💕作ってみたよぉ🍬<a href="https://t.co/cAArP8R6iW">https://t.co/cAArP8R6iW</a><a href="https://twitter.com/hashtag/vuejs?src=hash&amp;ref_src=twsrc%5Etfw">#vuejs</a> <a href="https://t.co/LLQxCnfq76">pic.twitter.com/LLQxCnfq76</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1167418023398891520?ref_src=twsrc%5Etfw">August 30, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


Vue.jsで、ハート型のボタンをTapする度に、シャッフル表示するサンプル。

<p class="codepen" data-height="600" data-theme-id="dark" data-default-tab="js,result" data-user="nonkapibara" data-slug-hash="OJLjMzM" style="height: 600px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="nonShuffleSelection">
  <span>See the Pen <a href="https://codepen.io/nonkapibara/pen/OJLjMzM/">
  nonShuffleSelection</a> by noriko fujita (<a href="https://codepen.io/nonkapibara">@nonkapibara</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

<br>
<br>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🍬Vue.js🍬<br>Vue CLI（v4.0.4） でVue.js作って、<br>Firebase(FirebaseHosting) にデプロイしてみたよぉ🤩<br><br>【Vue.js】カウントアップ（Firebase・Vue CLI v4.0.4）<a href="https://t.co/W7sWcleX4A">https://t.co/W7sWcleX4A</a><a href="https://twitter.com/hashtag/Vue?src=hash&amp;ref_src=twsrc%5Etfw">#Vue</a> <a href="https://twitter.com/hashtag/vuejs?src=hash&amp;ref_src=twsrc%5Etfw">#vuejs</a> <a href="https://twitter.com/hashtag/Firebase?src=hash&amp;ref_src=twsrc%5Etfw">#Firebase</a> <a href="https://t.co/ajUgvvvoSZ">pic.twitter.com/ajUgvvvoSZ</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1185650513469038592?ref_src=twsrc%5Etfw">October 19, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<br>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🎬Vue.js🎬<br>YouTubeの動画🎀APIリクエスト一覧表示🎀サンプル<br>作ってみたよぉ。<br>Vue CLI（v4.0.4） Vue.jsのaxiosでAPI通信🌏して、Firebase(FirebaseHosting) にデプロイ💡💡<br>ちゃんと動いたよぉ😍<a href="https://t.co/y7hw3zHRlI">https://t.co/y7hw3zHRlI</a><a href="https://twitter.com/hashtag/Vue?src=hash&amp;ref_src=twsrc%5Etfw">#Vue</a> <a href="https://twitter.com/hashtag/vuejs?src=hash&amp;ref_src=twsrc%5Etfw">#vuejs</a> <a href="https://twitter.com/hashtag/firebase?src=hash&amp;ref_src=twsrc%5Etfw">#firebase</a> <a href="https://t.co/C5zCM6n78R">pic.twitter.com/C5zCM6n78R</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1185956946630692864?ref_src=twsrc%5Etfw">October 20, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
fingerprintの調べ方(keystoreファイル、もしくはapkファイルから)

# keystoreファイルから
`keystore`ファイルがある場所へ移動し、下記を打ち込む。
`keytool -list -keystore [file name]`

```
$ keytool -list -keystore my-upload-key.keystore
Enter keystore password:
Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

my-key-alias, Aug 28, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA1): F5:A5:7E:6F:C2:CE:08

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore my-upload-key.keystore -destkeystore my-upload-key.keystore -deststoretype pkcs12".
```

# apkファイルから

`apk`ファイルがある場所へ移動し、下記を打ち込む。
`keytool -list -printcert -jarfile [file name]`

```
$ keytool -list -printcert -jarfile app-release.apk
Signer #1:

Signature:

Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Serial number: 2085
Valid from: Mon Sep 02 19:52:00 PST 2019 until: Fri Jan 18 19:52:00 PST 2047
Certificate fingerprints:
	 MD5:  26:D0:0D:AA:71:7C:E4:30:D1
	 SHA1: 93:A2:2C:38:3B:AF:A9:2F:82
	 SHA256: F3:A4:38:06:2C:A5:6C:8A:54:4F:36:E6:23:A0:8E:38:50:DF
Signature algorithm name: SHA256
```
Octaveコマンドまとめ1 -基本操作(主にベクトル)-

## Octave
先日 Coursera の **Andrew Ng 先生のMachine Learning** を受講し終えたのですが,そのプログラミング課題で使用したOctaveのコマンドをまとめたいと思います.
これからMachine Learningのプログラミング課題を受けるという方にはちょっと便利な記事かもしれない？
Andrew先生曰く Octaveはアルゴリズムを素早く組み立てることができるので,
**実際にアルゴリズムを構築する際には Octaveで試作してから python等で実装すると良い**とのこと.

本記事はおおよそWeek2の『Octave/Matlab Tutorial』のまとめです.
OctaveはMatlabとの互換性維持に重点を置いているみたいなので, Matlabとほぼ同じです.

一部具体例を踏まえ, 初歩の内容をまとめていきます.

**注意点**
・Octaveでは基本 (行,列)で書きます.
・一次元配列をベクトル, 二次元配列を行列と呼びます.
・基本的に小文字はベクトル,大文字は行列です.

## 演算子・論理演算子

| 演算子|入力コマンド|出力|注釈|
|:--------:|:--------:|:-------:|:------:|
|  +  |   5 + 6 |  11 |   
| -   |   5 - 6 |  -1 |    
| *   |   5 * 6 |  30 |   
| ÷   |   5 / 6 |  0.83333 |
| 累乗 |  2 ^ 3 |   8|   
| 等式 |   2 == 3 | 0| True:1 , False:0|
|非等式|  2 ~= 3 | 1|True:1 , False:0|
|不等号| 2 >= 3 | 0|True:1 , False:0|

| 論理演算子|入力コマンド|出力|注釈|
|:--------:|:--------:|:-------:|:------:|
|  and  |   1 && 0 |  0 |  True:1 , False:0|
|  or |   1 ┃┃ 0 |  0 |  True:1 , False:0|
|  xor  |   xor(1,0) |  1 |  True:1 , False:0|



#ベクトル・行列

※ 以下において vはベクトル,A,Bは行列とする.
###作成

|入力コマンド|出力|注釈|
|:------------:|:--------:|:--------:|
|v = [1 2 3]|1×3 行ベクトル|
|v = [1,2,3]| 3×1 列ベクトル|
|v = 1 : 0.1 : 2| [1　1.1　1.2  ...  1.9　2]　|(最初の数値):(刻む数値):(最後の数値)|
|v = 1:6| [1　2　...　6]　|
|ones(2,3) | 2×3行列(値がすべて1)|
|3*ones(2,3) | 2×3行列(値がすべて3)|
|zeros(2,3)|2×3行列(値がすべて0)|
|rand(2,3) | 2×3行列(値がランダム)|ランダム値は0~1の範囲|
|randn(2,3) | 2×3行列(値がランダム)|ランダム値はガウス分布から抽出されたもの|
|magic(3) | 3×3行列(縦, 横, 斜めの和が同値)|
|w = (平均値)+sqrt((分散))*(randn(1,10000))|平均,分散を指定してガウス分布作成|
|hist(w)| ヒストグラム作成|
|hist(w,50)|50ビンのヒストグラム作成|
|eye(3)|3×3の単位行列|単位行列:左上から右下にかけて1, それ以外0の行列|

###確認・操作

|入力コマンド|結果|注釈|
|:------------:|:--------:|:--------:|
|size(A)|Aの行×列を返す|
|size(A,1)|Aの行の次元サイズを返す|
|size(A)|Aの列の次元サイズを返す|
|length(v)|vの次元を返す|
|length(A)|Aの長い方への次元を返す|A = 2×3行列 なら, length(A) = 3|
|A(3,2)| 3行2列目の値参照|
|A(3,:)| 3行目すべて参照|
|A([1 3],:)| 1行目2行目すべて参照|
|A(:,2) = [1;2;3]| 2列目を置き換え|
|[A,[1;2;3]]|列を追加|
|A(:)|ベクトルになおす|
|[A　B] |A, B行列を列方向に連結|
|[A;B] |A, B行列を行方向に連結|
| A'|転置|2×4 → 4×2行列に|
|flipud(A)|垂直に反転|
|pinv(A)|Aの逆行列|

###行列の演算
要素同士の演算に . (ピリオド) がよく使われますが, 足し算の時には不要だったりするので自分で確かめるのが良いみたいです.

|入力コマンド|結果|注釈|
|:------------:|:--------:|:--------:|
|A*B|行列の積|
|A.*B|要素同士の掛け算|
|A.^2|各要素を2乗|
|A+1|各要素に+1|
|1./A|各要素の逆数|
|log(A)|各要素の対数を取る|
|exp(A)|各要素のeを底としたときのべき乗|
|abs(A)|各要素の絶対値|
|floor(A)|各要素を整数に切り捨て|
|ceil(A)|各要素を整数に四捨五入|
| A > 3 | 各要素が3より大きいか否か|True:1 , False:0|
|[r,c] = find(A > 3)|値が3より大きいインデックスを返す|r : 行,c : 列|
|sum(A,1) | 行方向の要素合計|Aが2×3 → 1×3 ベクトル出力|
|sum(A,2) | 列方向の要素合計|Aが2×3 → 2×1 ベクトル出力|
|sum(sum(A)) | 全要素合計|
|prod(A,1)| 行方向の要素積|
|prod(A,2)| 列方向の要素積|
|max(A,B)|A,Bの各要素同士の大きい方を出力|A,B行列に同等の次元の行列出力|
|max(A,[],1)|列の最大値|Aが2×3 → 1×3 ベクトル出力|
|max(A,[],2)|行の最大値|Aが2×3 → 2×1 ベクトル出力|
|max(max(A))|全要素の最大値|max(A(:))と同等|

##便利系
|入力コマンド|結果|
|:--------:|:--------:|
| PS1(' >> ')  | コマンドプロンプト上の 『>>』の部分を変更   |
| 末尾に; | 処理結果が表示されない|
|disp(a) | aを表示|
|disp(sprintf('2decimals : %0.2f', a))| aを少数2桁にして%0.2fに代入した文字列を表示|
|format long | デフォルトでより多くの桁数で表示|
|format short | デフォルトでより少ない桁数で表示|
| help (コマンド名)| コマンド名の詳細表示|
|pwd|カレントディレクトリのパス取得|

##以上
今回はとりあえずここまでです.
次回はデータのプロット(グラフ作成), ループ, if文, 関数についてまとめようと思います.
AsyncTaskLoaderは衰退したのか？

##〇概要
久々にAsyncTaskLoaderを使ったらsupportLoaderManagerが非推奨になっていました。

```
'getter for supportLoaderManager: LoaderManager!' is deprecated. Deprecated in Java
```

loaderManagerも同じく

```
'getter for loaderManager: LoaderManager!' is deprecated. Deprecated in Java
```

##〇調査

とりあえず公式
https://developer.android.com/reference/android/content/AsyncTaskLoader

目立つところに書いてますね。
![warning.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252283/2714c2f4-c5b9-5157-4477-d991931f04e6.png)

API level 28から非推奨と
たしかに
<font color="blue">implementation 'com.android.support:appcompat-v7:28.0.0'</font>
のバージョンを下げると警告は消えました。

[Revisions](https://developer.android.com/topic/libraries/support-library/revisions)を見てみると

Revision 28.0.0 Productionは[September 21, 2018]からリリースなので1年ぐらい前ですね。

Revision 27.1.0 Release
には以下のようなことが
<font color="red">The underlying implementation of Loaders has been rewritten to use Lifecycle. While the API remains unchanged, there are a number of behavior changes:</font>
[ローダー関係](https://developer.android.com/guide/components/loaders.html)は[アーキテクチャーライブラリ](https://developer.android.com/topic/libraries/architecture)を使うように書き換えるよと。

stackoverflowの投稿を読んでみると、アクティビティやフラグメントのライフサイクルの流れを考えると、ViewModelやLiveData等のアーキテクチャコンポーネントを使うほうが適切になったそうです。

もう利用頻度は大分減った技術なんですかね・・・

しかし、警告にあるようにSupport Libraryではまだ使えるます！
https://developer.android.com/reference/android/support/v4/content/AsyncTaskLoader.html

したがって修正

##〇対応
```Kotlin:XXX.kt
getSupportLoaderManager().initLoader(LOADER_TAG_METADATA,bundle,callback)
↓
LoaderManager.getInstance(this).initLoader(LOADER_TAG_METADATA,bundle,callback)

loaderManager.destroyLoader(loader.id)
↓
LoaderManager.getInstance(this@MainActivity).destroyLoader(loader.id)
```
##〇結果
これで警告は解除。
しかし、やはり時代はAndroidのアーキテクチャーコンポーネントを自在に使いこなせるようにならないとダメみたいですね。
child_process.exec を使ってみた

元ネタは[現代の JavaScript チュートリアル](https://ja.javascript.info/async-iterators-generators)

```sync_iterator.js
'use strict';

let range = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    return {
      current: this.from,
      last: this.to,
      next() {
        if (this.current <= this.last)
          return { done: false, value: this.current++ };
        else
          return { done: true }
      }
    }
  }
}

for (const value of range) console.log(value);
```

```test.js
'use strict';

const assert = require('assert');
const child_process = require('child_process');

describe('Async iterator', () => {
  it('should output sequence', done => {
    child_process.exec('node ./async_iterator.js', (error, stdout) => {
      assert.equal(stdout, '1\n2\n3\n4\n5\n');
      done();
    });
  });
});
```

# 参考にしたページ

[Child Process | Node.js v12.9.1 Documentation](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)
さくらインターネットのレンタルサーバーにssh通信&データベース接続(初心者用)

## 前提

## 知識
UNIX系のコマンド使用経験
Google検索する力

## レンタルサーバの情報を用意する
FTPサーバー名 [name].sakura.ne.jp
FTPアカウント [name]
サーバーパスワード [password]

下で、[name]、[password]を使うときには、[]は実際には記述しない。


## ssh鍵


### 事前テスト

```bash
ssh [name]@[name].sakura.ne.jp
[name]'s password: パスワード入力
```
を実行し、
`Welcome to FreeBSD!`が出力されれば、問題なくサーバーと通信できる
その後、

```bash
exit
```
を忘れないように

### ssh鍵作成

```bash
cd .ssh
ssh-keygen -t rsa -C "メールアドレス" -f "鍵の名前"
Enter passphrase (empty for no passphrase): 好きなパスワードを入力
```

### ログイン設定を準備
`/.ssh/config`に、以下の内容を書き込む。

```text
Host sakura
  HostName [name].sakura.ne.jp
  User [name]
```
`sakura`は、好きな文字列に置き換えることができる。置き換える場合、ここよりしたの`sakura`はすべてその文字列に置き換えること。

### ssh鍵をサーバーに送る

#### 使う人が1人の場合

```bash
scp 鍵の名前.pub sakura:/home/[name]/.ssh/authorized_keys
```
パスワードを聞かれたら、入力すること。

#### 使う人が複数人の場合

全員の`鍵の名前.pub`の内容を一つにまとめる。

```text
ssh-rsa (以下略)
ssh-rsa (以下略)
...
ssh-rsa (以下略)
```
のようにして、ファイルに保存する。
そして、

```bash
scp ファイル名 sakura:/home/[name]/.ssh/authorized_keys
```
を実行する
パスワードを聞かれたら入力すること。

### できたかチェック

```bash
ssh sakura
```

## データベース接続

### mysqlを実行する方法
`mysql -u ユーザー名 -pパスワード -h mysql(3桁の数字).db.sakura.ne.jp`
を実行


## 参考にしたサイト
[よく使うMySQLコマンド集](https://qiita.com/CyberMergina/items/f889519e6be19c46f5f4)
[【PHP超入門】クラス～例外処理～PDOの基礎](https://qiita.com/7968/items/6f089fec8dde676abb5b)
[PHPでデータベースに接続するときのまとめ](https://qiita.com/mpyw/items/b00b72c5c95aac573b71)
[【PHP】JSONデータのPOST受け取りで application/x-www-form-urlencoded とapplication/json の両方に対応](https://qiita.com/Kunikata/items/2b410f3cc535e4104906)
[【PHP超入門】HTTP（GET・POST）について](https://qiita.com/7968/items/4bf4d6f28284146c288f)
windows上でmaildir形式のthunderbirdのメールをsylpheedに移す

# 結論

- pythonでファイルを一つずつ開いて文字コードと改行コードだけ変換して保存するのが簡単で早い

# thunderbirdのメール保存形式

- mboxかmaildirか選択できる．標準はmbox．
- mboxで保存している場合，もっと単純にsylpheedからインポート可能．
- maildirを選択しているとフィルタの動作にバグっぽい挙動があり，メールが増殖したりする  
  →[MozillaZine\.jp フォーラム • トピック \- mboxからmaildir形式に変更したフォルダでフィルターが機能しない](https://forums.mozillazine.jp/viewtopic.php?f=3&t=17617)
- mboxへの変換は可能だが，添付ファイルもあったりすると，とてつもなく時間がかかるし無駄．

# sylpheedのメール保存形式

- mh形式
- よく見てみると改行コードが\nだったり，文字コードが合わなかったりで，maildirをそのまんまコピーしたのでは読み込めない
- 構造はクソ単純なので，maildirを文字コードと改行コードだけ変換して連番でつっこめば動作しそうではある

# コード

- このプログラムを実行したカレントディレクトリにimportHogehogeという感じの名前でMH形式でメールが保存される．
- `i = 1`を適当な数字に変えることで，既に利用しているMH形式のメールの続きとして出力できる

```python
import mailbox
import os

path_to_maildir = 'hogehoge'  # thunderbirdの受信箱 'Inbox' フォルダの入っているフォルダ
targets = ['Inbox', 'Inbox/subdir', ]

for target in targets:
    mhdir = f"import{target.replace('/', '')}"
    mdir  = f"{path_to_maildir}/{target.replace('/','.sbd/')}"
    _ = mailbox.MH(mhdir, create=True)

    files = os.listdir(f'{mdir}/cur')
    i = 1
    for f in files:
        if f[0] == '.':
            continue
        with open(f'{mdir}/cur/{f}', encoding='utf-8') as fobj:
            with open(f'{mhdir}/{i}', 'wb') as wobj:
                try:
                    buf = fobj.read()
                except Exception as ex:
                    # エンコーディングが違っている場合
                    # 私の環境ではJISはなかったようのでスルーした
                    # 必要に応じてtryの階層を掘っていけば何とかなる
                    with open(f'{mdir}/cur/{f}', encoding='cp932') as fobj2:
                        buf = fobj2.read()
                wobj.write(buf.replace('\r','').encode('utf-8'))
            i += 1
```
Bitriseのナンバリングを利用して、バージョンの自動インクリメントを実現(ReactNative, ios)

下記記事でFastlaneをBitriseに組み込み、MyAppへの自動デプロイを実現しました。
[FastlaneのコマンドをBitriseに組み込む(ios,ReactNative)](https://qiita.com/kenkono/items/b31bc3c3a5aed236643c)
しかし、開発の現場ですとデプロイ毎にバージョン番号を繰り上げて管理したいです。
そこで利用するのが、Bitriseのナンバリング番号です。

android版はこちら↓
[Bitriseのナンバリングを利用して、バージョンの自動インクリメントを実現(ReactNative, android)](https://qiita.com/kenkono/items/6b0f6d8634b0a6cbaf4e)

# Bitriseのナンバリング番号とは
[Build numbering and app versioning](https://devcenter.bitrise.io/builds/build-numbering-and-app-versioning/)
Bitriseのworkflowが動く際に管理されている番号のことです。
実行毎に番号が繰り上がるため、この番号をバージョン番号として使用しようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/37b42e86-4968-447c-40fe-1d9959818e91.png)

# 設定

Bitriseのをworkflowを編集します。
`fastlane`フローの前に`Set Xcode Project Build Number`を挿入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/6e89f2b9-53d9-3e51-1709-c75d3c9c21fa.png)

設定を記述します。
Info.plist file pathに`ios/アプリ名/info.plist`
Build Numberに`$BITRISE_BUILD_NUMBER`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/c4a151d1-dad4-2098-2acb-037edff49eb1.png)


これに伴い下記記事で作成したファイルの`increment`の機能は不要になるため、該当部分を削除します。
[fastfileの編集](https://qiita.com/kenkono/items/a3eb4d1a83d8b1d70864#fastfile%E3%81%AE%E7%B7%A8%E9%9B%86)

```ruby:ios/fastlane/Fastfile
desc "Push a new release build to the App Store"
  lane :release do
    # increment機能は不要のため、削除
    # increment_build_number(xcodeproj: "ReactNativePlatform.xcodeproj")

    match(type: "appstore")
    build_app(scheme: "ReactNativePlatform")
    upload_to_app_store(
      skip_waiting_for_build_processing: true
    )
    clean_build_artifacts
  end
```

# 実行
上記設定でBitriseが動きますと、MyAppにてバージョン番号がBitriseのナンバリング番号と一致しているのが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/2e97c95c-16d7-72fe-2390-c9436e7f316d.png)


# 参考
[iOSアプリのビルド番号自動設定をfastlaneまたはBitriseでラクラク実現する方法](https://tech.gunosy.io/entry/ios_build_number_with_fastlane_or_bitrise)
WindowsノートPCの自動起動/終了

#ノートPCでの自動起動/終了
WindowsのノートPCを展示などで使う際、自動起動/終了の設定を毎回忘れてしまうので備忘録です。

展示などの場合イベントの開始終了に合わせてPCの電源やアプリをオンオフしたくなります。
自動終了についてはコマンドをタスクスケジューラで実行するなり、アプリに組み込むなりすることで実現できます。
しかし自動起動については少しややこしく、基本的に電源オフ状態から時刻指定で立ち上げられるかどうかは使うPCのBIOSによります。

なので代替案として終了させたい時刻にPCをスリープさせ、開始時刻にスリープ解除→再起動するという手段をよくとっています。
（ただ夜間停電するような会場だとスリープ時にバッテリー切れになってしまいこの手段がとれない場合があります。）
今回はその設定手順です。

#以下、設定手順
##1, パスワード設定
「設定＞アカウント＞サインインオプション＞パスワード」でパスワードを設定。
「設定＞アカウント＞サインインオプション＞サインインを求める」をロックしないに変更。

##2, 自動ログイン設定
［windowsキー+R］を押して"netplwiz"を実行。
最上部の「ユーザーがこのコンピューターを使うには...」のチェックを外す。

##3, スリープ解除タイマーの許可
「コントロールパネル＞電源オプション＞プラン設定の編集＞詳細な電源設定の変更＞スリープ＞スリープ解除タイマーの許可」を有効にする。

##4, スリープの設定
こちらの記事を参考にスリープのコマンドを実行する。
https://tipszone.jp/20110517_stop-pc/

##5, 再起動の設定
タスクスケジューラで"shutdown -r -t 0"のコマンドを実行するタスクを作成する。
この時「条件」タブの「タスクを実行するためにスリープ解除する」にチェックを入れる。

以上です。
(Python) DataFrame のappend 時に配列が1列の複数データで挿入される際の解決方


## 問題：pandas.DataFrame にappend した行の配列データが、１列に複数のデータとして入る。
pandas.DataFrame のインスタンスに行を追加しようとした際、配列データをappend メソッドで追加すると、**１列に複数のデータとして入る**ようでした。

```sample.py
from pandas import DataFrame

dataFrame = DataFrame([
    ['a','b','c','d','e'],
    ['f','ggg','hhhh','ii','jjjjjjjj'],
])
appendedDataFrame = dataFrame.append(
    ['a','b','c','d','e']
)

print(appendedDataFrame)
```

```出力結果.txt
   0    1     2    3         4
0  a    b     c    d         e
1  f  ggg  hhhh   ii  jjjjjjjj
0  a  NaN   NaN  NaN       NaN
1  b  NaN   NaN  NaN       NaN
2  c  NaN   NaN  NaN       NaN
3  d  NaN   NaN  NaN       NaN
4  e  NaN   NaN  NaN       NaN
```

新規の行が 0 - 5 までのindex で複数のデータとして挿入されましたが、本来は行として挿入するつもりだったため、配列を行として一行追加する方法を調査しました。

## 解決法：pandas.Series のインスタンスとして append する。
一度`pandas.Series` インスタンスに配列データを入れて、それをDataFrame の appendメソッドに渡すことで、期待するDataFrame になりました。（この時 `pandas.Series` の name が append した時の行の index 名となるようでした。）

```sample.py
from pandas import DataFrame, Series

dataFrame = DataFrame([
    ['a','b','c','d','e'],
    ['f','ggg','hhhh','ii','jjjjjjjj'],
])
appendedDataFrame = dataFrame.append(
    Series(
        ['a','b','c','d','e'],
        name=2
    )
)

print(appendedDataFrame)

```

```出力結果.txt
   0    1     2   3         4
0  a    b     c   d         e
1  f  ggg  hhhh  ii  jjjjjjjj
2  a    b     c   d         e
```
これで新たな行を DataFrame に挿入することができました。

## Series には、name を設定するか、append メソッドに、igonore_index=True を設定する必要がある。
Series には、name（挿入する行のindex名）を指定しないと下記のエラーとなりました。

```
TypeError: Can only append a Series if ignore_index=True or if the Series has a name
```

Series には、name（挿入する行のindex名）を指定しない場合、これを回避するために、ignore_index=True を設定する必要があるようです。

```sample.py
from pandas import DataFrame, Series

dataFrame = DataFrame([
    ['a','b','c','d','e'],
    ['f','ggg','hhhh','ii','jjjjjjjj'],
])
appendedDataFrame = dataFrame.append(
    Series(
        ['a','b','c','d','e'],
    ),
    ignore_index=True
)

print(appendedDataFrame)
```



```出力結果.txt
   0    1     2   3         4
0  a    b     c   d         e
1  f  ggg  hhhh  ii  jjjjjjjj
2  a    b     c   d         e
```


以上です。
Bitriseのナンバリングを利用して、バージョンの自動インクリメントを実現(ReactNative, android)

下記記事でFastlaneをBitriseに組み込み、google play consoleへの自動デプロイを実現しました。
[FastlaneのコマンドをBitriseに組み込む(android,ReactNative)](https://qiita.com/kenkono/items/9e00eb3de49208e8892e)
しかし、開発の現場ですとデプロイ毎にバージョン番号を繰り上げて管理したいです。
そこで利用するのが、Bitriseのナンバリング番号です。

ios版はこちら↓
[Bitriseのナンバリングを利用して、バージョンの自動インクリメントを実現(ReactNative, ios)](https://qiita.com/kenkono/items/e5a2be486840bb07b86c)

# Bitriseのナンバリング番号とは
[Build numbering and app versioning](https://devcenter.bitrise.io/builds/build-numbering-and-app-versioning/)
Bitriseのworkflowが動く際に管理されている番号のことです。
実行毎に番号が繰り上がるため、この番号をバージョン番号として使用しようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/37b42e86-4968-447c-40fe-1d9959818e91.png)

# 設定

`android/app/build.gradle`の`versionCode`を下記のように変更します。
Bitriseのデフォルトの環境変数である`BITRISE_BUILD_NUMBER`を使用します。

```ruby:android/app/build.gradle
defaultConfig {
        applicationId "com.reactnativeplatformBitrise"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion

        Integer buildNumb = System.getenv("BITRISE_BUILD_NUMBER") as Integer
        versionCode buildNumb ?: 1 
        
        versionName "1.0"
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
        }
    }
```

これに伴い下記記事で作成したファイルの`increment`の機能は不要になるため、該当部分を削除します。
[fastfileの編集](https://qiita.com/kenkono/items/4b58f09eb5ffa177eeeb#fastfile%E3%81%AE%E7%B7%A8%E9%9B%86)

```ruby:android/fastlane/Fastfile
  desc "submit internal release to Google Play Store"
  lane :internal do

    # 下記のincrement機能は削除
    # increment_version_code(
    #   gradle_file_path: "./app/build.gradle"
    # )

    # make apk file
    gradle(task: "assembleRelease")
    # find the apk file
    supply(
      track: "internal",
      apk: "#{lane_context[SharedValues:: GRADLE_APK_OUTPUT_PATH]}"
    )
```

# 実行
上記設定でBitriseが動きますと、google play consoleにてバージョン番号がBitriseのナンバリング番号と一致しているのが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291139/fa1be639-ae03-018a-9aac-677cddb839d8.png)

# 参考
[Adding Bitrise build number to Android app version Code](https://medium.com/@AndreSand/adding-bitrise-build-number-to-android-app-version-code-7ad3be41908a)
ゼロ埋め連番作成 (vim Tips)

こんな感じのゼロ埋めシーケンスデータを準備したい

```
0000000
0000001
0000002
0000003
　：
(途中省略)
　：
0009997
0009998
0009999
```

#想定シーン

- 1万行作りたい　→　エクセルじゃきつい
- DBとか使えない
- vimがある

#vim機能のおさらい

###インクリメント、デクリメント

| インクリメント       |     デクリメント  |
|:-----------------:|:------------------:|
| **[Ctrl]** + **[a]** | **[Ctrl]** + **[x]** |

###nrformatsの設定

| 設定値 | 振る舞い |
|:-----------------:|:------------------|
| octal | 8進数扱い（デフォ） |
| hex | 16進数扱い |
| alpha | アルファベット |
| 未設定 | 10進数扱い |

###キーマクロ

| 記録開始       |  記録終了  |  実行  |
|:-----------------:|:------------------:|:------------------:|
| **[qa]**| **[q]** | **[@a]** |
※aに設定する場合

#実行（ベースデータ作成）

###vim起動
```
$ vim zero.txt
```

### nrformatsを10進数に
```
:se nf=
```


### 6桁のゼロを記入
```
000000
```

#実行（キーマクロでインクリメント記録）

### キーマクロ開始
**[qa]**

### 1行目をyank（コピー）
**[yy]**

### ペースト
**[p]**

```
000000
000000
```

### カーソル行でインクリメント
**[Ctrl]** + **[a]**

```
000000
000001
```

### キーマクロ終了
**[q]**

#実行（1万行作成）

### キーマクロ実行（1万回）
**[10000@a]**
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/43814a2c-8376-7743-48b9-60835fe50a39.png)
digdag の docker.run_options を少しだけ試した

# digdag の docker.run_options

digdagのバージョン `0.9.37 ` から docker に関する オプションが使えるようになったようです。


リリースノート : https://docs.digdag.io/releases/release-0.9.37.html?highlight=run_options

該当PR : https://github.com/treasure-data/digdag/pull/1025


PR の方から引用すると、以下のように設定できるみたいです。

```
_export:
  docker:
    image: ruby:2.5.1
    build:
      - apt install vim
    docker: /usr/local/bin/nvidia-docker
    run_options: ["-v", "/tmp:/tmp"]
    build_options: ["--pull"]
```

ここの　`run_options: ["-v", "/tmp:/tmp"]` ですが、 `run_options: ["-v /tmp:/tmp"]` みたいにできないものか と思って試したら

```sh
docker: Error response from daemon: create  /: " /" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
```

ってエラーが出るので出来なかったよ って話です (`build_options` でも同様ですね.)


## digdag の DEBUGログを見てみる

`digdag run -l debug` で デバッグログを出力することができます。

- `run_options: ["-v", "/tmp:/tmp"]` のときに実行されるコマンド

```
2019-08-30 19:19:07 +0900 [DEBUG] (0017@[0:default]+sample_wf+sample_docker_run_options) io.digdag.standards.command.DockerCommandExecutor: Running in docker: docker run -v /tmp:/tmp -i --rm -v ..略
```


- `run_options: ["-v /tmp:/tmp"]` のときに実行されるコマンド

```
2019-08-30 19:20:22 +0900 [DEBUG] (0017@[0:default]+sample_wf+sample_docker_run_options) io.digdag.standards.command.DockerCommandExecutor: Running in docker: docker run -v /tmp:/tmp -i --rm -v ..略
```


DEBUGログに表示される `docker`コマンドは**全く一緒**で、 どちらもコマンド的には問題なさそう。

コマンドだけをコピって ローカルのターミナルで実行すると実行できます。

上記の `docker: Error response from daemon` みたいなエラーは出ません。


## ではなぜ出来ないか

`run_options` は [この部分](https://github.com/sonots/digdag/blob/40fc2841606df74378146f0f95f0dba0837392d7/digdag-standards/src/main/java/io/digdag/standards/command/DockerCommandExecutor.java#L82) で `command` と宣言された `ImmutableList` に `addAll` されています。

この変数 `command` は最終的に `ProcessBuilder docker = new ProcessBuilder(command.build());` として `ProcessBuilder` に渡されます。


`ProcessBuilder` はプロセスの実行前にコマンドを一つにつなげる訳でもなく、`command.toArray(new String[command.size()]);` とするので、`run_options: ["-v /tmp:/tmp"]` と定義してしまうと、それが一つのコマンドとして入力されてしまうんですねぇ..?

つまり、**イメージ的には**

- `run_options: ["-v", "/tmp:/tmp"]` のときに実行されるコマンド

```sh

"docker" "run" "-v" "/tmp:/tmp" "nannka-image:0.1"
```

- `run_options: ["-v /tmp:/tmp"]` のときに実行されるコマンド

```sh

"docker" "run" "-v /tmp:/tmp" "nannka-image:0.1"
```
※ 上記を実行すると `docker: Error response from daemon` が発生します.
   
## まとめ

DEBUG ログでは、

```
logger.debug("Running in docker: {} {}", command.build().stream().collect(Collectors.joining(" ")), imageName);
```

とされてたので、`run_options: ["-v /tmp:/tmp"]` でも問題ないように見えたんですが、実際には `ProcessBuilder` による実行なので、問題あるんだよって話でした。


「そらそうよ。だから配列なんやで。」 って感じですかね。


何か間違っている点等がありましたら、ご指摘いただけると幸いです。
PWAのホーム画面追加ポップアップを任意のデザインに変更する方法

## イメージ

- デフォルトのポップアップデザイン

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271161/c7cd0ad3-8b7b-00ef-4b33-a783be6cf9b6.png" width="500">

- ポップアップを制御して（表示されないようにして）任意のデザインを充てたい

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271161/7172eba4-d444-3b15-f5d1-f92f9439a46b.png" width="500">


> 参考：[Add to Home Screen](https://developers.google.com/web/fundamentals/app-install-banners/)
> 参考：[Patterns for Promoting PWA Installation (mobile)](https://developers.google.com/web/fundamentals/app-install-banners/promoting-install-mobile)

## コード
```javascript:example.js
function promptA2hs() {

  let deferredPrompt;

  window.addEventListener('beforeinstallprompt', (e) => {
    let btnAdd = $('#promptPwa');
    e.preventDefault();
    deferredPrompt = e;
    btnAdd.css('display', 'block');

    btnAdd.click(function (e) {
      deferredPrompt.prompt(e);
      deferredPrompt.userChoice
        .then((choiceResult) => {
          if (choiceResult.outcome === 'accepted') {
            console.log('User accepted the A2HS prompt');
          } else {
            console.log('User dismissed the A2HS prompt');
          }
          deferredPrompt = null;
        })
    })

  });
}
```

この関数をサービスワーカーインストール後に記述

```javascript
  window.addEventListener('load', function () {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register("sw.js")
        .then(function (registration) {
          console.log("sw registed.");
        }).catch(function (error) {
          console.warn("sw error.", error);
        });
    }
  });
  promptA2hs()
```


## やっていること
- beforeinstallpromptイベントを使います。

- ボタンデザインのhtmlとcssは別途用意。該当箇所はcssで```display: none```にしておく
- 本来ホーム画面追加のポップアップが発火するタイミングで、
    - イベント（e）を```deferredPrompt```という変数に入れておく（スタッシュさせておく）。
    - 該当箇所を```display: block```に変更
    - 該当箇所をクリックしたときに```prompt```で```deferredPrompt```にスタッシュさせていたイベント発火させる。
- 追加 or キャンセルで任意のイベントを記載。```deferredPrompt.userChoice```以下。（GAで追加とキャンセルの数を計りたいとき等）

## 参考
- [Add to Home Screen](https://developers.google.com/web/fundamentals/app-install-banners/)
- [Patterns for Promoting PWA Installation (mobile)](https://developers.google.com/web/fundamentals/app-install-banners/promoting-install-mobile)
- [BeforeInstallPromptEvent](https://developer.mozilla.org/en-US/docs/Web/API/BeforeInstallPromptEvent)
Laravel view()とredirect()の違いについてまとめてみた

こんにちは。

Laravelのview()とredirect()の違いがいまいちわからず、自身で調べて納得できるレベルになったのでまとめてみました。

view()もredirect()もそれぞれ、(何らかの処理を行ったりした後に)ページ遷移をさせる処理です。

#view()#
表記の仕方は以下の通りです。
redirect()もそうですがController側に書きます。

```php:WelcomeController.php
public function index() 
{
    $message = 'ようこそ'
    return view('welcome', ['message' => $message]);
}
```

上記の場合、welcome.blade.phpにmessageという情報を保持させたまま、画面に表示させることになります。

この時ですが、welcome.blade.phpは resoure -> views 内にwelcome.blade.phpが存在するか確認し、存在した場合は表示処理が行われます。（レンダリング）

web.phpに記載する
```Route::get('welcome', 'WelcomeController@index')```
が行われているわけではないので注意しましょう。


#redirect()#
表記の仕方は以下の通りです。
WelcomeController.phpの表記を少し変更しました。

```php:WelcomeController.php
public function post() 
{
    return redirect('/welcome');
}
```
リダイレクト処理が行われた場合、web.phpに記載されるルーティング情報が読み込まれます。
正確にはRoute::get()が読み込まれます。詳細は後述します。
view()のように直接ファイルを読みに行ってるわけではないので注意しましょう。


#view()とredirect()の使い分け#
view()はWebページのアクセス時などのGET処理時に利用します。
そのため、Route::get()で利用されます。

それに対し、redirect()はフォーム送信などのPOST時に利用されます。
そのため、Route::post()で呼び出すメソッド内に記述します。

注意したいのが、RedirectはGET判定されることです。
そのためredirect()が実行されると、web.phpのRoute::get()が読み込まれるため注意しましょう。

redirect()を利用するときは以下のように誤ってRoute::getで呼び出したメソッド内に、redirect('welcome')など書かないようにしましょう。

```PHP
// WelcomeController.php
public function index() {
    return redirect('/welcome');
}

// web.php
Route::get('/welcome', 'WelcomeController.php@index);
```

この場合 redirect('welcome') -> Route::get('welcome...)読み込み -> redirect('welcome') -> Route::get('welcome...)読み込み
と延々に処理を繰り返してしまうためです。

#おわりに#
個人的に結構理解するのに時間がかかったため参考になれば幸いです。
【見出し編】Qiita記事をSEO的に改善してみよう。

## 1.googleさんが見出しついて言っている事

>一般に、見出しタグはタグに囲まれているテキストをページ上の通常のテキストよりも大きく表示するため、ユーザーにとってはそのテキストが重要であるという視覚的な手がかりとなり、見出しテキストの下に続くコンテンツの内容について理解しやすくなります。複数の見出しサイズを正しい順序で使用すると、コンテンツの階層構造が作成され、ユーザーがドキュメント内を移動しやすくなります
出典：<a href=https://support.google.com/webmasters/answer/7451184?hl=ja>Google Search console</a>

googleさんが見出しについて上記の事を述べており、今回大事なところは
>**複数の見出しサイズを正しい順序で使用する**

ここになります。

## 2.Qiitaの見出しについて
Qiitaはとても見出しがつけやすく「#」一つで見出しを作れるんですが、
「#」で作った見出しは「h1」になってしまうため、「h1」が大量発生してしまいます。

<a href=https://qiita.com/Nash-BETA/items/0d4e876cf9460778b985>こちら</a>の記事を参考に見出しを見てみると
<img width="658" alt="qiitaでSEO上位にあげたい（見出し）.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454305/6103a3b0-1933-9955-9e5a-8aa4b6634bdc.png">

h1が複数作成されており、タイトルと同じh1（ここでいうと「GitHubでセキュリティ脆弱性のアラートが来てビビりながら対応した話」）と同列で見出しを作成してしまっております。
そのため、googleさんがいう**複数の見出しサイズを正しい順序で使用する**を守れていない記事になってしまいます。

## 3.改善策

「#」で見出しを作らない様にして、「##」から順番に見出しを作ることでGoogleさんが言う「複数の見出しサイズを正しい順序で使用する」を守れる様になります。
ShellScript ls コマンド で 得られた ファイルとフォルダ の 個数 を 出力する

# 目的

- ShellScriptでlsコマンドの結果として得られたファイルとフォルダの個数を出力する方法を知る。

# 書き方の例

- 下記にShellScriptの処理を記載する。

``` shell
変数=(`ls`)
echo ${#変数[*]}
``` 

# より具体的な例

- フォルダ`/home/miriwo/work`直下のフォルダとファイルの数を出力する。
- 下記にShellScriptの処理を記載する。

``` shell
# ディレクトリ数、ファイル数を知りたいディレクトリに移動
cd /home/miriwo/work

# lsコマンドの結果を変数ls_resultに格納
ls_result=(`ls`)

# 結果数を格納した内容を出力する
echo ${#ls_result[*]}
```
pandas.DataFrame内のlist型を維持してファイルに吐き出したい

# MLモデル開発中にデータをファイルで保存したい

MLモデルの開発では、前処理や特徴量エンジニアリングなどの工程があり、
前処理を終えたデータを一時的にそのままの形でファイルに吐き出したい時などがある。
通常の場合、pandasの`to_csv` 関数でcsv出力すれば問題はない。しかし、DataFrame内のlist型が存在する時に型を保存できなくて困り、調べた。
(list型をDataFrameに入れることはあまりないが、複数選択可の項目で処理のために配列にしたい時があった。)

僕の場合の結論は、`parquet` で保存することが一番好ましかった。
調べたら色々と方法があったので、それぞれの方法をまとめる。

## DataFrameの準備
今回はDataFrame内のlist型の挙動を確認したいので、list型のデータを作る。

```.py
import pandas as pd


# ファイルの保存先のパス
file_path = './filepath'
# S3用
bucket = 'bucket_name'
prefix = 'prefix_path'

df = pd.DataFrame(data={'int_col': [1, 2], 'list_col': [[1, 2], [3, 4]]})

print(type(df['list_col'][0])) # <class 'list'>
```


## csvで読み書き
DataFrameをcsv出力させ、そのファイルを改めて読み込むとlist型はstring型になってしまう。

```.py
# 書き込み
df.to_csv(f'{file_path}/sample.csv.gz', index=False, compression='gzip')
# 読み込み
df = pd.read_csv(f'{file_path}/sample.csv.gz')
# 型確認
print(type(df['list_col'][0])) # <class 'str'>
```

以下のようにすることで、list型に変換できる。

```.py
df['list_col'] = df['list_col'].apply(eval)
print(type(df['list_col'][0])) # <class 'list'>
```

## pickleで読み書き
pickle は python に標準的に組み込まれており、オブジェクトをファイルとして保存することができる。
DataFrame内のlist型もしっかり扱うことができる。

```.py
# 書き込み
df.to_pickle(f'{file_path}/sample.pickle.gz', compression='gzip')
# 読み込み
df = pd.read_pickle(f'{file_path}/sample.pickle.gz')
# 型確認
print(type(df['list_col'][0])) # <class 'list'>
```

pythonのオブジェクトを読み込む必要があるので、pythonでしか扱えないのがネック。

## parquetで読み書き
こちらが今回の本命。
恥ずかしながら今回調べるまでは「Athenaで扱うときのフォーマットでしょ？」くらいの認識だった。
Column-orientedフォーマットというものにカテゴリ分けされるらしく、 列方向にデータが格納されている。
そのため、圧縮アルゴリズムも効きやすく、列を指定しての読み込みもできてしまう。

pythonで扱うためには、`fastparquet` か `pyarrow` というライブラリをインストールする必要がある。どちらも `pip` で簡単にインストールできる。
今回は `fastparquet` をインストールして試してみる。

```.py
# 書き込み
df.to_parquet('sample.parquet.gz', compression='gzip')
# 読み込み(columnsでカラムを指定できる)
df = pd.read_parquet('sample.parquet.gz', columns=['list_col'])
# 型確認
print(type(df['list_col'][0])) # <class 'list'>
```

pickleと同様にlist型も保存されている。


### S3に読み書き
fileをS3に置く場合も調べたので書いておく。
僕の調べた限りだと `to_parquet` 関数では送れなさそうだった。
以下のようにすればできた。

```.py
# 書き込み
import s3fs
from fastparquet import write

s3 = s3fs.S3FileSystem()
myopen = s3.open

write(
    f's3://{bucket}/{prefix}/sample.parquet.gz', 
    df, 
    compression='GZIP',
    open_with=myopen)
```
```.py
# 読み込み
import s3fs
from fastparquet import ParquetFile

s3 = s3fs.S3FileSystem()
myopen = s3.open

pf = ParquetFile(
    f's3://{bucket}/{prefix}/sample.parquet.gz',
    open_with=myopen)
df = pf.to_pandas()
```

## まとめ
csv(型が保存できない) → pickle(pythonでしか使えないし...) → Parquetという話だったのだが、
色々調べていたら列志向とデータ分析の相性の良さを改めて感じさせられた。
csvでもpickleでもparquetでも、扱うことはできるので使い分けが必要。

個人的には、データをpython(pandas)で扱う際に、カラムを指定して読み込みたい時は多々あるので、
今後はParquetフォーマットを使っていきたいと思う。


## 参考
https://blog.amedama.jp/entry/2017/10/10/135331
http://nagix.hatenablog.com/entry/2015/12/08/235512
https://note.nkmk.me/python-pandas-to-pickle-read-pickle/
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_parquet.html
phpspreadsheet 保存csv日语乱码的问题

//保存するファイルのファイルポインタを開く
 $fp = fopen('/var/www/html/laravel/public/'.$file_name, "w");
 
 
 //fputcsvでCSVデータを作る
 foreach ($sheet->toArray() as $val) {mb_convert_variables('SJIS-win', 'UTF-8', $val);fputcsv($fp, $val);}

 //ファイルポインタを閉じる
 fclose($fp);
SQL Serverで時間のかかっているクエリを算出するクエリ

備忘録
コンパイルされたクエリ毎に実行される

```SQL
DECLARE @DB名 nvarchar(16) = N'sample-database'
DECLARE @何分前 int = 30

SELECT 
    qs.last_execution_time AS 最後に実行された時間
    , qs.execution_count AS クエリ実行回数
    , qs.total_elapsed_time / 1000000 AS 合計実行秒
    , SUBSTRING(qt.text,qs.statement_start_offset/2 +1,   
                 (CASE WHEN qs.statement_end_offset = -1   
                       THEN LEN(CONVERT(nvarchar(max), qt.text)) * 2   
                       ELSE qs.statement_end_offset end -  
                            qs.statement_start_offset  
                 )/2  
             ) AS query_text
    , dbname = DB_NAME(qt.dbid) 
FROM sys.dm_exec_query_stats AS qs   
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE
    DB_NAME(qt.dbid) = @DB名
    and last_execution_time >= dateadd(minute, @何分前 * -1, getdate())
ORDER BY
    qs.total_elapsed_time desc
;  
```
HerokuでExpressのSessionをRedisで管理する

### 前書き

これは、本を読むのが好きだけど探すのが嫌いな僕が、適当な説明文を書いておけば誰かが勝手におすすめのものを教えてくれる「[積んでけ](https://tsundeke.me)」というサービスを作った際に学んだことを書いているものです。


# Herokuにheroku-redisを追加

コマンドでHerokuにAddonを追加

```
heroku addons:create heroku-redis:hobby-dev
```

インストール後に以下のコマンドでURLが見えているかを確認

```
heroku config:get REDIS_URL
```

# インストール

最低限必要なものだけ

```
npm install --save express
npm install --save express-session
npm install --save redis
npm install --save connect-redis
```

# 設定

必要な部分だけ

```node.js
const express = require("express");
const session = require("express-session");
const redis = require("redis");
const RedisStore = require("connect-redis")(session);
app.use(
    session({
        store: new RedisStore({
            url: process.env.REDIS_URL,
            client: redis.createClient({
                url: process.env.REDIS_URL
            })
        })
    }),
    ...
);
```

# 参考

https://github.com/velizarn/redis-demo

### 宣伝

もし興味があれば使ってくれると嬉しいです。

[積んでけ](https://tsundeke.me)

> 世界にはあなたやわたしがまだ出会っていないすばらしいものが無数に存在します。 あなたが知っている素晴らしいものは、だれかが探し続けているものかもしれません。 あなたが探し続けているものは、だれかがすでに素晴らしいと思って使っているものかもしれません。 「積んでけ」はだれもが気軽に軽い気持ちで自分が知っている素晴らしいものを教えあうサービスを目指しています。
PyPIへのアップロード＆パッケージ化を行うPowerShellスクリプトを書いた

ライブラリのアップロードはそう頻繁にあることじゃなく、ついつい手順を忘れてしまうのでスクリプトを書きました。
いちおうアップロードの直前に「本当にアップロードしても良いか？」聞くおまけ付きです。

いちおう全文英語なのでOSSのリポジトリとかにうっかり入れても安心。

```powershell:upload.ps1
Remove-Item "*.egg-info" -Recurse
Remove-Item "dist" -Recurse
Remove-Item "build" -Recurse
python setup.py sdist
python setup.py bdist_wheel
$title = "PyPI upload?"
$message = "The package was created in the `dist` folder. Can I continue uploading to PyPI?"
$tChoiceDescription = "System.Management.Automation.Host.ChoiceDescription"
$options = @(
    New-Object $tChoiceDescription ("Yes(&Y)", "Upload the library to PyPI.")
    New-Object $tChoiceDescription ("No(&N)", "Cancel the upload. The library remains in the `dist` folder.")
)
$result = $host.ui.PromptForChoice($title, $message, $options, 0)
switch ($result)
{
    0 {
      twine upload dist/*
      break
    }
    1 {
      "Cancel the upload. The library remains in the `dist` folder."
      break
    }
}
```

なお、アップロードに必要な`sdist`、`wheel`、`twine`コマンドは事前にインストール済み、PyPIアカウントの情報は`.pypirc`に記入済みであるものとします(この辺の処理がまだの人は参考記事を読んでください)。

# 参考記事

* [Pythonで作成したライブラリを、PyPIに公開/アップロードする \- Qiita](https://qiita.com/icoxfog417/items/edba14600323df6bf5e0)
* [PowerShell で選択肢メニューと、それに伴う分岐処理を簡潔に書きたい \- Qiita](https://qiita.com/yumura_s/items/274e8e49c975cce3a2ce)：結局複雑なコードにならなかったので、ここに書かれているコードは利用していません
* [Windows PowerShell Tip of the Week \| Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ff730939(v=technet.10))
【GAS】('b'+'a'+ + 'a' + 'a').toLowerCase() が「banana」と表示される

# 概要
タイトルの通りである．[こちら](https://qiita.com/okumurakengo/items/4c4c1d01fe90e827f101)の記事を拝見し，JavaScript で起こるなら Google Apps Script でも起こるのでは，と思い試してみた．

# 詳細
以下のコードを入力し，実行する．

```javascript:code.gs
function banana() {
    s = 'b' + 'a' + + 'a' + 'a';
    Logger.log(s.toLowerCase());
}
```
`Ctrl+Enter` でログを表示すると，確かに `banana` になっている．

```
[19-08-30 18:56:52:145 JST] banana
```

# 参考
- [javascript - Why is the result of ('b'+'a'+ + 'a' + 'a').toLowerCase() 'banana'? - Stack Overflow](https://stackoverflow.com/questions/57456188/why-is-the-result-of-ba-a-a-tolowercase-banana)
- [【JavaScript】('b'+'a'+ + 'a' + 'a').toLowerCase() が「banana」と表示される - Qiita](https://qiita.com/okumurakengo/items/4c4c1d01fe90e827f101)
Android Toolbarの書き方(標準、カスタム)

## 発信したいこと
久々の投稿でございます.

この記事を書くに至ったのは複数のAndroidプロジェクトを見ていて
Toolbarの実装方法が異なりどちらが実装しやすいのかなと思い投稿させていただきました。
やり方は様々あるのであくまで一つのやり方として参考にしてもらえれば幸いです！

## 環境
Mac : 10.14.3
AndroidStudio : 3.4.2
Language : Kotlin

## 実装

### カスタムのxml
Toolbarの中にゴリゴリ、レイアウトを実装しています.

```
<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar1"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary">

    <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <ImageView
                android:id="@+id/navigationImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_arrow_back_24dp"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                tools:ignore="ContentDescription"/>

        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/title"
                android:layout_marginStart="28dp"
                android:textSize="20sp"
                android:textColor="@color/white"
                app:layout_constraintTop_toTopOf="@+id/navigationImageView"
                app:layout_constraintBottom_toBottomOf="@+id/navigationImageView"
                app:layout_constraintStart_toEndOf="@+id/navigationImageView"/>

        <ImageView
                android:id="@+id/menuImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_settings_24dp"
                android:layout_marginEnd="20dp"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                tools:ignore="ContentDescription"/>

    </android.support.constraint.ConstraintLayout>

</android.support.v7.widget.Toolbar>
```

### 標準のxml
スッキリして見やすいですね!

```
<android.support.v7.widget.Toolbar
            android:id="@+id/toolbar2"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimaryDark"
            app:title="@string/title"
            app:titleTextColor="@color/white"
            app:navigationIcon="@drawable/ic_arrow_back_24dp"/>
```

### 所感

#### カスタム
- メリット  
自由自在にレイアウトできる。 iOSと同じようにして欲しい要望に答えることができる
- デメリット  
複数エンジニアが開発している場合、全画面のToolbarを同様にすることが難しい

#### 標準
- メリット  
コードを初見で理解できる
- デメリット  
特に見当たらない

## コード見たい人はココ
https://github.com/m-saeki0926/toolbar_sample_android

## 参考
https://developer.android.com/reference/android/support/v7/widget/Toolbar
よく分からないReactエラーメッセージ [メモ]

React/JSX特有のエラーメッセージは、明確になぜいけないのか教えてくれていることが少ない気がします。

#####sono1
```
does not exist on type 'JSX.IntrinsicElements'.  TS2339
```
以下のコードで怒られました。

```
render(){
return ( <test /> )
}

let test = () => { 
    return (<Grid>aa</Grid>);
}
```

なにがいけないのかさっぱりわからなかったのですが、関数コンポーネント名の最初
の文字を大文字にしたら、普通にコインパイル通りました。


#####sono2
```
Expected an assignment or function call and instead saw an expression  no-unused-expressions
```

[JSXタグ]をReturnで返していない

```
let test = () => { 
    (<Grid>aa</Grid>);
}
```
Google play consoleへデプロイする際のエラー[not compliant with the Google Play 64-bit ](ReactNative)

# エラー
Google play consoleへアプリをデプロイ（`.apk`ファイルのアップロード）の際に、下記のようなエラーが発生しました。

```
This release is not compliant with the Google Play 64-bit requirement
```

# 解決法
`android/app/build.gradle`のndk部分を下記書き換えた上で`.apk`ファイルの発行->再度、google play consoleへアップロード

```
    defaultConfig {
        applicationId "jp.co.hogehoge"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
        }
    }
```

# 参考
[Building with Android Studio or Gradle
](https://developer.android.com/distribute/best-practices/develop/64-bit#building_with_android_studio_or_gradle)