OmniAICreator/Qiita-1.07M huggingface dataset:
Micronaut(Java)でBean Validationを追加する

# Micronautで自作のBean Validationを使いたい
業務で自作のバリデーターを作る必要が出てきて、新しいフレームワークなので全然資料がない && Java初心者 で結構苦労しました。

結果的には期待する動作をするものが出来たのでメモします。

# 経緯
現在のタスクで、入力バリデーションとしてよくあるこのような実装が必要になりました。

1. リクエストの特定のパラメータが、指定の正規表現にマッチしてるか確認
2. していなければ特定のエラーメッセージを持ったエラーレスポンスを返す

素？のMicronautなら `Pattern(regexp = "パターン", message="メッセージ")` で実現できると思いますが、現在のプロジェクトではアノテーション別にハンドラで処理をしており、この実装だと不都合でした。


# 実装

**2020/03/04追記 Validatorクラスにに `@Singleton` を付ける必要があり、加筆しました。**

### アノテーション + バリデーター
EmployeeNumber フィールドに対して、以下のいずれかを満たしているかチェックするBean Validation

- 値がNULL
- UXXXX, NXXX, KXXXX の形


```java
package com.myproject.annotation;

import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.validation.validator.constraints.ConstraintValidator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Singleton;
import javax.validation.Constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.regex.Pattern;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({FIELD})
@Retention(RUNTIME)
@Documented 
@Constraint(validatedBy = {EmployeeNumberValidator.class})
public @interface EmployeeNumber {
    String message() default "社員番号は社名のアルファベット頭文字 + 4桁の半角数字で入力してください。";
}

@Singleton
class EmployeeNumberValidator
implements ConstraintValidator<EmployeeNumber, String> {
    private static final Pattern EmployeeNumberPattern = Pattern.compile("^[UNK]\\d{4}+$");

    @Override
    public boolean isValid(@Nullable String value, @Nonnull AnnotationValue<EmployeeNumber> annotationMetadata, @Nonnull io.micronaut.validation.validator.constraints.ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }
        return EmployeeNumberPattern.matcher(value).matches();
    }
}

```

今回、 バリデーターとアノテーションをひとまとめにしましたが、別ファイルに切り出したい場合はバリデーターを `public` にしてアノテーション側で `import` します。

アノテーション定義インターフェース自体についてるアノテーションは、特にMicronaut固有のものでもなく検索するとすぐ出てくるので解説しません（自分もよくわかってない）

### アノテーションを利用するリクエストエンティティ
```java
package com.myproject.request;

import com.myproject.annotation.EmployeeNumber;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import io.micronaut.core.annotation.Introspected;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

@Introspected
@Data
@JsonFormat
public class EmployeeSearchRequest {
    @NotNull
    private String officeCode;
    private String employeeId;
    @EmployeeNumber
    private String employeeName;
}

```

# つまづいたところ

当初、 `javax.validation.ConstraintValidator` を実装する記事を参考に実装してみたところ、アノテーションはつけられるのに、 `ConstraintViolationException` のハンドラで拾ってくれない現象が起きました。

**`io.micronaut.validation.validator.constraints.ConstraintValidator` を実装した** バリデーターを作成をする必要があったようです。

これを アノテーションの `@Constraint` に指定することで解決しました。
相関サブクエリを用いるのに日本語→WHERE句の順で考えた

初投稿です。初心者です。

### 本記事の3点要約
- 「***相関サブクエリ***」というものを使うと、SQLを使ってデータテーブル内のある行の値を他の行の値と比べることができる
- 相関サブクエリを使うときは、同じデータテーブル内で2回FROM句を使うときは、わかりやすいように ***AS*** 句を使って名称を分けることが望ましい


### 引っかかったこと
SQLの学習サイトで下記の問題にあたり(本頁末尾にソース記載)、つっかえた。
> 国名(name)、州名(continent)、人口(population)の一覧のデータテーブル'world'があった時に、「同じ州の中でどの国と比べても3倍の人口を持つ国」を探し、その国名と州名を答えよ」

というもの。

```
SELECT
  name,
  continent
FROM
  world
WHERE
  hogehoge
```

と書くのだろうと思ったが、そのhogehogeに何を書くのかでだいぶ悩んだ。


### 解決策：相関サブクエリ

先に回答を書くと以下のようである。

```
SELECT
  name,
  continent
FROM
  world as A
WHERE 
  A.population / 3 > ALL(
    SELECT
      population
    FROM
      world as B
    WHERE
      B.continent = A.continent
      AND B.name != A.name
  )
```

これに行き着くために、SQLの初心者である自分は「何をWHERE句で表現したいのか？」を日本語で表し、それをクエリに変換する作業を行った。

#### 脳内で考えたこと

まず、WHERE句で書きたいと思ったのが、
「(1)州内の人口を比較したいから持ってきてほしい。(2)worldテーブルからね。(3)最終的に求めたい国に対して、大陸が同じ国の人口だけを比べる。(4)あと、自分自身と比べちゃだめ。
(5)これらを州ごとに調べて、人口に3倍差がついているやつだけ(を出して)」
という内容。

#### 相関サブクエリとは何か
- 1つのクエリ(SELECTからお尻まで)の中で別のクエリ(SELECTからお尻まで)を呼び出すから***サブ***クエリ。
- 上記でいう、WHERE句のALL()内の文のこと。
前述の内容がサブクエリで表すべき内容なんだなと感じ、以下の通り日本語→WHERE句へ変換した。

```
WHERE
 A.population / 3 > ALL( -- ※(最後に読む)
    SELECT 
      population  -- (1)州内の人口を比較したいから持ってきてほしい
    FROM
      world as B  -- (2)worldテーブルからね。サブクエリとして呼び出すからわかりやすくBと命名するよ
    WHERE
      B.continent = A.continent -- (3)最終的に求めたい国に対して、大陸が同じ国の人口だけを比べるんだよね？
      AND B.name != A.name -- (4)自分自身と比べちゃだめだよね
    -- ※：(5)これらに該当する行をすべて比較して、3倍差がついているやつだけを表示するよ
  )

```


#### 大切だと思われるところ

- 相関サブクエリのようなSQL独特の言い回しを、初学者がいきなり思いつくのには無理がある。まずは日本語にて、抽出したいデータテーブルのイメージをはっきり言語化させてから、それを忠実に落とし込んだクエリを書くようにする。
- 「相関サブクエリを呼び出すときはAS句を使ってデータテーブルの名称を分けようね」と暗記するのではなく、「難しいクエリを書くなら、データテーブルを呼び出すたびに名前をつけておいたほうが後々便利そうだと感じよう」という***マインド***を持つことが大切なのではないか。

#### 所感
- SQLZoo難しい...難しくない？
- SQLZoo最高...最高じゃない？
- SQLZoo...最高やな！

####　ソース
- [SQLZoo(最高のSQL学習サイト[英語です])](https://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial)
- [SQLZooの本章の回答](https://github.com/mrdziuban/SQLZoo/blob/master/4_select_within_select.sql)
【極論】クラス名ではいかなる接尾語も禁止！！

クラス命名のアンチパターンについては、世間でも問題意識が共有されていて、すでに記事が書かれているのですが（Qiitaなら[この記事](https://qiita.com/magicant/items/8134edf969f9629fa66e) など）、

私は正直「**これは負け戦なのでは？**」と感じていました。ダメな命名パターンは無数にあり、リストは長くなる一方だからです（そして長すぎるリストは読まれない）。

そこで戦況を巻き返すべく、無茶を承知でこう宣言させていただきます。

# ルール「クラス名ではいかなる接尾語も禁止」

**何らかの接尾語（サフィックス）が付いたクラス名は全てNGです。**

`Service`, `Manager`, `Controller`, `Filter`, `Handler`, `Validator`, `Visitor`, `Agent`, `Dao`, `Rule`, `Info`, `Data`, `Helper`, `Util`, `Type`, `Enum`, `Proxy` その他とにかく接尾語（サフィックス）は悪いものです。命名を考え直してください。

また、`Reader`, `Writer`, `Accessor`, `Getter`, `Fetcher` などの「動詞-er/-or」も接尾語の一種だと思ってください。「動詞-er/-or」も悪です。

**※例外条項**：

- フレームワークやプロジェクトに接尾語のルールがある場合はそれに従います。
- （上級者向け）接尾語を新設するときはREADMEやコメントに明記します。

# なんで接尾語はダメなの？

経験上、こういったクラスはえてして、**とりあえずメンバやメソッドをぶち込む掃き溜め**になるからです。

- 「`User`に関係する情報だからとりあえず `UserInfo` のメンバにしよう」とか
- 「`User`に関連する処理だからとりあえず `UserService` の静的メソッドにしよう」とか

また、接尾語がつく名前は、**深く考えずにクラスを設計してしまっていることや、不適切なクラス分割をしてしまっている事が多いです**。

# なんで接尾語はダメなの？その２

また、**同じ接尾語が付くクラスは、共通性を持つと期待する**のが人情です。例えば `HogeValidator`と`FugaValidator`があった時は、

- それぞれ `Hoge`オブジェクトと `Fuga`オブジェクトをチェックするんだろう
- 同じメソッド（多分 `validate`）を提供するんだろう
- 生成方法（`new` なり DI なり）も同じだろう
- `Piyo` クラスを新設した時は、`PiyoValidator`も必要なのかな？

と期待するでしょう。

しかし、**こういった接尾語・カテゴリを正しく設計するのは案外難しい**ことです。

例えば一時期Rails界隈では「〜Service」が流行ったのですが、現在は下火です。最初は良いアイデアだと思われたのですが、実践してみると酷いコードが生まれる事も多かったからです。

- 参考： [俺が悪かった。素直に間違いを認めるから、もうサービスクラスとか作るのは止めてくれ - Qiita](https://qiita.com/joker1007/items/25de535cd8bb2857a685)

# じゃあ、どうやって接尾語を消せばいいんだよ！？

接尾語を避ける方法はいくつかあります。

**1. そもそもクラスを作らない**
`UserInfo`や`UserUtil`のメソッド・メンバは `User`に移せるはずです。
その結果 `User`クラスの行数は大きくなりますが、気にする必要はありません。いわゆる「クラスの肥大化」「Fat Model」は本当に大規模なコードでのみ問題となります。

**2. クラスを細かく分ける**
例えば、`User`関係のチェックが詰め込まれた`UserValidator`があるとしたら、チェック項目ごとにクラスを分けます。

- `User::NameIsNotEmpty`
- `User::EmailAddressValid`
- `User::AdultAge`

etc...

**3. 見方を変える**
例えば、「ネットワーク越しにユーザーログを書き込むクラス`NetworkUserLogWriter`でログを書き込む」ではなく、「ユーザーログ`UserLog`にログを書き込む（実際の処理はネットワーク越しに行われる）」のだと考えてみてください。

ログを生成する側（ControllerとかModelとか）からすれば、とにかく抽象化されたナニモノカにログを書けることが大事で、それが「ネットワーク越しに」「書き込んでいる」ことは重要ではありません。隠蔽されていて良いのです。隠蔽されるべきことを名前で表す必要もありません。

**4. いっそオブジェクト指向を諦める**
どうしても的確なクラス名が思いつかなかったり、既存のコードが既に破綻していてクラス設計は無意味な場合があります。そんなときは、オブジェクト指向を諦め、クラス・メソッドではなく、純粋な関数にしてしまう手もあります。

「関数」が無い言語も「staticメソッドを１個だけ提供するクラス（クラス名はstaticメソッド名と同じ）」などで同じ事ができます。

# 接尾語は絶対にダメですか？

もちろん、人気のフレームワークが提供する「接尾語」（RailsのControllerなど）は、長年の風雪に耐えたものであり、使ってもなんら問題ありません。プロジェクトで DDD / Clean Architecture を実践するつもりなら、`Repository`や`UseCase`といった接尾語を使うことになるでしょう。

あなたが本当に必要だと思うなら、新たな接尾語を新設しても構いません。ただし、その際には以下に注意してください：

- 接尾語が的確であること（`Service`の二の舞を避ける）
- 接尾語が実際に必要であること（今回の１クラスだけで終わるんじゃないか？）
- 接尾語の使い方をREADMEやコメントで説明する事

# 接尾語以外にもダメな命名はあるよね？

もちろんです。

- 英語ではなく、ローマ字ですらない（`UserRegistKubun`とか）
- 名前が内容に反する（`ViewModel`なのに、DBを更新するだと！？）
- `Common` （大抵雑多なメソッドの掃き溜めになる）

など、まだまだありますが、私にはその元気がありません。他の誰かが書いてくれることを望みます。

また、正しい名前を付けることは大切ですが、**それは当たり前のこと**であって、プログラムが動き、人の役に立つ事が重要なのは言うまでもありません。

どっとはらい。
Processingで初めて0から作ったプログラム！【その１】

にっちもさっちも、ぼくボッチ。
どうも私です。

これからエンジニアになるので、Qiitaを活用して積極的にアウトプットしていこうかなと思います。どうぞ生温かい見守って頂けると幸いです。


##はじめに…
さて今回初めての投稿ということで、何を書こうかなと思っていたのですが、今回は自分が初めて0から作ったプログラムについて書いていきたいと思います。

**「画像認識による楽譜の読み取りシステム」**
これだけ聞くとすごいことをやってそうですよね？？

簡単にどんなシステムなのかというと、スキャンした楽譜の画像データから音符の位置を認識し音に変換し出力するシステムです。


処理を行った画像：
https://drive.google.com/file/d/12CioG8gzdif8xZvsWtCp2JM6hxRL2uPw/view?usp=sharing


処理の手順として
1.楽譜の五線を検出
2.音符の検出
3.音の出力
この開発はProcessingとOpenCVを使って開発しました。



今回は処理の1つ目の手順**楽譜の五線を検出**について書いていきます。

ではいくぅ～

##楽譜の五線を検出
五線検出の手順
1.画像のグレースケール化
2.画像のエッジ検出
3.線分の検出
4.五線の検出

ざっとこんな感じです。
<dl>
1.2．のグレースケールとエッジ検出に関してはOpenCV⑮の関数で元々あるので閾値等を最適化するだけなので簡単！

```java:FindEgge
opencv.findCannyEdges(th1, th2);
//th1,th2は閾値の変数
```
</dl>
<dl>
3.の線分検出はHough変換を用いて直線検出。
**Hough変換とは**
画像の中から直線や円などの図形を検出したい際によく用いられる手法の一つ。
　直線を小さな点の集合体だと考え、その点の密集度が高いと思われる部分を直線として認識するもの。



```java:Hough
 lines = opencv.findLines(th, minLength, maxLineGap);
```
OpenCVでは「opencv.findLines」という関数を使えば簡単のHough変換を行うことができます。
</dl>

実行結果：
https://drive.google.com/file/d/1flUd90jAMDb98oXt2qOlpavJsRamV2HL/view?usp=sharing
（画像の添付方法分からない…）

ここで得た五線のY座標の値を配列に格納しておけば、とりあえず第一ステップは完了！


次回は音符の検出について書いていきます！
お楽しみに！
Nginxについて


会社のクラウドサービスにてNginxを使用していたので、今一度内容を整理してみます。

# Nginxとは？

Nginxは無料のオープンソースwebサーバーの事です。

## webサーバーとは
外部から送られてくるリクエストを受けて、webサーバー上で返せるもの（静的コンテンツ）ならばレスポンスを行い、アプリケーションサーバーに依頼する必要のもの（動的コンテンツ）ならば、アプリケーションサーバーの処理結果をクライアントにレスポンスします。

この webサーバーに位置するのがNginxです。


# 特徴は？

Nginxとよく引き合いに出されるのが、Apache

Apacheも代表的なwebサーバーです。

Nginxはそもそも、Apacheという汎用的なwebサーバーがもつ、同時大量アクセスに対してレスポンスが悪くなる問題に対応すれ為、生まれたのだとか。。。

比較はこちらの記事をご参考に
https://qiita.com/pink/items/7709218310b5cf11eabe

簡単にまとめると

- Apache

Webサーバーとしての機能が豊富
使い勝手がいいよ！
色々できるぶん、サーバーコストは高い

- Nginx

リバースプロキシン機能があり、同時リクエストの処理に特化
シンプルなので、サーバーコストが安い

# リバースプロキシンとは？
webサーバーとの仲介となって、リクエストにレスポンスを返してくれるサーバーの事。

## なんの意味が？
メリットとしては、webサーバーの身元を隠せる点や、webサーバーが複数ある場合は、処理を分散できる。つまりロードバランサーと同じ働きをしてくれる！！

これが、同時多数リクエストに強い特徴。



間違っていたら、ご指摘ください。


コマンドに関しては、こちらがご参考に！
https://qiita.com/katzueno/items/44e02db2f1bfa0de5860
Linux（コマンド）

# 最初に
**本ページでは、投稿者が使用したことのあるコマンドを備忘録として記載する内容です。**

自身で学習してきた内容を書き出していきます。
基本的には自分自身でわかるような内容になりますので、ご容赦ください。
また、誤っている点がありましたら、コメントにてご指摘ください。

**（要確認）**マークがあるものは、「実行前に必ずググる」べき内容。



# ⚠️今回はインプット寄りの投稿です⚠️
今回は、自身の開発中に使用したことのある（見覚えのある）コマンドを洗い出しています。
Linuxに関して、無知な部分がほとんどです💦
頑張って勉強していきまーす！



# index
- Linuxについて
- 使用してきたLinuxターミナルコマンド



# Linuxについて
### Linux (リナックス)
OSの一種（コンピュータを使う際の土台の一種）、オープンソースのOS
無料で使用できるぞ。



# Linuxターミナルコマンド
## cat
ファイルの中身を表示。
ポートフォリオ制作時に使用した。

```terminal:
$ cat test.html  # test.htmlの中身を表示
```



## grep
ファイル内から指定した文字に一致する内容を含む行を検索。
以前ECサイトを制作した際に使用した。

```terminal:
$ grep オプション 検索文字列 ディレクトリ名  # このような形になっています。

$ grep -r  # 指定したディレクトリ以下をたどって検索
$ grep -i  # 大文字小文字を区別せずに検索
$ grep -l  # 検索した文字列が含まれているファイル名のみを表示
$ grep -n  # 検索した文字列が書いてある行番号を表示（-lオプションと併用不可）
$ grep -e  # 複数の検索条件を指定する
$ grep -v  # パターンに一致しない行を表示

$ # 以前ECサイトを制作した際に使用したrailsでのコマンド
$ (bundle exec) rails routes | grep customer # これは特定のrouteを取得する際に良い（| grep GET を加えるとさらに絞れる）
```


# kill
プロセスを終了。

```terminal:
$ kill $(cat tmp/pids/puma.pid) # アプリケーションサーバ（Puma）の停止する際に使用
```


# chmod
そのファイルやディレクトリに対して、誰がどのような権限があるかを決定。
GitHubとの接続に必要な鍵の作成するときに、ls -la .sshなどでエラーが出た時などに使用した。

```terminal:
$ sudo chmod 700 .ssh
$ # 700は、変更する権限を数値にしたもの
$ # パスワードを求められるので、ログインしているユーザのパスワードを入力
```

権限の見方は複数あり、勉強中。


# 追加あれば、どんどん更新していきます。
駆け出しとして頑張ります。
GitHub ActionsとCircleCIで実行するgitコマンド結果の違い

## はじめに

GitHub ActionsとCircleCIそれぞれで実行したgitコマンド結果に違いがあったので、そのメモです。

## 環境

- actions/checkout@v2 

## git diff結果の違い

CircleCIでは、シェルスクリプト内で以下の`git diff`コマンドを実行し、masterブランチとの差分ファイル名を洗い出して、後続で利用するよう、私の`.circleci/config.yml`では処理を組んでいました。

```
$ git diff --name-only origin/master...HEAD
ファイル名
ファイル名
ファイル名
...
```

しかし、GitHub Actionsでは、同じコマンドが`fatal: ambiguous argument`のエラーとなります。

```
Run git diff --name-only origin/master...HEAD
fatal: ambiguous argument 'origin/master...HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
##[error]Process completed with exit code 128.```
```

## git log結果を比較してみる

CircleCIも、GitHub Actionsも実行コンテナ内にSSHで入ることができます。

それぞれのやり方は以下を参照してください。

- [CircleCI - SSH を使用したデバッグ](https://circleci.com/docs/ja/2.0/ssh-access-jobs/)

- [GitHub Actionsでtmateを使ってシェルに繋いでデバッグする](https://blog.n-z.jp/blog/2019-11-10-github-actions-tmate.html)

### CircleCIの場合

`git log`で以下のように過去のcommit履歴が表示されます。

```
circleci@b89e46911691:~/project$ git log --oneline
f9a03f6 (HEAD -> actions_vs_circleci, origin/actions_vs_circleci, master) fix typo
6184539 use actions
e75c0c0 (origin/master, origin/HEAD) Merge pull request #1 from shonansurvivors/circleci-project-setup
88dee0f (略)
a33d927 (略)
e6d85f5 (略)
...
```

### GitHub Actionsの場合

`git log`で表示されるのは、直近のcommit履歴だけです。

```
runner@fv-az16:~/work/laravel-ci/laravel-ci$ git log --oneline
f9a03f6 (grafted, HEAD -> actions_vs_circleci, origin/actions_vs_circleci) fix typo
```

## 終わりに

このような差異があるので、CircleCIでgitコマンドを使用して何らかの処理、条件分岐等を行なっている場合は、GitHub Actionsへの移行時には要注意です。

## 追記

`actions/checkout@v1`であれば、GitHub Actionsでも過去のcommit履歴が取得できます。
cloud9でherokuのコマンドが使えない

Heroku -v
をしたところ、
command not found
が出る。

nvm install node
npm install -g heroku-cli
を試す。

再度
heroku -v
を行うと、
 ›   Warning: heroku-cli update available from 7.0.9 to 7.39.0.
heroku-cli/7.0.9 linux-x64 node-v13.9.0

と出るので、
heroku update
を行うと
heroku-cli: Updating CLI... not updatable
と出た。

https://tanarizm.com/cloud9_heroku_command_notfound
こちらの記事に従って
source <(curl -sL https://cdn.learnenough.com/heroku_install)
を実行。
Heroku -v
はできた。

Heroku をブラウザで開くと
Application error
が出現。

heroku logs
でエラーの内容を確認し、修正、デプロイ。
すると
"We're sorry, but something went wrong."
エラーが出た。

https://teratail.com/questions/124183
こちらの記事を参考に
heroku run rake db:version
と
heroku run rake db:migrate
を行うと、herokuは動いた。

結論：
・バリデーションのコードミス
・heroku run rake db:migrateをしていなかった。

追記
・３時間後に作業を行ったところ、またherokuのコマンドが使用できなくなった。
　同じ手順を踏み、解決。
PDFに入っている文字列が変で困った

# 直面した問題
PDFの文字列を取得してみると、たまに変な文字が入っていたりする。
検索書けて合致する場所を探そうとしても、うまくひっかからない。

# 以下の文字列をメモ帳にコピペしてみてね！
⾼高
⽥田
⼭山

ね、違うでしょ？
コンソールでは全く同じ文字に見えていたので、なぜうまく検索に引っかからないのか気づくまで時間がかかりました。

# 原因はユニコードらしい
どう検索してたどり着いたかは忘れましたが、ここを参考にしました。
https://qiita.com/korkewriya/items/e747253b715f41febfc4

# 以下のコードで解決

```Python: 
# resultにはすでに何らかの文字列が入っているものとする
from unicodedata import normalize
result = normalize('NFKC', result)  # Unicode正規化
```
AWS Systems Manager Session Manager でセッションを開始できない時に確認すること

# 現象

Session Manager のインスタンス一覧でインスタンスを選択すると「**インスタンスにある SSM エージェントのバージョンが Session Manager をサポートしていませんが、**」で始まるエラーが表示される。

![session_manager_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36122/231478d3-0c1c-d1e1-b33d-c258d3e577b8.png)

この状態で「**セッションを開始する**」ボタンを押しても反応がなく、セッションを開始できない。

# 確認すること

まずは示されたドキュメントを確認する。

- [Session Manager のトラブルシューティング \- AWS Systems Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-troubleshooting.html#session-manager-troubleshooting-instances)

上記の内容を確認しても解決しなかった場合、**SSM エージェントが起動しているか**を確認する。

次は Amazon Linux2 で確認し、停止していた例（`Active` が `inactive (dead)` になっている）。

```
$ sudo systemctl status amazon-ssm-agent
● amazon-ssm-agent.service - amazon-ssm-agent
   Loaded: loaded (/usr/lib/systemd/system/amazon-ssm-agent.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since 火 2020-mm-dd hh:mm::ss JST; 2s ago
  Process: 3480 ExecStart=/usr/bin/amazon-ssm-agent (code=exited, status=0/SUCCESS)
 Main PID: 3480 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/amazon-ssm-agent.service

(省略)
```

この場合、起動する。

```
$ sudo systemctl stop amazon-ssm-agent
```

次に起動したことを確認する（`Active` が `active (running)` になっている）。

```
$ sudo systemctl status amazon-ssm-agent
● amazon-ssm-agent.service - amazon-ssm-agent
   Loaded: loaded (/usr/lib/systemd/system/amazon-ssm-agent.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since 火 2020-mm-dd hh:mm::ss JST; 2s ago
  Process: 3480 ExecStart=/usr/bin/amazon-ssm-agent (code=exited, status=0/SUCCESS)
 Main PID: 3480 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/amazon-ssm-agent.service

(省略)
```

失敗した場合はログを確認して対応をする。

これで先ほどのエラーメッセージが消えて、セッションが開始できるようになっている。

# あとがき

以前は接続出来ていた（設定が出来ていて、以降も変更していない）のに、突然できなくなったというケースではこの対応が参考になるかもしれない。

エラーメッセージを英語に切り替えると次のように表示される。

> The version of SSM Agent on the instance supports Session Manager, but the instance is not configured for use with AWS Systems Manager. Verify that the IAM instance profile attached to the instance includes the required permissions.

最初のカンマまでは「**インスタンスの SSM エージェントのバージョンは Session Manager をサポートしていますが、**」と約するのが正しいのではないだろうか。ただ、その場合でも Session Manager のエラーメッセージからは SSM エージェントの起動状態は分かりづらい。
Flask Basic認証

一度Dokcerizeしてあるプロジェクト前提になってます。
前回：[Docker + Python + Flaskでアプリケーション開発](https://qiita.com/nanaco/items/e6941cd94a3cf74bbf58)

# ファイル構成
```
├── api
|   └── auth.api
├── requirements.txt
└── docker-compose.yaml
```

# Basic認証機能の追加
```python:auth.py
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
import os

auth = HTTPBasicAuth()

users = {
  os.getenv("BASIC_AUTH_USER"): generate_password_hash(os.getenv("BASIC_AUTH_PASSWORD"))
}

@auth.verify_password
def verify_password(username, password):
    if username in users:
        return check_password_hash(users.get(username), password)
    return False
```

```python:
from api.auth import auth

# 省略
@route('/')
@auth.login_required
def add():
# 省略
```
basic認証が必要なルーティングに`@auth.login_required`を追加します。

# dockerの修正

```yaml:docker-compose.yaml
version: '3'
services:
  api:
    container_name: tool-api
# 省略
    environment: 
      BASIC_AUTH_USER: "user"
      BASIC_AUTH_PASSWORD: "password"
```
`auth.py`で使うアイパスを環境変数に設定します。

```tex:requirements.txt
# 省略
flask_httpauth
```
必要なモジュールを追加します。


実行

```
$ docker-compose up
```
イラレ オプティカルとメトリクスの違い

###オプティカル
ソフトウェア（Illustratorなど）が判断して自動で文字詰めを実行

###メトリクス
フォントに埋め込まれた特定の文字の組み合わせ情報（ペアカーニング情報）での最適なカーニング情報に基づいて自動で文字詰めを実行

つまり、**「オプティカル」を使うとソフトウェアが割とざっくり詰めてしまう**危険性がありますが、**「メトリクス」を使えば書体デザイナーが設定したより精密な文字詰めを自動で行う**ことが可能になります。

>少しの工夫でグッと良くなる！タイポグラフィTIPS
>https://note.com/kyonskmt/n/n844b20b7f58b

オプティカルのままだと文頭にある（）カッコの文字詰めができなかったのですが、メトリクスにしてトラッキングを調整したらキレイに揃いました。
文末もオプティカルだときちんと揃わないのですが、メトリクスは揃います。
COBOLレコードのElasticsearchへの取り込み - (1)コンセプト

#はじめに
この記事は、「COBOL ハッカソン 2020 ～IT温故知新 世代を超えた開発コンテスト～」の活動内容について記載したものです。
[COBOL ハッカソン 2020](http://www.cobol.gr.jp/knowledge/hackathon/hackathon2020.pdf)
テーマとしては「クラウド連携やってみた！」ということで、COBOLとなんらかのクラウド連携をしてみるというものです。COBOLコンソーシアムが主催となっていますが、アマゾンウェブサービスジャパンが協力しているということで、何かはAWS上で動くものを作るということになっています。
今回、我々のチームが実施した内容は以下の記事に分割して記載していきます。

## 関連記事

[(1) コンセプト](https://qiita.com/teamcimkcs2020/private/cb3e8a020e414f7acad3) <=当記事
[(2) 要素技術](https://qiita.com/teamcimkcs2020/private/5689e95b83052500a5fa)
[(3) 実行結果/まとめ](https://qiita.com/teamcimkcs2020/private/d3582ec41fb580ee3b72)

以下のYoutube動画も合わせてご参照下さい。
[Youtube:COBOLレコードのElasticsearchへの取り込み](https://youtu.be/PkEuYrMJBe0)

# コンセプト
参考: [DXレポート ～ITシステム「2025年の崖」克服とDXの本格的な展開～](https://www.meti.go.jp/shingikai/mono_info_service/digital_transformation/20180907_report.html)
経産省が出している上のレポートはあちらこちらで参照されており、「2025年の崖」克服のためのDXの重要性が謳われています。この手の話は言葉を変えつつも以前からずっと続いてきているテーマとも言えます(ホスト集中 => クラサバへ、Web連携、SOA、SoE-SoR などなど...)。いずれも、新しい仕組みにシフトするにしても、スクラップ&ビルドで一切合切を作り直すということではなく、既存の仕組みを活かしながら適材適所で考えるということは共通しているかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595911/38ea3eb6-ad2e-8a01-28cb-f35fa8c4227b.png)

今回はCOBOLを中心としたハッカソンということですが、テーマとしては"クラウド連携"というのが挙げられており、既存資産の代表ともいえるCOBOLと、比較的新しい世界の"クラウド"環境をそれぞれうまく活用することについて検討しました。
さて、両者の間には文化の違いや技術的な隔たりが多々あると思いますが、ここでは、取り扱うデータ形式の違い、ということに着目してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595911/6f65747d-881e-dfc0-3680-5e6c12c2bb6b.png)

COBOL上ではレコードベースのデータで扱われます。これは特定のオフセットに特定の長さのデータが入るということがあらかじめ決められていて、そのフォーマットに従ってデータが保持されます。データ構造はCopybook(コピー句)によってあらわされます。従って、データそのものだけだとどの部分にどのデータが入っているかは分からず、Copybookの構造と照らし合わせることではじめて意味のあるデータを取り出すことができるということになります。
昨今のサービスで使われるデータ形式はJSONで扱われることが多いと思います。これはデータ自体に項目名や構造を保持しているために疎な連携がしやすく可読性にも優れます。一方でデータサイズが大きくなりがちなので余計な負荷がかかることにもつながります。

COBOLはデータサイズを意識する言語ですので、サイズが可変のJSONのようなデータを直接扱うことは苦手です。そこで、COBOLで扱われているレコードベースのデータをJSONベースのデータにして管理するようなパスが作れれば、既存の仕組みを活用する新しい道が開けるのではないかと考えます。
今回は大量データの管理や可視化、分析などによく利用されるElasticsearchにデータを取り込んで見ることにしました。

テーマ: **COBOLアプリから出力されるレコードベースのデータを、Elasticsearchに取り込んでKibanaで簡単に可視化/分析できるようにしてみよう！**

#方針

基本的には以下の前提/方針で進めることにします。

- 既存のCOBOL資産を有効活用する
    - なるべく既存アプリに手を入れなくて済むような仕組みとする
- 要員のスキルセットの境界を明確にする
    - COBOLを扱う要員は、従来のCOBOLの作法の範疇で考えればよいようにする(COBOLアプリ側でJSONは意識させない)
- アプリケーションが特定のミドルウェアに直接的に依存しないようにする
    - DBとのコネクションなどは保持しない

つまり、できるだけ疎結合になるような方向性で考えたいと思います。

# 参考
当ハッカソンの前提条件と審査のポイントは以下の通り
## 前提条件
- 一部でもよいのでCOBOLが使われており、実際にコンピュータ上で稼働すること
- 成果物のうち「何か」がAWS上で稼働していること（ハッカソンのテーマについてはAWSの利用に関するものでなくてもOK）

## 審査のポイント
- COBOLの特徴を生かした使い方・COBOLをうまく使っている！
- コンセプトの着眼点！（共感度・納得度・面白さ）
- COBOL利用の将来性への貢献度！（有益な手法であること/その情報があるとうれしい人が多そう）
- コンセプトの実現性！（構想だけでなく動く事を検証している）

------


次は、具体的な仕組み作りに必要な要素技術を個別に見ていきます。

[=>次の記事へ](https://qiita.com/teamcimkcs2020/private/5689e95b83052500a5fa)
Your version of Django supports SameSite flag in the cookies mechanism. You should remove django-cookies-samesite from your project.

# 背景
Chrome80に対応するため、SameSite=Noneの明記をしたい。

# pip install django-cookies-samesite ではダメだった。

参考：https://webty.jp/staffblog/production/post-2629/

参考ページに沿って、django-cookies-samesiteを設定してみたところ、以下のエラーに遭遇。

```
DeprecationWarning at /
Your version of Django supports SameSite flag in the cookies mechanism. You should remove django-cookies-samesite from your project.
```

ちなみにDjangoのバージョンは、Django2.2
Docker上のCentOSでnodebrewを入れる

# はじめに
Centosにnodebrewを入れる記事はたくさん存在するのですが、
Dockerでやった時に詰まったので個人的なメモがてら残しておきます。

# 環境
* docker

```zsh
$ docker --version
Docker version 19.03.5, build 633a0ea
```

* Dockerfile

```Dockerfile
FROM centos:centos7
```

# やったこと
## 1. 従来の記事を読んでinstall
```zsh
$ curl -L git.io/nodebrew | perl - setup
```

↓ 悲しみのエラー

```
Can't exec "which": No such file or directory at - line 927.
Can't exec "which": No such file or directory at - line 927.
Need curl or wget at - line 927.
```

whichがないと言われinstall出来ない。
どうやら、centos:centos7にはwhichなどがない模様。

## 2. whichをinstall
```zsh
$ yum -y install which
```

## 3. 再びnodebrewをinstall

```zsh
$ curl -L git.io/nodebrew | perl - setup
```

↓ install 完了！

```zsh
Fetching nodebrew...
Installed nodebrew in $HOME/.nodebrew

========================================
Export a path to nodebrew:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================
```

## 3. 欲しいバージョンを入れて使用
```zsh
$ /root/.nodebrew/current/bin/nodebrew install v12.16.1
$ /root/.nodebrew/current/bin/nodebrew use v12.16.1
```
今回は、nodeのv12系を入れたかったので、こんな感じでinstallしました。

余談ですがdocker等でサーバを立てたりする時にpassを通すと後から確認する時困ることが多いので、僕はフルパスで起動するようにしています。
もちろん、自分のmacではしっかりpassを通してます。

## 4. まとめ
```zsh
$ yum -y install which
$ curl -L git.io/nodebrew | perl - setup
$ /root/.nodebrew/current/bin/nodebrew install v12.16.1
$ /root/.nodebrew/current/bin/nodebrew use v12.16.1
$ /root/.nodebrew/current/bin/node --version
```

↓ nodeが使えることを確認

```zsh
v12.16.1
```

# おわりに
dockerを触っていると、環境構築ばかり行うので詰まった時とかはqiitaに残しておくのが必要ですね...!
samtools を用いた BAM file から Unique mapped reads の抽出 ~bowtie2 のアライメントファイルから~

##samtools##
samtools は NGS のリードのアライメント後の出力ファイルである sam/bam file を編集できるツールです。
今回は、samtools でソートしてしまった bam file から unique mapped reads の抽出を行いましたので、書き置きします。
[samtools のマニュアルページはこちら](http://www.htslib.org/doc/samtools.html)

sam file であれば、テキスト形式なので、grep 等を使って unique mapped reads を抽出できます。一方で、bam file はバイナリの形式なので、単に grep を咬ませるだけでは抽出できません。
そこで、今回は single-end reads と paired-end reads を bowtie2 でアライメント後、bam file から unique mapped reads を抽出したいと思います。

bowtie2 の sam/bam file には、それぞれのリードにタグ情報が付与されています。
今回は、複数回アライメントされたリードに付く XS タグを除くことで、unique mapped reads を抽出します。

```bash:
# grep -v : ある文字を持った列を取り除く

# Single-end
# -h : Header のみの出力にしない, -@ : Thread number, -b : bam 形式で出力
$ samtools view -@ 8 -h ./MappedReads.bam | grep -v "XS:" | samtools view -@ 8 -h -b > ./UniqueMappedReads.bam

# Paired-end
# -f 0x2 : ペアでアライメントされたリードを表示
$ samtools view -@ 8 -h -f 0x2 ./MappedReads.bam | grep -v "XS:" | samtools view -@ 8 -h -b > ./UniqueMappedReads.bam
```

以下参考
・[samtools のマニュアルページ](http://www.htslib.org/doc/samtools.html)
・[bowtie2 のマニュアルページ (タグに関しても含む)](http://bowtie-bio.sourceforge.net/bowtie2/manual.shtml)
・[grep の使い方とオプション](https://eng-entrance.com/linux-command-grep)
静的コンテンツでパスパラメータを利用する方法【Nuxt×Firebase Hosting】

## 実現したいこと

この様にURLに直アクセスでパスパラメータを取得する画面を静的コンテンツ(nuxt generate)で実現します。
![generate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420680/bcf8ea29-c5e0-3776-5f2b-1a329f88620b.png)
普通にNuxtをgenerateしてデプロイするだけだと、内部リンク(nuxt-link等)からのアクセスでは表示できるのですが、パスを指定した外部からのアクセスでは404 Not Foundになってしまいますのでこれに対処します。


## モチベーション
SSR（Hosting+Functions）にすれば当然簡単に実現できますが、FirebaseのCloud FunctionsだとHostingとの連携はリージョンが「us-central1」しか利用できない*1のでレイテンシが気になりますし、あまり利用数がないとコールドスタートなので起動が遅かったりで、Hostingだけでなんとかできないか模索しました。
*1 [https://firebase.google.com/docs/hosting/functions?hl=ja](https://firebase.google.com/docs/hosting/functions?hl=ja)

## 静的コンテンツでパスパラメータを利用する方法

Firebase Hostingのrewrite構成を設定するだけで可能です。

```json:firebase.json
{
  "hosting": {
    "public": "app/dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "/test/*/*/",  //アクセスを想定するパス構造を定義し、ルートのindex.htmlにリライトします
        "destination": "/test/index.html"
      },
      {
        "source": "/test/*/",　//こちらは/test/_id/を想定
        "destination": "/test/index.html"
      }
    ]
  }
}
```
上記に対応したpagesのディレクトリ構成は以下の通りです。

```
./pages
└── test
   └── _id
      └── _no
         └── index.vue
      └── index.vue
   └── index.vue
```

ページは以下の様にパスパラメータを利用する際の通常通りで問題有りません。

```vue:/pages/test/_id/_no/index.vue
<template>
  <div>
    <div>TEST NO INDEX</div>
    <div>$route.path:{{ $route.path }}</div>
    <div>$route.params:{{ $route.params }}</div>
  </div>
</template>

<script>
export default {}
</script>
```

これで静的コンテンツのみでパスパラメータを実現することができます。
[初学者必見]はじめてのQiita編集方法

#この投稿の目的
はじめて１ヶ月ぐらいのエンジニアがアウトプットの場所としてQiitaを利用できるようになる。

#手順
以下に手順を示す。

##1.アカウントの作成
Qiitaのアカウントを作る
その他設定。（ここは詳しく説明する必要もないでしょう。）

##2.編集画面
右上のアイコンをクリックし、下書き一覧をクリックする。（以下の写真に飛ぶ）
次に以下の画像の右の方にある「鉛筆のアイコン」をクリックする。
![スクリーンショット 2020-03-03 18.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590181/7bdb91de-360a-74cc-447a-df6f507d0f0f.png)

##3.タイトルとタグの編集
以下の画像のように飛んだらタイトルとタグに入力する
![スクリーンショット 2020-03-03 18.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590181/b8f32db4-2a4d-e96e-4b05-8e5b3dc60a30.png)

##4.本文の編集
Qiitaの記事作成にはMarkDownという言語を使用する。
下記の画像の「はてなマーク」を押すとMarkDownの書き方が掲載されている。
![スクリーンショット 2020-03-03 19.05.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590181/699488da-a99f-a487-3e23-bc7deae1e175.png)
以上

#この記事のMarkDown本文一部
以下の写真
![スクリーンショット 2020-03-03 19.21.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590181/83639175-fcf5-4fe0-dda9-5f16717467e6.png)


※また今回使った画像（上記のURL)はスクリーンショットをし以下の画像のボタンから添付した。

**またその他Markdownの例を見たい場合、以下の画像のように誰かの記事の右上のアイコンをクリックしMarkdownで本文を見るをクリックすると良い。**
![スクリーンショット 2020-03-03 19.13.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590181/033b3b80-ccc7-f579-1356-687c17068e5e.png)

#投稿背景
outputが大事だということをよく聞くので、よくお世話になっているQiitaに投稿しようと思いました。
現状、エンジニアを目指し始めて１ヶ月近く立ちます。
私自身もはじめての投稿となりますので、薄い内容ではございますが、最後まで読んで下さった方、
いいね。
押してもらえればかなり嬉しいです。
NUMAを何度も検索したくないBookmark

不意にNUMAの正確な知識を求められる場合がある。そのたびに検索していた。馬鹿だなぁ。
この記事ははてぶと同じことだけど、今の私にはこのリストだけでも十分ありがたい。

# Bookmark
http://sasaki.hateblo.jp/entry/2017/07/18/152427
https://ipsj.ixsq.nii.ac.jp/ej/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=91638&item_no=1&attribute_id=1&file_no=1&page_id=13&block_id=8
https://qiita.com/tomo0/items/5352b8ceb6ccb70390c8
pipでインストールしたjupyter notebookを起動しようとして「command not found」と言われたらPATHを通せばいけるっぽい。

##前提
いろいろとインストールした前回（https://qiita.com/midonon/items/d15385387a04dc7c6007 )の続き
- OS:macOS Catalina 10.15.3
- メモリ:16GB
- Python:3.7.3


##jupyter notebookが起動しない
udemyで面白そうな講座を見つけたので、その動画の指示に従ってjupyter notebookを起動しようとしたら、`-bash: jupyter: command not found`と言われてしまった。

echo $PATHで確認したところパスが通っているのは以下

- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin

そしてjupyterのありかを`pip3 show jupyter`で確認したら `/Library/Python/3.7/site-packages`なので、パスが通ってないせいっぽい。

「-bash: jupyter: command not found」でググって出てきたhttps://stackoverflow.com/questions/45495753/jupyter-not-found-after-pip-install-jupyter を参考に以下を実施したところ、無事に行けた。


##パスを通す
`cd ~`
`ls -la`
でホームディレクトリの一覧を見て、.bash_profileのファイルがないことを確認。
`touch .bash_profile`で.bash_profileを新規作成し、`open ~/ .bash_profile`で.bash_profileをテキストエディットで開く。
中身に`eexport PATH="$HOME/Library/Python/3.7/bin:$PATH"`を追記。

その後にターミナルを開き直して`echo $PATH`で目的のパスが通っていることを確認後、`jupyter notebook`としたところ無事に起動。
ようやく講座のスタートに立てる・・・
【VBScript】任意のエクセルファイルを開いて編集後、名前を付けて保存をする。

メモとして残します。


#■やり方
```vb
with WScript.CreateObject("Excel.Application")
    .DisplayAlerts = False ' アラートダイアログを表示しない。
    Set book = .WorkBooks.Open("開くエクセルファイルのパス")
    Set sheet = book.WorkSheets.Item(1) 'とりあえず1番目のシートを取得

    '変数「sheet」に対して処理など・・・・

    book.Saveas("保存先パス") '.DisplayAlertsがfalseであれば同名ファイルは上書きされる。

    .Quit()  ' Excel.Applicationを破棄
end with
```
#■さいごに
おそらくCOMオブジェクト？を呼びしだしてそのオブジェクトの操作をしているだけなのでVBSで、というよりかは、COMオブジェクトを用いて、エクセルを開いて、編集、名前を付けて保存という表現が正しい気がします。
Docker + Python + Flaskでアプリケーション開発

前回：[Flask SQLAlchemyを使ってMySQLに接続](https://qiita.com/nanaco/items/f22f67e2a50fab64c937)で作成したプロジェクトを使ってDockerizeします。

# Dockerize
## ファイル構成
```
├── api
├── app.py
├── config.py
|
├── requirements.txt
├── Dockerfile
└── docker-compose.yaml
```

```text:requirements.txt
flask
SQLAlchemy
Flask-SQLAlchemy
PyMySQL
```
requirements.txtにはインストールが必要なモジュールを書き込んでいきます。

```docker

FROM python:3.8-alpine

ADD requirements.txt /var/www/html/tool/
WORKDIR /var/www/html/tool
RUN pip3 install -r requirements.txt
```

```yaml:docker-compose.yaml
version: '3'
services:
  api:
    build: .
    container_name: tool-api
    volumes:
      - ~/path/tool-api:/var/www/html/api
    ports:
      - 5000:5000
    tty: true
    command: flask run --host 0.0.0.0 --port 5000
    external_links:
      - "db:db"

networks:
  default:
    external:
      name: db_default
```
今回は他のコンテナにあるmysqlに接続しています。

実行

```
$ docker-compose up
```


# 静的ファイル
## ファイル構成
```
├── api
├── app.py
├── config.py
├── requirements.txt
├── Dockerfile
├── docker-compose.yaml
|
├── nginx
|   ├── Dockerfile
|   └── nginx.conf
└── statics
    └── css
        └── sample.css
```

## nginxのdockerfileを作成

```docker:/nginx/Dockerfile
FROM nginx
CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]
```

```conf:nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;

    keepalive_timeout  75;

    upstream flask_server {
        server tool-api:5000 fail_timeout=0;
    }

    # サーバの設定
    server {
        location /statics/ {
            alias /var/www/;
        }
        
        location / {
            try_files $uri @proxy_to_api;
        }
        
        location @proxy_to_api {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_redirect off;
            proxy_pass http://flask_server;
        }
    }
}
```
`/statics`にアクセスするとnginxが`/var/www/`ファイルを見に行くようになります。

## docker-composeファイルを修正
```yaml:docker-compose.yaml
version: '3'
services:
  nginx:
    build: ./nginx
    container_name: tool-nginx
    volumes:
      - ./statics/:/var/www/
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 80:80
    depends_on: 
      - tool-api
  api:
    build: .
    container_name: tool-api
    volumes:
      - ~/path/tool-api:/var/www/html/api
    ports:
      - 5000:5000
    tty: true
    command: flask run --host 0.0.0.0 --port 5000
    external_links:
      - "db:db"

networks:
  default:
    external:
      name: db_default
```

実行

```
$ docker-compose up
```
[Ruby] 基本のメソッド一覧（追記中）

#はじめに
「改定４版 基礎 Ruby on Rails / 黒田努・佐藤和人」を使ってRailsの学習をしています。
この本に出てくるメソッドの忘備録を作っておきたいと思って作成しました。

コードはファイルにコピペしてすぐターミナルで実行できるような形式で書いています。

※ 随時更新＆追記していきます。
※ p.はこの本のページナンバーです。

#メソッド一覧
p.85
`respond_to?()`
引数にシンボルを渡すと、そのオブジェクトがメソッドを持っているかどうか調べられる

```ruby:example.rb
def count_10
    10.times do |i|
        print i, ","
    end
    puts "'count_10' method using 'times' method" if 10.respond_to?(:times)
end
count_10
# output: 0,1,2,3,4,5,6,7,8,9,'count_10' method using 'times' method
```
---
p.86
`include?()`
引数が指定した配列に含まれているかどうか

```ruby:example.rb
def fruit
    arr = ["apple", "banana", "lemon"]
    puts "'arr'配列は'apple'を含む" if arr.include?("apple")
end 
fruit
# output: 'arr'配列は'apple'を含む
```


下記のように入力値を受け取り、その値によって条件分岐させることもできる

```ruby:example.rb
def passphrase
    print "合言葉:"
    word = gets.chomp
    if ["apple", "banana", "lemon"].include?(word)
        puts "OK"
    else
        puts "NO"
    end
end
passphrase
# output: 合言葉:
# 入力値がapple, banana, lemonのどれかだと OK、
# それ以外だと NOが返される
```
---
p.87
`all?`
配列には、ブロック（{}←これ）を使って条件を調べるためのメソッドがあり、これは
配列の中の全てが条件を満たすかどうかを調べられる

```ruby:exaple.rb
def all_zero_or_more
    arr = [0,1,2,3,4,5,6,7,8,9,10]
    puts "OK" if arr.all?{|item| item >= 0}
end
all_zero_or_more
# output: OK
```
---
p.87
`any?`
これもブロックを使って条件を調べるためのメソッド
配列の中のどれかが条件を満たすかどうかを調べられる

```ruby:exaple.rb
def five_or_more
    arr = [0,1,2,3,4,5,6,7,8,9,10]
    puts "OK" if arr.any?{|item| item >= 5}
end
five_or_more
# output: OK
```
HomebrewとPycharmのインストール手順メモ

プログラミングに興味をもったので、いろいろ準備した。
##やったこと
以下の物品をインストールした。

- Homebrew
- Python
- ライブラリ（Numpyなど)
- Pycharm

##前提
- OS:macOS Catalina 10.15.3
- メモリ:16GB

##Homebrew, Python,ライブラリのインストール
https://qiita.com/yoshizaki_kkgk/items/4663148a2b3ca078ddbc
基本的に上記記事に従って実行。

###HomebrewとPythonのインストール
「Pythonが既にインストールされていないか確認しましょう」とのことで、無反応を予想しながら`which python3`すると、予想に反して`/usr/bin/python3`　が帰ってきた.
知らない間にpython3がインストールされていたみたい。

ちなみにversionはPython 3.7.3だった。
###ライブラリのインストール
引き続きライブラリのインストールをしようと`pip3 install numpy`を叩くもエラー

エラーメッセージは
`Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/3.7'
Consider using the `--user` option or check the permissions.`

意訳すると「環境エラー[エラー１３]/Library/Python/3.7のパーミッション拒否のせいでパッケージがインストールできませんでした。--userオプションの使用を考えるか、パーミッションを確認してね。」って感じ？

どうにも権限がないっぽい

https://teratail.com/questions/10352
↑を見て、sudoを使って管理者権限で実行すればOKとのことなので`sudo pip3 install numpy`としたところ、インストールできた。
しかし、以下のように怒られる。
`The Directory'/Users/XXX/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/Users/XXX/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.`


https://laboradian.com/error-with-pip-install/
とか
https://pyteyon.hatenablog.com/entry/2019/05/24/003924
を見ると--userオプションを使った方が良さそうなので`sudo pip3 install --user scipy`でインストールした。
この結果は怒られなかったので、これで正解っぽい。

同様に--user を使ってscikit-learn, Chainer, Jupyter notebookをインストールした。

##Pycharmのインストール
ここまで参考にしてきたキカガクの記事はAtomをおすすめしているが、Twitterで教えてもらったPycharmを使いたかったので、ここからは先生を変更。
https://dev-reco.com/416
この記事を参考にPycharmのインストールをしました。

基本的には書いてあるとおりだけど、リンク先の手順８（下記引用部分）で使用するPythonの場所のみ変更
> 以下を入力して”Create”ボタンを押下します。
“untitled”部分は好みのプロジェクト名に変更してください。
“Base interpreter”はプロジェクトで使うPythonを設定します。
今回はpyenvでインストールしたPythonを使いたいので以下に変更します。
~/.pyenv/versions/3.7.1/bin/python3.7

以上で、無事にPycharmのインストールが完了しました。
udemyで面白そうな教材見つけたので、やって行こうと思います。

ちなみにanaconda使わないのは、この記事の影響。
https://qiita.com/yniji/items/b1b20211846a5a9f189b

>"vanilla" Python を使うか Anaconda を使うかは、最初に書いたように好みの問題です。ただし、Web、デスクトップ、組み込み、ゲーム、モバイル等のアプリ開発をする場合は、"vanilla" Python を使ったほうがいいです。Anaconda は、データサイエンス向けのものなので、アプリを開発するために必要なパッケージが不足しています。それらを pip でインストールすることは可能ですが、pip で大量にパッケージをインストールすると二重管理になってしまい問題が発生すやすくなります。でも、"vanilla" Python から Anaconda に移行することも逆に移行することも簡単だし、プロジェクトによって使い分けることもできるので、あまり気にせずに始めたらいいと思います。

ま、困ったらanacondaに移行します。
PowerPoint Tips

殆ど自分用備忘録
不定期に更新します．

# Add-ins

# 1. pptTeX
スライドにTeX数式を挿入できる．
後から編集も可能
導入方法：[pptTeXでパワポにきれいな数式を挿入する](https://qiita.com/kzkadc/items/7c32d1633e7093461128)
# 2. MLC
オブジェクトの整列，配置などを行う．
Adobe illustratorの機能を移植したみたいなアドイン
全機能を使うには$50/month必要（ぼったｋ..）
正直Free版でもまあまあ便利．
製品ページ：[MLC PowerPoint Add-in](https://mauriziolacava.com/my-addin/)

# 画像の挿入とリンク
スライドに画像を挿入する場合，基本的に画像はスライドに埋め込まれるが画像の挿入方法は「挿入」「リンク」「挿入とリンク」の3種類がある．

挿入タブから画像グループの画像をクリックすると，ファイル選択ウインドウが開く．
この時，下図のように挿入ボタンの▼を押すと挿入方法が選べる．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228086/c2d6a42c-68a6-66e2-cd2a-5fc5ce217c10.png)

個人的にオススメは**挿入とリンク**
元の画像ファイルを編集した際に更新することで変更がスライドに反映されるので再度画像を挿入する手間が省ける．
また，リンクとは違って，元画像が削除されてもスライドの画像には影響がない．

参考：[スライドに図を挿入するときの種類 (元の図とリンクするには)](https://www.crie.co.jp/chokotech/detail/310/)

# クイックアクセスツールバー
ウインドウ上部にあるツールバーをカスタマイズすることで，スライド作成効率が格段に上がります．（実体験）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228086/dd30b7f3-8b53-c5f9-f0f2-d2b84d99888e.png)

右端の▽をクリック->「その他のコマンド」を選択するとツールバーをカスタムすることができます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228086/4d7008c7-366e-2b83-d598-252cc6d731c1.png)

基本的なコマンドから詳細なものまで殆ど揃っています．また，アドインもツールバーに追加できます．

自分のツールバーを晒します．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228086/a49a1ffc-73ed-ee64-510a-b679cddab5cb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228086/b3b6378d-b6c3-ad90-91ff-b0ce9e071534.png)


オブジェクトの整列や図の挿入コマンドと，pptTeXアドインを追加しています．
また，右端の▽ -> 「リボンの下に表示」を選択することで，ツールバーにアクセスし易くなります．
Unity用のdylibを使ったC++Pluginを作るときに困った


dylib使ったUnity用のC++Pluginを作った際に、DllNotFoundExceptionエラーが出て困ったのでメモ

## Xcode Projectの作成

1. **create new Xcode project > Bundle**で新しいプロジェクトを作る
2. C++のソースコードを適当に書いて追加する
3. 使いたいdylib(hoge.dylib)もプロジェクトに追加する
4. dylibを **Build Phases** の **Copy Bundle Resources** にも追加する
5. ビルドする

![スクリーンショット 2020-03-03 16.50.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45348/fc01f049-d6b4-eae4-75b8-637de3d4498a.png "スクリーンショット 2020-03-03 16.50.48.png")

## Unity Projectにの作成

1. Unityで新しいプロジェクトを作る
2. ビルドしたBundleをプロジェクトに追加する
3. 適当にスクリプトを書く
4. 実行すると **DllNotFoundException error** が出てしまう

<img width="500" alt="スクリーンショット 2020-03-03 17.25.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45348/2f9046af-b0b6-b295-cd5a-cdf39d7a4120.png">

<img width="500" alt="ススクリーンショット 2020-03-03 17.27.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45348/e285afb7-f51a-f966-11db-fc52bda583c1.png">

TestNativeが依存ライブラリのhoge.dylibを読み込めずエラーがでてしまうらしい


## プラグインの依存パスを書き換える

TestNativeがhoge.dylibを読み込めずエラーが出るので依存パスを書き換える

### プラグインの依存パス確認

パスの確認には **otool** を使う

	$ cd TestNative.bundle/Contents/MacOS
	$ otool -L TestNative
	 
<img width="500" alt="スクリーンショット 2020-03-03 17.45.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45348/7f6140da-9dca-1a02-74df-303a14097d9b.png">	 

### プラグインの依存パス設定

パスの書き換えには **install_name_tool** を使う

	$ install_name_tool -add_rpath @loader_path/.. TestNative
	$ install_name_tool -change "@executable_path/hoge.dylib" "@rpath/Resources/hoge.dylib" TestNative
			
### プラグインの依存パスをもう一度確認

	$ otool -L NativePlugin
	
<img width="500" alt="スクリーンショット 2020-03-03 17.37.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45348/814d271e-4203-4269-286a-850f6e00d08d.png">	 

## Unityを実行

書き換わっていることを確認できたらUnityを再起動して実行する


## 参考サイト
http://blog.shogonir.jp/entry/2017/10/26/030028
https://qiita.com/omochimetaru/items/21d662b8df8bce1bc5ca
https://qiita.com/itoru257/items/d36b4e3908a39bfbbb18
https://xanadu6291.stars.ne.jp/?p=726
Flask SQLAlchemyを使ってMySQLに接続

# ファイル構成
```
├── api
|   ├── __init__.py
|   ├── database.py
|   ├── views
|   |   └── user.py
│   ├── models
|       └── user.py
├── app.py
└── config.py
```

# ファイル作成
```python:__init__.py
from flask import Flask
from api.database import db
from .views.user import user
import config

def create_app():
  
  app = Flask(__name__)

  # DB設定を読み込む
  app.config.from_object('config.Config')
  db.init_app(app)
  
  app.register_blueprint(user, url_prefix='/user')

  return app
  
app = create_app()
```

```python:database.py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def init_db(app):
  db.init_app(app)
```

```python:app.py
from api import app

if __name__ == '__main__':
  app.run()
```

```python:config.py
class SystemConfig:
  DEBUG = True

  SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://{user}:{password}@{host}/{db-name}?charset=utf8'.format(**{
      'user': 'user',
      'password': 'password',
      'host': 'localhost',
      'db_name': 'sample'
  })

Config = SystemConfig
```

# モデルの作成
```python:/api/models/user.py
from api.database import db

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    
    def searchBy(id):
        return db.session.query(User)\
            .filter(User.id == id)\
            .one()
```

#  ルーティング作成
```python:/api/views/user.py
from flask import Blueprint
from api.models.user import User

# set route
user = Blueprint('user_router', __name__)

@job.route('/<int:id>', methods=['GET'])
def getUser(id):
    user = User.searchBy(id)
    print(user)
```


# 参考
[Flask + SQLAlchemyプロジェクトを始める手順](https://qiita.com/shirakiya/items/0114d51e9c189658002e)
[VS CodeとFlask-SQLAlchemyでデータベース操作](https://www.atmarkit.co.jp/ait/articles/1808/07/news029.html)
SQLでテーブル作成

#MySQLにおけるテーブル作成

```
CREATE TABLE [データベース名.]テーブル名 (カラム1 型情報, カラム2 型情報, ...);
```

指定データベースに新規テーブルを作成します。「USE」文などで使用するデータベースを指定している場合は、データベース名を省略できます。

##テーブル名の文字数・記号
テーブル名には、クォーテーションなしでテーブル名に使える文字は、英数字、アンダーバー「_」、ドル記号「$」です。ハイフン「-」などその他の記号は、クォーテーションなしで使えないので避けたほうが良いです。さらに、テーブル名は64バイト以内となっています。

##MySQLにおける予約語
また、MySQLにはCHANGE、EXPLAIN、INDEXなどの予約語があり、予約語をテーブル名に使うのは可能であれば避けたほうが良いでしょう。

テーブル名を予約語にした場合は、テーブル名をクォーテーションで囲む必要があります。

#MySQLのテーブル作成時につかえるオプション
テーブル作成時に、オプションを加えることでより詳細な設定をすることができます。今回は、よく使うオプションを紹介します。

##テーブルが存在しなければ作成「IF NOT EXISTS」

```
CREATE TABLE IF NOT EXISTS [データベース名.]テーブル名 (カラム1 型情報);
1
```

テーブル作成時に、同名のテーブルがなければ作成し、テーブルが既に存在する場合はなにもしません。PHPなどのプログラムからデータベースを作成する際などによく使われます。

##nullを許可しない「NOT NULL」

```
CREATE TABLE [データベース名.]テーブル名 (
  カラム1 型情報 NOT NULL,
  カラム2 型情報);
```

カラムにnullを保存することを許可しません。デフォルトでは、nullを許可する設定となっています。
##カラムを連番に設定する「auto_increment」
```
CREATE TABLE [データベース名.]テーブル名 (
  カラム1 型情報 AUTO_INCREMENT,
  カラム2 型情報
);
```
AUTO_INCREMENTが設定されたカラムは、新しい行が追加される毎に１ずつ自動加算される連番のカラムとなります。


##プライマリーキーを設定する「PRIMARY KEY」

```
CREATE TABLE [データベース名.]テーブル名 (
  カラム1 型情報 NOT NULL PRIMARY KEY,
  カラム2 型情報
);
```
カラムの値を重複不可とする場合は、プライマリーキー（主キー）を設定します。この時、同時にNOT NULLも設定する必要があります。さらに、プライマリーキーの設定をすると、そのカラムに対してPRIMARYという名前のインデックスが作成されます。

##ユニークキーを設定する「UNIQUE」

```
CREATE TABLE [データベース名.]テーブル名 (
  カラム1 型情報 UNIQUE,
  カラム2 型情報
);
```
ユニークキーは、カラムの値を重複不可とするという点ではプライマリーキーと同じです。ただし、ユニークキーはnullを保存でき、なおかつnullの値だけは重複可となっています。

##カラムのデフォルト値を設定する「DEFAULT」

```
CREATE TABLE [データベース名.]テーブル名 (
  カラム1 型情報 DEFAULT デフォルト値,
  カラム2 型情報);
```
カラムへのデータ挿入時に、値が指定されなかった場合にデフォルトで設定される値を指定します。
##カラムにインデックスを設定する
```
CREATE TABLE [データベース名.]テーブル名 (
  カラム1 型情報,
  カラム2 型情報,
  カラム3 型情報,
  INDEX(カラム1, カラム2 ...)
);
```
指定したカラムに対してインデックスを作成します。また、インデックスは「CREATE INDEX」でも作成できます。

##ユーザーテーブルを作成する例
以上のことを踏まえて、userテーブルを作成するクエリの例を紹介します。

```
CREATE TABLE IF NOT EXISTS user (
  ID    int(11) unsigned AUTO_INCREMENT NOT NULL,
  score int(11) default '0',
  name  text NOT NULL,
  PRIMARY KEY (ID)
);
```
このクエリは以下のようなテーブルを作成します。

・ID、score, nameの3つのカラム
・IDにAUTO_INCREMENTとプライマリーキーを設定
・scoreにデフォルト値0を設定
・nameはnull不可

##最後に
以上MySQLでテーブル作成をする方法を紹介しました:open_hands:
WSL2のメモリ割り当て量を変えたい

# 概要
.wslconfigというファイルに記述することで、メモリの割り当て量を設定できます。

# 設定
Windows側のホームディレクトリ(厳密には```%UserProfile%```)に.wslconfigファイルを作成します。

```:~/.wslconfig
[wsl2]
memory=8GB
```

ファイルを作成したら、PowerShellからWSLを再起動します。

```powershell
wsl --shutdown
```

# 参考
Windows Subsystem for Linux のリリース ノート
[https://docs.microsoft.com/ja-jp/windows/wsl/release-notes](https://docs.microsoft.com/ja-jp/windows/wsl/release-notes)
部分テンプレートとは

##部分テンプレート
同じHTML構造の部分を共通化することによって、ビューファイルを作成することができます。この共通化された部分を、部分テンプレートといいます。
部分テンプレートを使用した場合、HTML構造を他のビューでも使いまわすことができます。
部分テンプレートのメリットとして
**繰り返し書くコードを一回で済ませられる**
**修正するときに修正箇所が少なく済む**
というメリットがあります。
部分テンプレートのファイル名は必ずアンダーバーから始まります。
例えばモデルがPostだとしてapp/views/posts/index.html.erbを部分テンプレートするとき、共通化してる部分を切り取りapp/views/posts/_post.html.erbに貼り付けます。
##renderメソッド
部分テンプレートを呼び出す際に利用するメソッドです。
partialオプションを付けることで、部分テンプレート名を指定し、部分テンプレートを表示することができます。partialは部分的という意味です。
【例】

```
<% render partial: "sample" %>
```
localsオプションを付けることで、部分テンプレート内でその変数を使えるようになります。
【例】

```
<% render partial: "sample", locals: { post: "hoge" } %>
```
部分テンプレート内においてhogeという文字列の代入されたpostという変数が使えるようになります。
app/views/posts/index.html.erbに追記していきます。<% @posts.each do |post| %>、<% end %>は共通化してない部分なので部分テンプレートはしていません。
【例】

```app/views/posts/index.html.erb
<% @posts.each do |post| %>
  <%= render partial: "post", locals: { post: post } %>
<% end %>
```
上記の{ post: post }の右側のpostはeachメソッド内の変数としてのpostでpostのインスタンスを示しています。一方、左側のpostは部分テンプレート内での変数の名前を表しています。

今回はapp/views/users/show.html.erbも部分テンプレートするとして
【例】

```app/views/users/show.html.erb
<div class="XXXX">
  <%= @user.nickname %>さんの投稿一覧
</div>
<% @posts.each do |post| %>
  <%= render partial: "posts/post", locals: { post: post } %>
<% end %>
```
違うフォルダ内の部分テンプレートを呼び出すときはposts/postのようにどのフォルダの部分テンプレートを使用しているかを記載します。
postsはhttp://localhost:3000/postsでpostはフォルダの部分テンプレート名です。
WSLにDjangoをインストール

Ubuntu18.04を選択
チュートリアルに従ってpipでpython3をインストール
python manage.py startprojectでプロジェクトを作成
python manage.py startappでアプリケーションを作成

ここまで進んだら、VSCode側の設定を行う。
VSCodeのremote extensionを使って、WSL接続ができるように。
且つ、PythonのExtensionとDjangoのExtensionもインストール。
RemoteでWSLを選択して開き、Djangoのホームディレクトリを開く。（普通は~/、つまり/home/ubuntu）
デバッグ実行でDjangoを選択できるので、それを選択すると、http://localhost:8000で起動するので、ブラウザから開くことを確認する。

MySQLのインストールはUbuntu18.04のインストール方法に従う。
ユーザー作成、DB作成、ユーザーの権限付与等を実施する。
MySQLの文字コードをutf8mb4に変更するのを忘れずに。
WSLだと、/var/lib/mysql を作らないといけないので、それも忘れずに。（WSL MySQLで検索するとヒットする)

DBの設定はsetting.pyに記述SQLITE3からMySQLへ変更。
この時、python側にインストールするものとして、
PyMySQLを紹介しているサイトがあるが、(pip install PyMySQL）これは古い情報。
今現在は、mysqlclientである。（pip install mysqlclient)。
但し、先にpython3-dev libmysqlclient-dev をインストールしておかないといけないので、注意。(sudo apt install python3-dev libmysqlclient-dev)

データベースのmigrationを実行し、adminのテーブル作成をすること。
python manage.py migrate 
その後、管理用アプリケーションのログインユーザーを下記コマンドで作成する。
python manage.py createsuperuser