OmniAICreator/Qiita-1.07M huggingface dataset:
S3にアップロードした画像をAjaxで取得する

# やりたいこと
デバッグ等で、S3にアップロードされているかどうかをチェックした後に、
URLを差し替えて画像を表示したいというニッチなニーズに遭遇。

普通に何も考えずに実装すると
> has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

という感じに怒られる。
ちゃんとヘッダを設定して、クロスドメインを有効にしましょうという話。


## S3のCORS設定
<img width="1400" alt="s3_cors_settings.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45540/9aaea52e-258a-69a6-62a3-1a3080458593.png">

```xml

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
```

## AjaxでcrossDomainを有効にする

```javascript
    _.each($('.s3-image-debugger'), function(img, _idx) {
      var $img = $(img);
      var src = $img.attr('src');

      if (src && src.match(/s3-ap-northeast-1.amazonaws.com/)) {
        $.get(src, {crossDomain: true}).fail(function() {
          $img.attr('src', src.replace('production', 'test'));
        });
      }
    });
```

かなり急いで作ったので雑ですが、意図した挙動になりました :innocent:
SQL Server と Oracle のヒント句

## はじめに

SELECT を発行した時に、どの INDEX を利用するかは、一般的に DBMS のオプティマイザが自動で選択しますが、ヒント句を付加することで、明示的に利用する INDEX を指定することができます。

## ヒント句の例

### SQLServer

`テーブル名 WITH(INDEX(インデックス名))`

```sql
SELECT * FROM table_hoge WITH INDEX(index_hoge_01)
```
### SQLServer　でのヒント句の注意
指定した INDEX が定義されていないと SQL 発行時にエラーになります。

### Oralce

`SELECT /*+ INDEX(テーブル名 インデックス名) */`

```sql
SELECT /*+ INDEX(table_hoge index_hoge_01) */ FROM table_hoge
```

### Oracle でのヒント句の注意
テーブルをエイリアスにしている場合は、ヒント句もエイリアス名で指定する必要がある。

```sql
SELECT /*+ INDEX(t index_hoge_01) */ FROM hoge_table t
```

インデックス列に NOT NULL 制約がない場合は、理論上 NULL が引っかかる可能性があるとヒント句を指定しても無視される。


hoge_table.id な null 許可の場合


```sql:INDEXが有効
SELECT /*+ INDEX(t index_hoge_01) */ FROM hoge_table t
WHERE id = 'abc'
```

```sql:INDEXが有効
SELECT /*+ INDEX(t index_hoge_01) */ FROM hoge_table t
WHERE id IS NOT NULL
```

```sql:INDEXが有効
SELECT /*+ INDEX(t1 index_hoge_01) */ FROM hoge_table t1
inner join poge_table t2 on t1.id = t2.id
```

```sql:INDEXが無効
SELECT /*+ INDEX(t index_sample_table_01) */ FROM sample_table t
```

```sql:INDEXが無効
SELECT /*+ INDEX(t1 index_hoge_01) */ FROM hoge_table t1
left outer join poge_table t2 on t1.id = t2.id
```

## おわりに

このレベルのメモ書きをアップする際の見やすいテンプレートみたいな形式はありますかね？
Pythonで簡単なShellを実行するだけの関数

# Pythonで簡単なShellを実行するだけの関数

'ls -l'のような複数行は非対応。

```python
import subprocess

# shell実行して文字で返す
def res_cmd(cmd, char_code="utf-8"):
    return subprocess.Popen(
        cmd, stdout=subprocess.PIPE,
        shell=True).communicate()[0].decode(char_code)

cmd = 'echo -n "hello world"'
res = res_cmd(cmd)
print(res)
# hellow world
```
意思疎通をするために図を描く。下手でもいいからとにかく描く

# 要約

- 情報共有はまず図に描いて、それをお互いに見ることから始めよう
- 現場向け、マネージャ向け、経営層向けに、それぞれ１種類ずつの図を描いて多角的に観察しよう


# 本文
本日、現場の同僚とプロジェクトの状況について情報共有を行った。
そのとき、ホワイトボードに描いて、つねにボードを見ながら共有をするようした。

描いたのは主に３つ。

- アーキテクチャ図
- 組織体制図
- ステークホルダー関係図

上記の図は、自分の立ち位置に近い順番で描いた。
我々の立場はエンジニアなので、「あるべき姿をどのように実現するか」をフォーカスする。
もちろん、Whyへの言及があったほうが提案に厚みが出るが、基本的にはHowを主領域としている。

そこでアーキテクチャ図を用い、自分たちの担当領域を明確にし、どこについて話しているのかを確認するようにした。これで、「いまどこの領域の話をしているのか」についてイチイチ互いに脳内補完する必要がなくなるわけだ。絵がそこにあるのだから。

組織体制図は、組織の誰に負荷が集中しているかを共有するために描いた。
体制図の形にすると、「どのように負荷が集中しているか」のスパイラル構造が分かる。

ステークホルダー関係図は、組織のパフォーマンスを下げている要因がどこにあるかを共有するために描いた。
組織のパフォーマンスが落ちるのは情報連携がうまくいってないときなので、それはどこで発生しているのかを知るためだ。
今回は、互いに縦割の組織で周りとの課題共有がうまくいってないことが挙げられた。
「問題なのは、リーダー格の人間だけがすべてを知っていて、メンバー層まで連携されていない」という事実であった。

というわけで、**情報共有はまず図に描くことからすべてが始まるという話であった**。
chorme拡張で出現する「Refused to load the script 」の解決方法

```
Refused to load the script 'https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js' because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem: chrome-extension-resource:". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
```
これを解決するには、manifest.jsonに以下の追記をする


```manifest.json
  "content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
```
GitHubで草が生えなくて焦った話

### なにがあったか
GitHubのリポジトリにプッシュしてるのに草が生えなくて焦った。
今まではメインでbitbucketを使っており、コミット量や書き換えた行数がわかる折れ線グラフをみてほくそ笑んでいた。それが開発のモチベーションだった。
しかし、GitHubにプッシュしても草が生えなくてやる気がなくなった。

### 状況
* リポジトリ作成時のコミットはあり、作業した日のコミットがなぜか一回しかコミットしていない事になっている。
* ブランチ
    * master(メイン)
    * develop

### やったこと
検索してqiitaの記事を発見。
https://qiita.com/endo_hizumi/items/49edf021b8b9189b4f88
>
GitHubに登録されているメールアドレスの確認
Setting→ProfileのPublic profileの中のPublic email

を確認したがなんと空になっていて焦った。しかし、下の注意書きを読むと
>
You have set your email address to private. To toggle email privacy, go to email settings and uncheck "Keep my email address private."

つまり、自分はメールアドレスを非公開にしているので表示されないということになる。実際にメールアドレスを公開したら選べる様になっていた。

次にローカルのgitに登録されているメールアドレスを調べる。

```
git config user.email
```
だが表示されたのはgithubで発行されたダミーアドレスだったし、.git/logsのファイルを見てコミット履歴を確認してもダミーアドレスでコミットしていた。
参考記事とは別の原因のようだ...
悩んでいた時、今までgithubではmasterブランチに直接プッシュしていたのに、初めてブランチを分けて作業したなと思いだした。
もしからしたら、ブランチを分けたから反映されないと思い試しにマージしたら無事草が反映されました。
どうやらメインブランチのコミットが草として反映されるらしいです！
草が生えて超気持ちいい！！！
gitでmerge、conflict解消する時の基本的な流れ

1.まず現在のディレクトリで、develop（統合したい先）に移動

```shell
$git checkout develop
```


2.developがあるか確認


```shell
$git branch
```

3.developをpullする

```shell
$git pull origin develop
```
4.自分のレポジトリに移動

```shell
$git checkout myrepos
```

5.自分のレポジトリと相手(develop)のレポジトリをmerge

```shell
$git merge develop
```

6.この瞬間に、conflictがあれば、反映されているので、エディタ、IDE上で手動で変更するか、以下のコマンドを実行

自分のものを優先する時

```shell
$git checkout --ours samplefile.php(修正したいファイル名)
```

7.相手のものを優先する時

```shell
$git checkout —-theirs samplefile.php(修正したいファイル名)
```

mergeが解消したら、commitしてpushする
Amazon Linux 2でrbenvを使う


## 環境
- Amazon Linux 2

## インストール手順
```bash:install
# 0. 依存ライブラリのインストール
$ sudo yum install -y git gcc openssl-devel readline-devel zlib-devel

# 1. レポジトリをクローン
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv

# 2. .bash_profileの設定
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

# 3. シェルを再起動
$ exec $SHELL -l

# 4. プラグイン用ディレクトリ
$ mkdir -p "$(rbenv root)"/plugins

# 5. rbenv installができるように
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

# 7. 確認
$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash
```

## 使い方
```bash:usage
 # インストールできるバージョンを確認
 $ rbenv install -l
 
 # 指定バージョンのRubyをインストール
 $ rbenv install 2.5.1
 
 # グローバルのバージョン指定
 $ rbenv global 2.5.1
 
 # インストールされているバージョンを確認
 $ rbenv versions
```

## 参考
- [Amazon Linux 2にrbenvをいれる - Qiita](https://qiita.com/ryooob/items/ce3354c9f2e0f202ff89)
- [rbenv - github](https://github.com/rbenv/rbenv)
Dataprocのsqoopでavro保存しようとしたらハマって困った

# この記事について
Dataproc で sqoop を実行し、oracleからデータを引っこ抜こうとしたらエラーが出た。
そのトラブルシューティングの記録。


# 環境
- Dataprocイメージ： 1.3.16-deb9
- sqoopパッケージ： [sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz](http://ftp.jaist.ac.jp/pub/apache/sqoop/1.4.7/)
- 連携テーブルにClobタイプのカラムあり
- ファイルは avro 形式で保存したい

# Dataprocでのsqoop方法
この記事を読めば大体書いてある。
https://medium.com/google-cloud/moving-data-with-apache-sqoop-in-google-cloud-dataproc-4056b8fa2600

記事はMysqlだが、これをOracleでやる場合は以下の違いがある。

- `--jars` に上記sqoopパッケージを解凍して得たsqoop-1.4.7.jar と lib 配下の全ての jar を指定する
- `--conect` 部分をoracleドライバに変更する

しかし、タイトルの通りこれでは avro 形式での sqoop に失敗する。

# 解決方法
以下の2つのオプションを付与したところ成功した。

1. `-Dmapreduce.job.classloader=true`
    "-Dmapreduce.job.user.classpath.first=true" をつけろ！という記事はたくさんあるが、それだと以下のエラーが出て上手くいかなかった。

    ```
    Error: org.apache.avro.reflect.ReflectData.addLogicalTypeConversion(Lorg/apache/avro/Conversion;)
    ```

2. `-map-column-java Clobカラム=String`
    Clobタイプのカラムはこれを指定しないと怒られた。


# 参考
- https://stackoverflow.com/questions/41810664/sqoop-imported-failed-cannot-convert-sql-type-2005-when-trying-to-import-oracle
- https://www.linkedin.com/pulse/sqoop-import-avro-files-ashish-kumar
RE:VIEW で画像を横並びに出力する

後でまとめます。

ものすごく力技だが、embedを使ってむりやり横ならびに出力することができた。
脚注(//footnote)を画像の直後に書くとfigureの中に出力されてしまうのでfigureの外に記述する。

また、ページに対する比率に設定してある画像サイズはminipageに対する比率になる。

```
//embed[latex]{
\begin{figure}[htbp]
  \begin{center}
    \begin{tabular}{c}

    \begin{minipage}{0.5\hsize}
      \begin{center}
//}

//image[apparel][洋服工場@<fn>{inaparel}][scale=1.0]{
//}


//embed[latex]{
      \end{center}
    \end{minipage}
//}

//embed[latex]{
    \begin{minipage}{0.5\hsize}
      \begin{center}
//}
//image[food][食品工場の写真@<fn>{infood}][scale=0.5]{
//}


//embed[latex]{
      \end{center}
    \end{minipage}
//}

//embed[latex]{
\end{tabular}
 \end{center}
\end{figure}
//}
```
dep ensureでbuild.NoGoErrorが出た場合

`github.com/aws/aws-xray-sdk-go`をdepを使って取り込もうとし、READMEに従い`dep ensure`コマンドを入力したら下記エラーに出くわした。

```
$ dep ensure -add github.com/aws/aws-xray-sdk-go
Fetching sources...

Solving failure: No versions of github.com/aws/aws-xray-sdk-go met constraints:
	v0.9.4: Could not introduce github.com/aws/aws-xray-sdk-go@v0.9.4, as its subpackage github.com/aws/aws-xray-sdk-go does not contain usable Go code (*build.NoGoError).. (Package is required by (root).)
```

これは`github.com/aws/aws-xray-sdk-go`の配下に.goファイルが見つからないためエラーになっている模様。
.goファイルが入っているpackageを指定したらエラーなく取り込めた

```
$ dep ensure -add github.com/aws/aws-xray-sdk-go/xray                                                                                                   
Fetching sources...

"github.com/aws/aws-xray-sdk-go/xray" is not imported by your project, and has been temporarily added to Gopkg.lock and vendor/.
If you run "dep ensure" again before actually importing it, it will disappear from Gopkg.lock and vendor/.
```
Touch Barにウィンドウ幅を画面幅に合わせるアクションを

1. マルチモニタ環境で，ウィンドウを主モニタの横幅いっぱいにしたい。
2. それをTouch Barからできるとなお嬉しい。

ちょっと力技ですが，やってみました。JXA*をAutomatorのサービスとして動かすやつです。
*JXA: JavaScriptでAppleScriptみたいなことするやつ（←雑）

# ウィンドウを横幅いっぱいに使う。
筆者のメインモニタはFullHDモニタを縦置きしているので，横幅は1080pxです。
普通に考えると，現在のウィンドウのX座標を0に，widthを1080にすれば良さそうです。

```JavaScript:不正解のコード
var app = Application.currentApplication();
var new_bound = app.windows[0].bounds();
new_bound.x = 0;
new_bound.width = 1080;
app.windows[0].bounds = new_bound;
```
ところがどっこい，マルチモニタ環境では，どうやら「その」モニタの左端のx座標が0とは限らないようです。（仮想的に，複数のモニタを全部合わせた大きな矩形になっている？）
なので，「その」モニタの左端のx座標をどうにかして指定しなくちゃいけません。
が，それをスクリプトで取得するのは意外とめんどくさそうなのでパス。適当なウィンドウを左端に置いてx座標を調べる，というアナログな方法で調べた結果，**私の 今現在の**設定だと，お目当のモニタの左端はx=359らしいです。

ということで，これをそのまま練り込むとこんな感じ。

```JavaScript:スクリプトエディタ.app上では動くコード
var app = Application.currentApplication();
var new_bound = app.windows[0].bounds();
new_bound.x = 359; //マジックナンバー!!
new_bound.width = 1080;
app.windows[0].bounds = new_bound;
```
うーん，糞コード。

#Automatorでクイックアクション化する。

Automatorでは「クイックアクション」を作ることができます。「サービス」に登録できたりする優れもの。
そこで，「JavaScriptを実行」アクションだけのワークフローを作ります。（「ワークフローが受け取る項目」は「入力なし」でOK）
内容は，アクションのデフォルト値の`// Your script goes here`以下に上記コードをペーストすればOK…というわけでは無かったりします。
というのは，「サービス」として動作する場合，カレントアプリケーションはサービスだからなのか，アクティブなウィンドウを操作してくれません。
そこで，System Eventsを使ってfrontmostなアプリケーションを取得し，そのアプリケーションの先頭ウィンドウを操作するようにします。
結論としては，こんな感じに。

```JavaScript:"JavaScriptを実行"アクション内のスクリプト
var TARGET_X = 359; //お目当てモニタの左端x座標(手作業で取得)
var TARGET_WIDTH = 1080; //お目当てモニタの幅

function run(input, parameters) {
	// Your script goes here
	var processes = Application("System Events").processes();
	getApp: for( var i in processes ){
		if( processes[i].frontmost() ){
			var app = Application(processes[i].name());
			break getApp;
		}
	}
	
	var bound = app.windows[0].bounds();
	bound.x = TARGET_X;
	bound.width = TARGET_WIDTH;
	app.windows()[0].bounds = bound;
}
```

適当に「画面幅に合わせる.workflow」とでも名付けて，サービスとして保存します。

#Touch Barに登録する
システム環境設定.appから，「キーボード」→「キーボード」内の「Touch Barをカスタマイズ…」をクリックし，「クイックアクション」をTouch Barに追加。
<img width="1289" alt="スクリーンショット 2019-05-30 18.39.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192970/746cc305-aa0a-457a-1c6b-cc6a3f04acc2.png">
そうすると，Touch Barでこの「クイックアクション」に触れば，すぐに上記「画面幅に合わせる」を動作させられちまうんだ！
<img width="1085" alt="TouchBarショット .png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192970/abdc4a0a-ab3c-0855-1004-5f32959c464a.png">
create-react-app 3 で絶対パスインポート

# 環境
```.sh
❯ npx create-react-app --version
3.0.1
```
version 3.0以上の環境だと`src/hoge/piyo`のように絶対パスでインポートできません。
`../../..`のような地獄から逃れるためには以下の設定が必要です。

# 絶対パスインポートするために必要な設定
## 1 環境変数`NODE_PATH` を設定する
プロジェクト直下に`.env`を作成します。

``` .env
NODE_PATH="."
```

## 2 `tsconfig.json`を設定する
プロジェクト直下に`paths.json`を作成します。

```paths.json
{
  "compilerOptions": {
    "baseUrl": "."
  }
}
```

`tsconfig.json`の最後の2行を追記します。

```tsconfig.json
{
  "compilerOptions": {
     ...
  },
  "include": ["src"],
  "extends": "./paths.json"
}
```
これで`src/~`のように絶対パスでimportできます。:clap:
Node.jsのジョブキューbull使用感メモ

github: https://github.com/OptimalBits/bull
npm: https://www.npmjs.com/package/bull

## リトライ
デフォルトではリトライしない。
queueに対してではなく、jobをaddするときにオプションでattempsやbackoffを指定する。
https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queueadd

Backoffはfixed（固定）の他にexponentialもある。

```failedイベント``` はリトライの度に発火するので、
たとえばattempsを5としてずっと失敗すると5回走る。

今何回目のリトライなのかは ```job.attemptsMade``` で取得できる。
最終的に失敗したかどうかをハンドルする方法がわからない。
```completedイベント``` は成功のときにしか発火しなかった。
```errorイベント``` は全く発火しなかった。
以下のように試行回数を比較すれば一応できる。

```ts
queue.on('failed', job => {
    logger.debug(`job[${job.id}] failed ${job.attemptsMade} times`)
    if (job.attemptsMade === job.opts.attempts) {
        logger.error(`finally, failed job[[${job.id}]]`)
    }
})
```
トレンドの「ojichat」で遊びたいがためにGoを導入してみた。

おじちゃっと。発想が天才。

 [本家Github](https://github.com/greymd/ojichat) 

[はてなブックマーク - GitHub - greymd/ojichat: おじさんがLINEやメールで送ってきそうな文を生成する](https://b.hatena.ne.jp/entry/s/github.com/greymd/ojichat)

## こんなときに
* 「ojichat」をためしたい
* 「ojichat」でおじさんと遊びたい
* 「ojichat」でおじさんに名前呼ばれたい
* 「ojichat」で…(ry

* Go言語をとりあえず使ってみたい


## 手順
1. homebrewでインストール
2. パスを通す
3. .bash_profileを再読込
4. Goでhello worldしてみる。
5. ojichatをインストール
6. おじさんと遊ぼう


### 1. homebrewでインストール
```bash
brew install go
```
わりと重い。

### 2. パスを通す
```bash
export GOPATH=$HOME/go/
export PATH=$GOPATH/bin:$PATH
```

ホームフォルダ直下の
`.bash_profile`に以下を追記。


### 3. `.bash_profile`の読み込み

```bash
source .bash_profile
```

まじで忘れる。「command not found」が返ってくる原因、大抵これ。


### 4. Goでhello worldしてみる。（蛇足）
適当なディレクトリに `hello.go`というファイルを以下の内容で作る。

```go:hello.go
package main
import "fmt"

func main(){
    fmt.Printf("Hello, world\n")
}
```

ディレクトリに移動して、以下のコマンドを叩く。

```bash
go run hello.go
```
> Hello, world


### 5. ojichatをインストール

```bash
go get -u github.com/greymd/ojichat
```

これも結構重い。時間かかる。


### 6. おじさんと遊ぼう

#### ランダムに遊ぶ
```bash
ojichat
```

> りかちゃん、会社をサボるなんて、悪い子だなぁ😄😆💗冗談💕😃♥ 💗バー🍷好きかな🤔（￣ー￣?）✋❓今週の日曜日、仕事が早く終わりそうなんだけど、ご飯でもどうかな✋❓⁉😜⁉️（￣ー￣?）


#### 名前を読んでもらう
```bash
ojichat どらら
```

> ヤッホー😃✋🎵💗💕どららちゃん、元気かな😜⁉️❓今日はどんな一日だッタ（￣ー￣?）⁉そろそろご飯行こうよ🎵ご要望とかはあるのかな（笑）💗🤔😜⁉️❓

ときどき名前読んでもらえないこともある。根気よくチャレンジしよう。
PHPスクラッチでECサイト構築

## カート機能　備忘録
---
### カート機能利用の流れ
商品一覧画面　→　商品詳細画面　→　商品の個数を入力し、**カートに商品を入れる**

#### カートに必要な機能
- クライアントが選んだ商品IDの保持
- 商品数量の保持
- 複数の商品をカートに格納することができること

#### PHPで重要となる構文
スーパーグローバル変数SESSIONの利用
→　クライアントが選んだ**商品ID**と**商品数量**を保持するために**多次元配列**をSESSIONに保存する

####  解説の流れ
1.商品IDの受け渡し
2.多次元配列をSESSIONに格納
3.var_dumpを利用した出力の確認
4.カートに商品を複数保持する

##### 1.商品一覧画面(product_list.php)→商品詳細画面(product_detail.php)における**商品ID**の受け渡し
```php:product_list.php
<form action = "product_detail.php" method = "post">
 <input type = "submit" value = "詳細" />
 <input type = "hidden" name = "id" value = "<?php echo $val['id'];?>">
</form>
```
```php:product_detail.php
$id = $_POST['id'];
```

##### 2.多次元配列をSESSIONに格納
下記のように記述することで、商品IDと商品個数を多次元配列でSESSIONに格納することができる

```php:product_detail.php
$_SESSION['cart'][$id]=array(
  'id'=>$_POST['id'],
  'number'=>$_POST['num'],  //$_POST['num']はクライアントが選んだ商品数量
);
```

##### 3.var_dumpを利用した出力の確認
```
var_dump($_SESSION['cart']);
```
出力結果

```
array(1) { [1]=> array(2) { ["id"]=> string(1) "1" ["number"]=> string(1) "5" } }
```
この出力結果はSESSION['cart']に商品IDが１の商品が5個挿入されたことを表している

##### 4.カートに商品を複数保持する
if文でカート内に既に商品が格納されているかどうか判断し、商品が存在すれば商品個数を足し、商品が存在しなければ、SESSIONに商品を格納するというプログラムの内容になっている

```php:product_detail.php
if(isset($_SESSION['cart'][$id])){
    $_SESSION['cart'][$id]['number'] +=$_POST['num'];
    header('Location:product_list.php');exit();
  }else{
    $_SESSION['cart'][$id]=array(
      'id'=>$_POST['id'],
      'number'=>$_POST['num'],
    );
    header('Location:product_list.php');exit();
  }
```
出力結果

```
array(3) {
  [3]=> array(2) { ["id"]=> string(1) "3" ["number"]=> int(6) }
  [1]=> array(2) { ["id"]=> string(1) "1" ["number"]=> string(1) "3" }
  [2]=> array(2) { ["id"]=> string(1) "2" ["number"]=> string(1) "4" }
 }
```
カートに商品を複数格納することが可能になった。
Githubでブランチ保護設定した時の作業メモ

## 概要

ブランチの運用周りの整理をすることになって,
今まであんまり意識してなかったので,メモを残しておく


## 手順
### ブランチ保護の設定画面を開く

1. リポジトリトップの`Settings`
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/95dfcef9-cfdc-00b1-fa65-0f64810afaf3.png)
1. `Settings`のメニューから`Branches`
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/a88d6cd7-8289-f3c4-1596-a6de67c68cf1.png)
1. `Branch protection rules`の `Add rules`
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/756356a8-bcbb-82fa-8179-e49b5b34fcb7.png)
  
### 設定画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/4f37d102-b5cd-71c4-066b-d9244aebe929.png)

#### Branch name parttern

赤枠の部分 `Branch name pattern`...あれ?
参考にした記事を見るとブランチ選択してぽちぽちって感じだったのに
最近変わったっぽい

パターンマッチ使えそう....!!(期待大)

[公式ドキュメント](https://help.github.com/en/articles/configuring-protected-branches)
やっぱり使えるみたい🤪

<font color="red">**※ここで `feature/*` みたいに指定すると作業ブランチすらpushできなくなるので注意**</font>

#### Rule settings
##### Protect matching branches

パターンに当てはまるブランチ名を強制pushや,削除されないように保護してくれる
※この設定は必ず入ります

##### Require pull request reviews before merging

パターンにマッチするブランチに対してマージする前に,プルリクエストでレビューを受けることを必須にする設定。
この設定を入れるとプルリクが承認(Approve)されるまではマージできなくなる

またチェックを入れると以下のように項目が展開される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/a9314c9c-b74d-6d67-507c-b0a892e4820a.png)

- Required approving reviews
    - approveの最低限の数を設定する(例:2に設定したら最低2人に承認を得る必要がある)
- Dismiss stale pull request approvals when new commits are pushed
    - 承認後に新たなcommitがpushされた場合は承認が自動的に取り消される
- Require review from Code Owners
    - コードオーナーのレビューを必須にする設定=>[参考資料](https://qiita.com/FumiyaShibusawa/items/c7a3ff4d0793ca2d281f)
- Restrict who can dismiss pull request reviews
    - プルリクのレビューを却下できる人,チームを指定できる

##### Require status checks to pass before merging

CIなどのサービスを連携している場合の設定。
CIなどの実行が成功しないとマージできないようにできる

チェックを入れると以下のように展開する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/66cfc9dc-03c2-2953-8105-b8381884faf0.png)

- Require branches to be up to date before merging
    - リポジトリに何かしらのサービスを連携させているとここに表示され,サービスごとに保護の条件に含めるか選べる


##### Require signed commits

署名済みコミットを必須にする設定
署名がないとマージすることができなくなる

##### Include administrators

管理者もこのブランチ保護の制限の対象に含めるか
チェックを入れると管理者も同様にマージできなくなります

##### Restrict who can push to matching branches

パターンにマッチしたブランチにプッシュできる人を制限できる。

チェックを入れると以下のように展開する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/07b8b1d7-6375-3ddf-cc51-d08d4afdcb47.png)

展開されたフォームから許可する人,またはチーム名を入力して選択する



## 設定値
結果↓のような感じにまとまりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133737/2a3bca41-e7c1-764f-5e27-0a4ba2063acf.png)

ブランチのパターン指定についてはブランチの運用次第で変わってくるのでどれがベストプラクティスとかなさそうですが↓を設定しました

- `master` もしくは `main`
    - まぁこれは絶対
- `release/*`
    - リリースブランチ系も当然
- `develop/*`
    - developブランチも同じ設定で運用上保護しました


## 参考資料

[[GitHub] ブランチの保護設定を活用しよう 【レビューが通るまでマージさせんぞ】](https://dev.classmethod.jp/tool/github/protect-branch/)

### おわり
Dockerfileを楽に作りたい（imageから自動生成したい） [修正版]

# はじめに
以前，下記の記事を書きました．
https://qiita.com/RyodoTanaka/items/6f8da0749cbd0afa0ddd

が，うまく行かないことがわかり修正版を作りました．
修正と言っても，もはや作り変えです．

# やりたいこと
Dockerfileを楽に作りたいなぁと思った時，どうやりますか？
**Dockerfileを任意のimageから自動生成できたら嬉しいですよね！**
私は下のような手順で出来るといいなと思ってます．

1. Docker image の実行
2. 環境構築
3. imageからDockerfileを作成

というわけでその手順を記しておきます．

# 制約
後で仕組みの説明をしますが，下記のような制約があります．

- Bashじゃないとダメ
- コマンド総数が2000行を超える場合は，予め`.bash_history`の行数制限を解除する必要アリ
- 環境構築時にエラーが出るようなコマンドを自動認識することは不可能

です．
ここに上げてる以外のこともあるかもしれません...
その場合は是非issue等を立ててください！
一緒に改善していきたいです！

# 仕組み
前回の記事では`docker history`を使っていましたが，
これでは image にログインした後のコマンドは全く追えませんでした．
なので，`bash_history`を使って環境構築部分を引っ張ってきてやろう！
で，引っ張ってきたやつを無理やり`RUN`で全部回してやろう！
というのが仕組みです．
ホントそれだけです．

# Dockerfileが出来るまでの流れ
#### 1. Docker image の実行
例えば，`Ubuntu 16.04`をベースにしたいなと思ったとき，まずはimageを引っ張ってきますよね．

```bash
$ docker pull <image repository name> 
```

でもってPullが完了したら，そいつを実行します．

```bash
$ docker run -it <image name>
```

### 2. 環境構築
実行してるcontainer内で色々環境構築します．
具体的に何をするかは皆様お好きに！
環境構築が終わったら`exit`コマンドとか使って終了します．
この時，**予めコマンド数が増えそうだとわかっているなら，
bash_historyの保存制限を解除してください！！**
やり方はこちらが参考になると思います．
https://stackoverflow.com/a/12234989

### 3. containerからimageを作成する
まずはcontainer 情報を下記コマンドで確認します．
ここからDockerfileを作りたいcontainer IDか名前を取得します．

```bash
$ docker ps -a
```

そしたら，下記コマンドで希望のcontainerを任意の名前のimageにします．

```bash
$ docker container commit <container ID> <image name>
```
一応作成し終わったら，下記コマンドでimageがちゃんと作られてるか確認します．

```bash
$ docker images
```

#### 4. imageからDockerfileを作成
本記事のミソです．
以前の投稿ではワンライナーで出来るとかどうとか言ってましたが，
そもそも仕組みが変わったんでスクリプトを書きました．
`dfimage`というコマンドを使えるようにしてます．
スクリプトは下記リポジトリに置いてあります．
https://github.com/RyodoTanaka/.bash_extend/blob/master/dfimage.bash
こいつをで読み込んでやれば，

```bash
$ dfimage <image name>
```

とするだけで，Dockerfileを標準出力に出力してくれます．
なのでUNIX系使いの方であれば

```bash
$ dfimage <image name> > Dockerfile
```

とすれば自動でDockerfileが出来上がります！
`.bashrc`とかで読み込むようにしておくと便利です．

##### 5. 出来上がったDockerfileの手直し
最初の方にも書いたように，余分なコマンド等の認識はしていません．
（ただし，`ls`コマンドだけは除外するようにしてます）
なので，ご自身で`docker build`とかされながらちゃんと動作するように手直ししてください．

# まとめ
というわけで，ようやくそれっぽいものができました．
色々不完全なので，皆様のご指摘をいただけると嬉しいです！！
【Azure】Azure PowerShell をローカル環境にインストールする方法

#概要
Azure PowerShellをローカル環境にインストールする方法

#必要条件
- PowerShell 5.1 以上 (Windows)
- PowerShell Core 6.x 以上 (macOS, Linux)

PowerShellのインストールは[こちら](https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-windows-powershell?view=powershell-6)
PowerShell Coreのインストールは[こちら](https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell?view=powershell-6#powershell-core)

#手順
PowerShell上で以下のコマンドを実行する．

```shell:PowerShell
Install-Module -Name Az -AllowClobber
```

カレントユーザーにのみインストールしたい場合は以下のコマンドを実行する．

```shell:PowerShell
Install-Module -Name Az -AllowClobber -Scope CurrentUser
```

以下の出力が表示されるので`y`をタイプする．

```shell:Output
Untrusted repository
You are installing the modules from an untrusted repository. If you 
trust this repository, change its InstallationPolicy value by running 
the Set-PSRepository cmdlet. Are you sure you want to install the 
modules from 'PSGallery'?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help 
(default is "N"):
```

#サインイン
以下のコマンドでサインインする.

```shell:PowerShell
Connect-AzAccount
```

以下のアウトプットのURLをブラウザで開いて，コードを入力する．

```:Output
WARNING: To sign in, use a web browser to open the page 
https://microsoft.com/devicelogin and enter the <code> to authenticate. 
```
<img width="454" alt="スクリーンショット 2019-05-30 18.40.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/776a0efc-567b-a2e2-8428-cff01a9a5433.png">

#アップデート
以下のコマンドでアップデートする．

```shell:PowerShell
Install-Module -Name Az -AllowClobber -Force
```

#参考
[Azure 公式ドキュメント](https://docs.microsoft.com/ja-jp/powershell/azure/install-az-ps?view=azps-2.1.0)
０から始め、Java Silver取得した話

#はじめに
アンニョンハセヨ~(୨୧ᵕ̤ᴗᵕ̤)　チオンです。
今日はJavaSilver取得するまでの話を皆さんと共有したいと思います。
それではスタート～～

#勉強前のスペック
・未経験で2カ月前IT会社に入社し、実務経験なし。
・Javaに関してはオブジェクト指向の言語だという理解程度
・Pythonを独学で1ヶ月間勉強

#勉強期間

・勉強期間：2019年3月中旬~2019年5月末(約2カ月半)
・勉強時間：平日　0.5~1時間、　土日　3~6時間
・受験日：2019年5月30日

#勉強方法
###・開始~1カ月目(黒本3周)
はじめはJavaの知識がなく、黒本の1章解くのも大変だったので、解説を理解することからやりました。1章から9章まで3周読みながら理解できない概念や問題はチェックして今後みれるようにまとめました。
その後、10章の模擬問題を解いてみました。当時、10章の正解率が44%で低くて少しショック。
###・2カ月目(黒本2周)
Java Silver問題の傾向を理解し、11章の模擬問題を解いてみました。11章の正解率が66%
合格できそうな気分で嬉しく、間違った問題を中心に黒本を2周読みました。
###・試験前の2週間(黒本1周、ネット問題)
いまだによく間違う問題や弱い概念を把握してノートに整理してメモして勉強しました。
また、試験前の1週間はネットにあるJava silver問題を解いてみたりしながら勉強しました。

Oracle Javasilver サンプル問題👇
http://www.oracle.com/jp/education/certification/ocjp-silver-se8-3494542-ja.html

#試験結果
###正解率90%で合格しました。“(⌯¤̴̶̷̀ω¤̴̶̷́)✧
本番の問題は黒本の問題とすごく似ていて、初めてみる問題は2問程度。
黒本の復習が大事だと思いました。




#感想
資格の勉強を通じてJavaの理解もできたので、良かったです。現場でJava に携わりたい。Javaで何か作りたいというモチベーションがUPしました！
何も分からなかった私も資格を取得できたので、皆さんもできると思います！応援します。

※日本語で少し不自然な表現がありましたら、すみません。日本語ももっと勉強します★
Unityを使ったMultiple APKのやりかた

# Multiple APK とは

[App Bundle](https://support.google.com/googleplay/android-developer/answer/9006925)より昔にあったやりかたで、
API levelやCPU architectureなどでインストールするAPKを切り替えることができる機能のこと。

- https://developer.android.com/google/play/publishing/multiple-apks

基本的にはApp Bundleで十分なので使用する必要はない。
しかし、プラグインの事情など特別な理由によりAPKファイルを切り替えたい時に使用できる。

# 前提知識

Google Play Consoleにアップロードするため、リリースのやり方は別途調べておく必要がある。
- 私は https://qiita.com/tsucchi13/items/11b3d9c8f99ceedb4b47 を参照しました。

# 手順

1. Player Settings - Android - Publishing Settings を設定しておく
2. Player Settings - Android - Configuration を変更する
3. Player Settings - Android - Identification - Bundle Version Code を被らないように変更する
    - 上位の桁にAPI Levelを埋め込むなど他のAPKファイルと被らない番号であればよい(桁数も含め自由に設定できる)
        - https://www.isus.jp/smartphones/google-play-supports-cpu-architecture-filtering-for-multiple-apk/
4. apkを出力し、必要な分だけ2に戻る
5. Google Play ConsoleにすべてのAPKファイルをそれぞれアップロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47699/72cab550-72b6-3ae5-f527-a355d425b9da.png)
6. 公開する

# 要点

インストール時に使用されるAPKファイルは以下のように選択されるようなので、そこで制御を行う。
事実上、複数のAPKファイルさえ用意できればBundle Version Codeを管理できさえすれば、他には何もする必要はない。
(パックするツールがあるのかと探したが、その必要がなかった)

1. 該当の端末で使用できるAPKファイルをフィルタリングする
    - API levelやCPU architectureなどでフィルタリングされる
2. フィルタリングされたものの中でBundle Version Codeが一番大きいものが採用される
    - そのため、下位互換のあるもの(ARM64がARMv7のものを実行できるなど)については優先するものほど大きい値にする必要がある
【Java】継承とインターフェース実装を同時に行った場合のメソッド呼び出しのエラー

Java研修中に起こったエラーについての覚え書き。

#コードおよびコンパイルエラー
```java:Sample.java
abstract class A{
    abstract void aMethod();
} 

interface B{
    void bMethod();
}

//A継承
class OnlyA extends A{
    public void aMethod(){};
}

//A継承・B実装
class AB extends A implements B{
    public void aMethod(){};
    
    public void bMethod(){};
}

public class Main {
    public static void main(String[] args){
        A[] a = new A[]{new OnlyA(), new AB()};

        //抽象クラスメソッド呼び出し
        a[0].aMethod();
        a[1].aMethod();

        //インターフェースメソッド呼び出し
        a[1].bMethod();
    }
}

/*
Main.java:26: error: cannot find symbol
        a[1].bMethod();
            ^
  symbol:   method bMethod()
  location: class A
*/

```
呼び出せませんでした。

#解決法
```java:Main.java
public class Main {
    public static void main(String[] args){
        A var1  = new AB();
        B var2  = new AB();
        AB var3 = new AB();
        
        var1.bMethod(); //これはダメ
        var2.bMethod(); //これはオッケー
        var3.bMethod(); //これもオッケー
    }
}

```
この場合、インターフェース型で宣言するかそれを実装した型で宣言しないとダメみたいですね。

インスタンス`class AB extends A implements B`のメソッドに直接アクセスしてるもんだと思ってたけど`class A`で宣言してるからまずそっちにアクセスしてるのかな？

継承だけ・実装だけの場合、親子両方定義するので`cannot find symbol`が出ることはまあないんですが、このように継承と実装を同時に行うと注意しないといけないですね。
（あまりインターフェースを使ったことがないのがバレる形になった）

もっと勉強が必要と感じた次第です。
Laravel Excel で .xlsx ファイル出力時にデフォルトのフォントを変更する方法

Laravel Excel https://laravel-excel.com/ を使って、 .xlsx ファイルを出力する際にファイル全体のデフォルトのフォント変更する方法。

なお、 Laravel Excel のバージョンは 3.1 です。

## 結論: registerEvents() を使って、 $event->sheet->getDelegate()->getParent()->getDefaultStyle()->getFont()->setName('ＭＳ Ｐゴシック'); とかする

書いたとおりなのですが、 `registerEvents()` を使って、 `$event->sheet->getDelegate()->getParent()->getDefaultStyle()->getFont()->setName('ＭＳ Ｐゴシック');` などとします。

## どうやるのか

https://docs.laravel-excel.com/3.1/exports/

このチュートリアルに習って、 `UsersExport` を生成すると以下のファイルが生成されます。

`app/Exports/UserExport.php`

で、そのファイルの中は、以下のようになっているはずです。

```app/Exports/UserExport.php
<?php

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;

class UsersExport implements FromCollection
{
    /**
    * @return \Illuminate\Support\Collection
    */
    public function collection()
    {
        return User::all();
    }
}

```

このクラスに `Maatwebsite\Excel\Concerns\WithEvents` を implements して、要求される `public function registerEvents(): array;` を実装します。

https://docs.laravel-excel.com/3.1/architecture/#lifecycle や https://docs.laravel-excel.com/3.1/exports/extending.html#events を参照のこと。

```app/Exports/UserExport.php
<?php

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithEvents;

class UsersExport implements FromCollection, WithEvents
{
    /**
    * @return \Illuminate\Support\Collection
    */
    public function collection()
    {
        return User::all();
    }

    public function registerEvents(): array
    {
        return [
            AfterSheet::class => function (AfterSheet $event) {
                $event->sheet->getDelegate()->getParent()->getDefaultStyle()->getFont()->setName('ＭＳ Ｐゴシック');
            },
        ];
    }
}

```

で、上記のように、 `PhpSpreadsheet` のインスタンスを引っ張り出してきて、 最終的に `setName();` します。

フォントサイズを変更したいときは、同様に `setSize();` です。

PhpSpreadsheet で設定できるやつは、この方法で設定できるはず。 https://phpspreadsheet.readthedocs.io/en/latest/
テストクラスにApex電子メール送信の検証方法

テストメソッドが実行完了すると、トランザクションは自動的にロールバックされます。
テストクラスからApexメール送信機能を呼び出して、実際に送信しないことです。

テストクラスに [Limits.getEmailInvocations](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_limits.htm) を使用してApex電子メール送信されるかどうかを確認できます。

```java:Apex電子メール送信機能

public with sharing class EmailUtility {
    public static void sendPlainTextEmail(List<String> toAddresses, String subject, String body) {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.settoAddresses(toAddresses);
        mail.setSubject(subject);
        mail.setPlainTextBody(body);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
}
```

```java:テストクラス（Apex電子メール送信確認）

@isTest
private class EmailUtilityTest {
    @isTest
    static void testEmailUtility() {
        Test.StartTest();
        
        EmailUtility.sendPlainTextEmail(new List<String>{'test@test.com'}, 'Unit Test X', 'Unit Test');
        
        Test.stopTest();
        
        // Apex電子メール送信検証
        System.assertEquals(1, Limits.getEmailInvocations());
    }
}
```
Create an argo workflow(custom resource) with Javascript Kubernetes Client

# Introduction

Describes how to create [argo workflow](https://github.com/argoproj/argo) (Custom Resource)  with [Javascript Kubernetes Client](https://github.com/kubernetes-client/javascript).
I saw the [kubernetes-client/javascript/issues#144](https://github.com/kubernetes-client/javascript/issues/144),but I felt it did not explain enough, so I will share it here.


# How to

I explain using [argo](https://github.com/argoproj/argo).
I don't explain KubeConfig etc. because  it is not related to custom resource.

If you need further explanation, please see the following document.
- https://github.com/kubernetes-client/javascript/blob/master/README.md

```javascript
  let kc = new k8s.KubeConfig();
  kc.loadFromOptions(kubeConfig);
  let kc = await k8sCli.getClient();
  let k8sApi = await kc.makeApiClient(k8s.Custom_objectsApi); //NOTE.1
  let yaml = await readManifestFile(workflow.file);

  // NOTE.2
  k8sApi.createNamespacedCustomObject('argoproj.io', 'v1alpha1', 'default' , 'workflows', yaml).then((res) => {
      // any.
  }).catch((e) => {
      // any.
  });
```

## NOTE.1 Use Custom_objectsApi

```
kc.makeApiClient(k8s.Custom_objectsApi)
```

Use `Custom_objectsApi`as an argument for makeApiClient.
you can call createNamespacedCustomObject which allows you to specify the custom resource group and version.

## NOTE.2 createNamespacedCustomObject

```javascript

  k8sApi.createNamespacedCustomObject('argoproj.io', 'v1alpha1', 'default' , 'workflows', yaml).then((res) => {
      // any.
  }).catch((e) => {
      // any.
  });
```

The arguments for createNamespacedCustomObject can be understood by checking the contents of crd.

```shell
$ kubectl get  crd workflows.argoproj.io  -o json |jq -r ".spec"
{
  "conversion": {
    "strategy": "None"
  },
  "group": "argoproj.io",  # ★group
  "names": {
    "kind": "Workflow",  
    "listKind": "WorkflowList",
    "plural": "workflows",   # ★plural
    "shortNames": [
      "wf"
    ],
    "singular": "workflow"
  },
  "scope": "Namespaced",
  "version": "v1alpha1",    # ★version
  "versions": [
    {
      "name": "v1alpha1",
      "served": true,
      "storage": true
    }
  ]
}
$
```

# Refernece
- https://github.com/kubernetes-client/javascript/issues/144
- https://github.com/kubernetes-client/javascript/blob/master/README.md
Minecraft Skript 応用編 Part.3 タイマー

#タイマーを作ってみる。
```:timer.sk
command /timer <text> [<int>]:
	trigger:
		if arg-1 is "start":
			if arg-2 is set:
				set {timer.time} to arg-2
				set {timer.status} to true 
				stop
			else:
				set {timer.time} to 500
				set {timer.status} to true 
				stop
		if arg-1 is "set":
			if arg-2 is set:
				set {timer.time} to arg-2
				send "&5タイマーの時間を%arg-2%に変えました。" to player 
				stop
			else:
				send "&c時間を指定してください。" to player
				stop
			stop 
		
every seconds:
	if {timer.status} is true:
		loop all players:
			set action bar of loop-player to "残り時間 : %{timer.time}% 秒"
	remove 1 from {timer.time}
```
それでは少しずつ説明しましょう。

まず変数の紹介です。

```:変数一覧
{timer.status} == タイマーの状態（True/False）
{timer.time} ==== タイマーの時間
```
#argumentを無視してみる・・・
まずコマンドです。
`command /timer <text> [<int>]:`
このコードは初めて見るのではないでしょうか？

これはargumentを２つ用意して、２個目のargumentを`[]`で囲んだものになります。

`[]`で囲むと何ができるのかといいますと、
コマンドのargumentを無視できるのです。

？？？

となった方が多いのではないでしょうか？
わたくしもそうなっていますｗｗ

まあ、これに関してはコマンド実行時の書き方を見てもらえばわかると思います。

`/tp A B`と実行するとAの場所にBが行くというコマンドですよね？
ですが、`/tp A`と実行すれば、実行したプレイヤーがAの場所に行くというコマンドです。

すると、argumentは２つの時と１つの時があるわけです。

ですが、カスタムコマンドを作るときに`<～～～>`だけで書いているとargumentを用意した分、argumentを書かないと「実行できませんよ」というシステムエラーを吐くと思います。

ですが、そのargumentを`[]`で囲んであげると、囲んだargumentをなかったものと扱ってもあるものと扱ってもいいようになるんです。
※argumentは常に左から順に１、２、３、４、５・・・・となっています。

`/timer start`コマンド・・・

```:timer.sk
=======================
            if arg-2 is set:
                set {timer.time} to arg-2
                set {timer.status} to true 
                stop
            else:
                set {timer.time} to 500
                set {timer.status} to true 
                stop
=======================
```
まあ、これはもし、`arg-2`が埋まっていればそれを開始時のタイマー時間にセット、埋まっていなければ開始時のタイマー時間を５００秒にセットするというコードですね。

`/timer set`コマンド・・・

```:timer.sk
=======================
			if arg-2 is set:
				set {timer.time} to arg-2
				send "&5タイマーの時間を%arg-2%に変えました。" to player 
				stop
			else:
				send "&c時間を指定してください。" to player
				stop
			stop 
=======================
```
これはタイマー時間を途中変更できるものです。
このコマンド、タイマー実行中じゃなくても実行可能ですが、タイマー開始時に時間を変更する必要があるので使っても意味がないといったことになります。

これに関しては少し弄っただけでどうにかできますが、
このコードを見て、何をしてるんだい？となってる方（汚いコードだな・・・とか以外）は、たぶんどうしようもないかと・・・

#最後に・・・
これまでのページを見てきた人は、「あれ？`Loop`でやったらだめなの？なんで`every seconds`なの？」と思ってる方がいるかもしれません。

まあ、`every seconds`なのは俺の好み。
`while`とかでも問題ない・・・

でも`Loop`はおやめなさい・・・ｗ

詳しくはまたの機会に・・・

次は[コチラ](https://qiita.com/meoto2408/items/9feca3ab34e986da8054)

前は[コチラ](https://qiita.com/meoto2408/items/841eec0ae4ffb09899f3)
WPFアプリでタッチの波紋を非表示にする

###環境
Windows10 1809

###Windowsの設定で波紋を非表示にする
[設定]-[簡単操作]- 左サイドメニュー[カーソルとポインターのサイズ]
「タッチのフィードバックを変更する」を「オフ」にする

この方法だと独自で作ったアプリでは破門が消えない。

###アプリから波紋を非表示にする
```
Stylus.SetIsTouchFeedbackEnabled(this, false);
Stylus.SetIsTapFeedbackEnabled(this, false);
Stylus.SetIsPressAndHoldEnabled(this, false);
```

これで消えるんだけども、全画面一気にできる方法ないかなー
絶対に_idを秘匿したい俺 v.s. 絶対に_idを秘匿させたくないTypeORM - mongodb編

## 闘技場

- Nest.js
- TypeORM
- mongodb (AWS DocumentDB)
- Docker

---

## チャレンジャー紹介

絶対に秘匿したい俺

- 秘匿したいレベル100
- フロントに `フィールド名が_id` かつ `mongodb固有のHexString` が露出することで一族が滅びた過去を持つ孤高の戦士
- そもそも_idを別の名前で利用したかった（ライブラリラッパーでもいい）

絶対に秘匿させたくないmongodbおよびTypeORM

- 秘匿したくないレベル100
- 素晴らしいObjectIDな仕組みをもって高橋一族を滅びした魔女の末裔
- どうあがいても _id で保持してしまう

---

## 結果

**絶対に秘匿したい俺の勝利**

- 保存時とかは id -> _idをするのは我慢した
- class-transformerの仕組みを活用

## ダイジェスト

ここからはダイジェストでお送りいたします。

---

### classToPlain()を駆使して加工した俺

```ts:SomeEntity.ts
import { Entity, ObjectIdColumn } from 'typeorm';
import { ObjectId } from 'mongodb';

@Entity()
export class SomeEntity() {
  @ObjectIdColumn()
  @Exclude()
  _id?: ObjectId;

  @Expose()
  public get id() {
    return this._id ? this._id.toHexString() : undefined;
  }
}
```

これをclass-transformerの `classToPlain()` したあとでレスポンスを返すことで無事勝利

解説の山田さん「classToPlain()されたときの挙動を `@Expose()` `@Exclude()` の両呪文をうまくつかって隠蔽していますね」

@Exclude(): classToPlain() したときにフィールドごと吹っ飛ばす呪文
@Expose(): classToPlain() したときにフィールドと値を付け足す呪文

---

### classToPlain()をインターセプトした俺

```ts:class-to-plain.interceptor.ts
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { classToPlain } from 'class-transformer';

@Injectable()
export class ClassToPlainInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(map(data => classToPlain(data)));
  }
}
```

---

解説の山田さん「Controllerでいちいち `return classToPlain()` したくなかったことが伺えますね。インターセプターがうまく機能しているように見えます」
Javascript　配列の最大値と最小値を求める

何度かいても忘れるやつ
MAX/MINを求めたい配列`list`があるとして

```javascript:min.js
const Min = list.reduce((a,b)=>a<b?a:b)
```

```javascript:max.js
const max = list.reduce((a,b)=>a>b?a:b)
```
HTML３日目

#HTMLステップアップ
#table
```
	  <table border="1">
		  <tr>　--- tabel row
			  <th>姓</th>  --- table header
			  <th>名</th>
		  </tr>
		  <tr>
			  <td>田中</td> --- table data
			  <td>花子</td>
		  </tr>
		  <tr>
			  <td>山田</td> --- table data
			  <td>太郎</td>
		  </tr>
	  </table>
```

## thead, tbody, tfoot

単なる意味付け。あってもなくても、何も変わらない。

```
	  <table border="1">
		  <thead>
			  <tr>
				  <th>ヘッダー1</th>
				  <th>ヘッダー2</th>
			  </tr>
		  </tread>
		  <tbody>
			  <tr>
				  <td>データ1</td>
				  <td>データ2</td>
			  </tr>
		  </tbody>
		  <tfoot>
			  <tr>
				  <td>フッター1</td>
				  <td>フッター2</td>
			  </tr>
		  </tfoot>
	  </table>
```


##フォーム
ユーザーがwebページからサーバーにデータを送信するためのもの

```
<form action="#", method="post">
<form>
```
- action → データをどこに送信するか。送信された情報を処理するプログラムのURL
- method → フォームを送信する際にブラウザーが使用するHTTPリクエストメソッド（get or post）
    - head
    - get
    - post
    - put
    - delete
    - connect
    - options
    - trace
    - patch


##少し詳しく
- get　→　サーバーからデータを取得したいときに使う
- post　→　サーバーへデータを送信したいと気に使う

##input要素
- データを入力するための要素
- type属性を変えることで、様々な入力フォームになる。

```
<input type="text">　type="ここにタイプ属性を入力"
```
[input属性紹介ページはこちら](https://developer.mozilla.org/ja/docs/Web/HTML/Element/Input)

#実際のやつ
```
		<form action="#" method="post">
			<input type="text" name="username" placeholder="ユーザーネーム">
			<input type="password" name="password" placeholder="パスワード">
			<input type="submit" value="ログイン">
		</form>
```

- name: サーバー側がwebページから送られてきたデータを識別するためにつける
- placeholder: フォーム内にデフォルトで表示される文字列
- value: submitボタンに表示される名称

#いろいろ纏めてご紹介

セレクトフォーム

```
<select name="prefecture"> valueがサーバー側に送られるっぽい
  <option value="" selected>選択してください</option>
  <option value="hokkaido">北海道</option>
  <option value="tohoku">東北</option>
  <option value="kanto">関東</option>
  <option value="chubu">中部</option>
  <option value="kinki">近畿</option>
  <option value="chugoku">中国</option>
  <option value="sikoku">四国</option>
  <option value="kyusyu">九州</option>
</select>
```

ラジオボタン　(nameで一括りのラジオボタン群として判断)

```
					<th>性別</th>
					<td>
						<input type="radio" name="gender" value="male" checked>男性
						<input type="radio" name="gender" value="female">女性
```

可変長のテキストフィールド

```
					<th>お問い合わせ内容</th>
					<td>
						<textarea name="contents"></textarea>
					</td>
					</td>
```

チェックボタン

```
					<th>プライバシーポリシーに同意する</th>
					<td>
						<input type="checkbox" name="pravacy" value="1">同意する
					</td>
```
Qiitaに画像をアップロードできなくなった話

![Doge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403350/7367de48-9c14-02b8-70f8-38e7a9ae3d03.png)

　殺伐とした記事にDogeが！！
<br/>
　どうも、みやゆーです。今de:codeに行ってきた記事を書いてたんですが、写真を大量にぶち込もうとしていた結果、途中から

```
![error]()
```
　えぇ...さっきまで元気に動いてたやん...急に何...
<br/>
　どうやら、**1件も記事を投稿してないと、アップロードできる写真のサイズは合計2MBまで**らしく、**投稿すると100MB/月に増える**そうです。
<br/>
　ということで、記事を投稿してみました。**これです**。

　これでサイズは増えたのか確認してみます。

　みやゆーでした。
MacでPythonからC/C++を呼ぶ

初投稿です。最近要望があってPython触ってみたけど、遅い。でもPythonで書かなきゃいけないときに「C呼んでしまえばよくね！？」ってなっていろいろ調べてみた。でも他の人が書いた記事の通りにやってもうまくいかなかった。参照か何かが間違ってたのかなぁって感じだったが、強引に動かしたら動いたのでメモ。

#概要
**Boost.Python**というやつを使えばいいらしい。ライブラリを参照するのがうまくいかなかったので、**一つのディレクトリ内に全部入れて**動かした。

#環境
macOS 10.13.6
Python 3.7
BoostPython 1.68.0

#必要なものを用意する
このプログラムを*実行するディレクトリ*を用意した。どこでもいいと思うが、僕は`~/Python/BoostPythonTest/`にした。ここに以下のものを用意する。

- libboost_python37.dylib
- libpython3.7.dylib
- C/C++ソース
- Pythonソース

##libboost_python37.dylib
以下でBoost.Pythonをインストールする。[^1]

```shell
% brew install boost-python3
```
インストールしたら`/usr/local/Cellar/boost-python3/1.68.0/lib/libboost_python37.dylib`があるはずなので、これを*実行するディレクトリ*にコピーする。

##libpython3.7.dylib
Pythonをインストールしておく。[^1]

```
% brew install python3
```

`/usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Python`を*実行するディレクトリ*にコピーして、`libpython3.7.dylib`という名前に変更する。


##C/C++ソース
テスト用に`hello.cpp`っていうソースを用意した。

```cpp:hello.cpp
#include <boost/python.hpp>
#include <stdio.h>

char greet(int x){
    printf("printHELLO!!\n");
    return '0' + x + 1;
}

char const* fine(){
    return "How are you?";
}

BOOST_PYTHON_MODULE(hello){
  using namespace boost::python;
    def("greet", greet);
    def("fine", fine);
}
```

##Pythonソース
テスト用に`test.py`っていうソースを用意した。

```python:test.py
import hello
x = hello.greet(2)
print(x)
y = hello.file()
print(y)
```

#コンパイル
以下でコンパイルできるはず。*実行するディレクトリ*内のファイルを参照するだけ。

```shell
% g++ -fPIC -Wall -O2 -shared -o hello.so hello.cpp libboost_python37.dylib libpython3.7.dylib
```
`hello.so`が*実行するディレクトリ*に作られる。

#実行
実行してみる。

```shell
% python3 test.py
printHELLO!!
3
How are you?
```

ちゃんとできてそう。

#まとめ
一つのディレクトリに全部ぶっ込んで動かすっていうちょっと強引な方法でしたが、とりあえず動いたのでよしとしよう。

Ubuntuでも動かそうとしたけどできなかった。`dylib`使ってるからMacじゃないとダメみたい。

#参考
[1]c/c++をラップしてpythonで使えるように
https://www.quark.kj.yamagata-u.ac.jp/~hiroki/python/?id=19

[2]boost インストールから実行(boost::python)まで。
http://nonbiri-tereka.hatenablog.com/entry/2014/02/01/004547


[^1]: `brew`を使うときにパーミッションエラーがでたら、`sudo brew ...`ってやる。
【Rails】Active Storage + S3 + Active JobでGoogle Cloud Visionセーフサーチ

個人開発のWebアプリ「[まちかどルート](https://machiroute.herokuapp.com/)」v6.0rc6への実装メモです。

# Amazon S3に画像をダイレクトアップロード

[Railsガイド](https://railsguides.jp/active_storage_overview.html)をもとに実装しました。

# セーフサーチを実装

前回の記事のとおりです。

[【Rails】Active Storage環境下でGoogle Cloud Visionのセーフサーチを実装](https://qiita.com/west2538/items/8e1752b1383219755b49)

# S3アップロード画像のパブリックURLを取得

こちらの記事を参考にしました。

[Rails ActiveStorage で PUBLIC な URL を表示する](https://qiita.com/yutackall/items/bc1ab2e9a508e33a05ac)

# セーフサーチを非同期処理化

※controllerのコードは省略します

## model
```ruby:post.rb
    has_one_attached :image
    after_commit :annotate_self, on: [:create, :update]

    def annotate_self
        if image.attached?
            ImageAnnotateJob.set(wait: 10.second).perform_later(self)
        end
    end
```
postの新規投稿もしくは編集のときに画像`image`が添付されていたら`ImageAnnotateJob`というActive Jobのキューを走らせます。10秒後に走らすようセットした理由は、Amazon S3へのアップロード完了までのタイムラグが発生するかなと思ったからです。

## job
```ruby:image_annotate_job.rb
class ImageAnnotateJob < ApplicationJob
  queue_as :second

  def perform(target)
 
    tempfile = target.image.attachment.service.send(:object_for, target.image.key).public_url

    require "google/cloud/vision"
    image_annotator = Google::Cloud::Vision::ImageAnnotator.new
    response = image_annotator.safe_search_detection image: tempfile
    # 注1
    response.responses.each do |res|
    safe_search = res.safe_search_annotation.to_h
      if safe_search.values.include?(:VERY_LIKELY) || safe_search.values.include?(:LIKELY)
        target.destroy
        return
      end
    end

  end

end
```
いったん`tempfile`にS3アップロード画像のパブリックURLを格納。それをGoogle Cloud Visionのセーフサーチにかけます。このコードはすべてActive Jobによってバックグラウンド(非同期)処理されます。もし不適切な画像と判断されれば投稿そのものを削除する流れです。

**注1: 2022/05/19**
初出の書き方だとAPIの仕様が変わったため正常動作しなくなったので`if`～`end`の部分をこのように書き換えたら動くようになりました。`to_h`メソッドを使っているのがポイントです。

## Sidekiq
```ruby:config\sidekiq.yml
:concurrency: 5
:queues:
  - [default, 7]
  - [second, 5]
```
じぶんはActive JobのライブラリとしてSidekiqを使用しています。上記`image_annotate_job.rb`の`queue_as :second`によってキューが処理される優先順位を設定しました。

# あとがき

駆け足ですが以上です。Google Cloud Visionのセーフサーチは高精度ですがレスポンスに1～2秒ほど要するため、そのぶん[前回の記事](https://qiita.com/west2538/items/8e1752b1383219755b49)のような同期処理だと投稿完了までにユーザーを待たせてしまううえ、サーバーサイドに負荷がかかります。今回の記事はそれらの課題を解決するものとなります。

また、苦労したのがS3アップロード画像のパブリックURLを取得する部分でした。`url_for`や`rails_blob_url`といったActive Storageのメソッドを使うと時限的なものorリダイレクトされるURLしか取得できずセーフサーチにかけても「そんな画像はありませんよ」と言われてしまいます。

というわけで試行錯誤を経たおかげでよりレスポンス性とセキュリティ性を兼ね備えた画像投稿機能を実装できました。

**補足: Rails 6.0ではこちらもご覧ください**
https://qiita.com/west2538/items/f932978e79220b880693

**gemのv1.0.0に対応した記事を書きました**
https://qiita.com/west2538/items/89bdbc4a935d12a65202
[Django]デプロイしたサイトのレイアウトが壊れた（静的ファイルが読み込めない）時の対処法[CentOS7][Apache2.4]

# 環境
* Django 2.1
* CentOS 7
* Python 3.6
* Apache 2.4
* mod_wsgi 4.6.5

# 対処法
静的ファイルをApacheで配信する設定に変更する

### 1. Apacheの設定ファイルを開く（設定ファイルの場所）

下記のファイルは自分で作成するファイルです。
おそらくこの記事を読んでいる人の大半は既に作成していると思いますが、無い人は作成しましょう。

```
vi /etc/httpd/conf.d/xxx.conf
```

### 2. Apacheの設定ファイルを編集する
設定ファイルの基本的な書き方は他の記事に委ねます。
ここでは、静的ファイルをApacheに配信させる設定のみに焦点を当てています。

また、```mysite/settings.py```を下記のように設定していることを前提とします。

```
STATIC_URL = '/static/'
```


#####1. adminと自作のmyappの静的ファイルを同じ場所に格納している場合（もしくは一方のみの場合）

```
    Alias /static /var/www/mysite/static
    <Directory /var/www/mysite/static>
        Require all granted
    </Directory>
```

#####2. adminと自作のmyappの静的ファイルを別場所に格納している場合

```
Alias /static/admin /var/www/mysite/static/admin
<Directory /var/www/mysite/static/admin>
    Require all granted
</Directory>

Alias /static/myapp /var/www/mysite/myapp/static/myapp
<Directory /var/www/mysite/myapp/static/myapp>
    Require all granted
</Directory>
```
Tomcat Manager API から アプリの停止、配備解除する方法

```:shell
#アプリの停止
curl --user ユーザ:パス http://TomcatのURL/manager/stop?path=/アプリ名
#アプリの配備解除
curl --user ユーザ:パス http://TomcatのURL/manager/undeploy?path=/アプリ名
```
vimコマンド（自分用）

##使い始めた理由
仮想環境（GCEとか・・・）でファイル共有面倒すぎてvim使いになることを決心
##vim導入(ubuntu/linux)
```
sudo apt-get install vim
```
##コマンド一覧
|コマンド|内容|
|----|----|
|vim ~~|~~にファイルパスでvimが使えるようになる|
###escを押した状態で使うコマンド(最初開いたときはこの状態)
|コマンド|内容|
|----|----|
|vim ~~|~~にファイルパスでvimが使えるようになる|
|:wq|保存|
|:q!|保存しないで終了|
|gg|先頭にいく|
|G|最後の行に行く|
|2G|2行目に行く（数字変えると何行目にもいける）|
|dd|行削除|
|2dd|2行削除（数字変えると何行でも削除できる）|
|w|単語移動|
|$|行末に移動|
|i|挿入モード(戻るときはesc)|
|v|ビジュアルモード(戻るときはesc)|
ModelChoiceFieldで__str__は変更せず、表示する文字列を変更する

model に定義してる \_\_str__ は変更したくないけど
セレクトボックスに表示する文字列を変更したいケース

## 試した環境

- Windows10
- Django 2.2
- python 3.6.8

## ModelChoiceField の作成

こんな model があって

```python:models.py
class Person(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    age = models.IntegerField()

    def __str__(self):
        return f"{self.last_name} {self.first_name}" 
```

ModelChoiceField を定義して

```python:forms.py
class SampleForm(forms.Form):
    persons = forms.ModelChoiceField(
        queryset=Person.objects.all(),
    )
```

表示すると model の \_\_str__ で設定した文字列が表示される。

```python:models.py
    def __str__(self):
        return f"{self.last_name} {self.first_name}" 
```

こんな感じ
![image00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259465/8af53e63-495a-8a03-b9d6-6a4bb8382011.png)


## セレクトボックスの表示だけ文字列を変更したい

セレクトボックスに表示する時だけ、「氏名 + 年齢」にしたい
model の \_\_str__ を変更すると model を参照している箇所が全部変わってしまうので

### ModelChoiceField を継承する

ModelChoiceField を継承したクラスを作成して
label_from_instance 内で表示したい文字列を定義する。

```python:forms.py
class PersonChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, person):
        return f"{person.last_name} {person.first_name} {person.age}歳"

class SampleForm(forms.Form):
    persons = PersonChoiceField(
        queryset=Person.objects.all(),
    )
```

表示してみると
![image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259465/4c4d0171-e169-a7d2-2c9d-894163fd184e.png)
年齢もセットで表示されるようになった。

## 参考
ModelChoiceField の 一番下に書いてある（英語）
[公式ドキュメント - ModelChoiceField](https://docs.djangoproject.com/ja/2.1/ref/forms/fields/#django.forms.ModelChoiceField)