OmniAICreator/Qiita-1.07M huggingface dataset:
Kindleの自動スクショ保存プログラム

# 初めに
Kindle本を購入したけどアカウントが消えて今までの本が見れなくなった、、
保存しておけばよかった、、
となったので、Kindle本を保存しておくためのプログラムを作成しました。

MacにおけるKindleAppの、全ページの画面のスクリーンショットを自動で撮ることを目的としています。

今回は簡単のため、ページの大きさにフィットさせるのではなく、画面全体をスクリーンショットすることで実装しています。

保存した画像ファイルをpdf化する方法は以下の記事に書きました。
[Kindleの自動スクショ保存プログラム 〜PDF化編〜](https://qiita.com/yassyyuki/items/f46760cfa0b8ef2c3d38)


# 使用方法

プログラムをインストールしましょう。

```
git clone https://github.com/yassyyuki/save_kindle_book.git
```
インストールできない方は、以下のコードをコピペして、`save_kindle_screen.py`ファイルを作成してペーストしましょう。

```py
import pyautogui
import time
import os
import datetime


# ページ数
page = 5
# スクショ間隔(秒)
span = 1
# 出力フォルダ頭文字
h_foldername = "output"
# 出力ファイル頭文字
h_filename = "picture"


# ５秒の間に、スクショしたいkindleの画面に移動
time.sleep(5)

# 出力フォルダ作成(フォルダ名：頭文字_年月日時分秒)
folder_name = h_foldername + "_" + str(datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
os.mkdir(folder_name)

# スクショ処理
for p in range(page):
    # 出力ファイル名(頭文字_連番.png)
    out_filename = h_filename + "_" + str(p+1).zfill(4) + '.png'
    # 画面全体のスクリーンショット
    s = pyautogui.screenshot()
    # 出力パス： 出力フォルダ名 / 出力ファイル名
    s.save(folder_name + "/" + out_filename)
    # 次のページ
    pyautogui.keyDown('left')
    # 画面の動作待ち
    time.sleep(span)

```

使用するライブラリが実行環境にない方は以下のようにしてライブラリをインストールしましょう。

```
pip install pyautogui
pip install time
pip install os
pip install datetime
```

次に、保存しておきたいKindle本を選び、フルスクリーンで１ページ目を開いておきましょう。

次に、`save_kindle_book.py`ファイルの上の方にある、

```py
page = 5 # ここをページ数に設定し直す
```
の部分の数値を、自分の保存しておきたいKindle本のページ数に設定し直しましょう。
このページ数は、どれだけ範囲を１ページ分として開いているかが人によって様々なので、大きめに設定しておいて、余分な分はあとで削除するのが楽です。

設定し終えたら、ターミナル上で実行しましょう。

```
python save_kindle_book.py
```

実行したら、５秒以内にKindle本を開いた画面に移動し、後はそのまま放置です。

実行し終えると、新しくディレクトリが作成され、その中にスクリーンショットが保存されています。

`１秒×ページ数`が目安の時間がかかります。

# 注意
Kindle画面をスクリーンショットし、個人で楽しむのは問題ありませんが、他人に譲渡することは違法ですのでご注意ください。

# 最後に
最後までご覧いただきありがとうございました。
リンクに飛べるのをわかりやすくする方法

# プログラミングの勉強日記
2020年7月8日　Progate Lv.148

#目的
　[こちらの記事](https://qiita.com/mzmz__02/items/2ac88037d8f99bee5ac8)で画像にリンクを貼る方法やCSSでリンクデザインを変更する方法を説明しているので、こちらも読んでみてください。

　文字に下線がある場合やリンクの文字だけ色が違う場合はリンクが貼られていることがわかりやすいが、画像にリンクが貼られていることは物によっては作成者にしかわからない場合がある。なので、今回はリンクに飛べることをわかりやすくするために用いた方法を紹介する。

#文字にリンクを設定している場合
　リンクに飛べるのをわかりやすくしたいけど、見た目上下線を付けたくないし、色も揃えたいから変えたくない、、

<img width="938" alt="0708-2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/29aed11b-db23-91e2-80c8-c6106e578801.png">

ヘッダー部分とHelloの下に書かれてるResumeとWorksはリンクに飛べるようになっている。そこで、カーソルを合わせたときにだけ下線を表示するようにした。

<img width="938" alt="0708-3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/31ba4bd3-ead8-57c9-d9ba-1074986540a2.png">

この上の写真ではヘッダーのResumeにカーソルを合わせている。

##コード
　カーソルを合わせたときのデザイン変更はセレクタに`:hover`と書くだけ。今回は標準の状態では`text-decoration: none;`で下線部を消去しているので、マウスカーソルをリンク上に乗せたときに`text-decoration: underline;`を指定して下線部を表示させている。

```html:HTMLファイル
<nav>
  <ul>
    <li><a href="index.html">Top page</a></li>
    <li><a href="resume\index.html">Resume</a></li>
    <li><a href="works\index.html">Works</a></li>
  </ul>
</nav>
```

```css:CSSファイル
a {
    text-decoration: none;
}

a:hover{
    text-decoration: underline;
}
```

#画像にリンクを設定している場合
　画像のリンクは製作者にしかわからない可能性もある。よって、文字のリンクのときよりもデザインの工夫が必要であると感じた。
　今回は下の写真のようにWebサイトの写真にリンクを貼っている。

<img width="937" alt="0708.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/b9e23dd5-2506-6325-87a0-c364ca504231.png">

写真で見るとわかりにくいが、画像にカーソルを合わせると影を消して、画像を大きくしている。

<img width="947" alt="0708-1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/827a0a8e-9ba1-9aaf-0ef6-b0d8e98ea5a9.png">

Twitterで動画を乗せたので詳しくはこっちを見てください↓↓

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">画像クリックでリンクに飛べるのを分かりやすくしました！ <a href="https://t.co/0AE0SQNt3b">pic.twitter.com/0AE0SQNt3b</a></p>&mdash; mai (@mai74747304) <a href="https://twitter.com/mai74747304/status/1280839734739136512?ref_src=twsrc%5Etfw">July 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##コード
　文字のリンクと同様に、カーソルを合わせたときのデザイン変更はセレクタに`:hover`と書く。影はCSSで`box-shadow`を指定することでつけられる。影を消すときは`box-shadow: none;`を指定する。
　`transform:scale() `で要素を拡大縮小することができる。()に数値を指定することで拡大縮小をできる。scale()関数では2つの数値を使う。つ目の数値はX方向、2つ目の数値はY方向の比率で、2つ目の数値を省略すると最初の値と同じになる。


```html:HTMLファイル
<img src="../photo/travel.PNG" class="button buttonTravel">
```

```css:CSSファイル
.buttonTravel{
    cursor: pointer;
    box-shadow: 10px 10px rgb(120, 162, 224);
}

.buttonTravel:hover{
    cursor: pointer;
    /* 影を消す */
    box-shadow: none;
    /* 拡大する */
    transform: scale(1.1);
}
```
初心者によるプログラミング学習ログ 364日目

#100日チャレンジの364日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
364日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>昨日の作業・やったこと⇩<br><br>●寝る直前の筋トレ5分<br>●ブログ記事1記事作成<br>●プログラミング学習364日目 1.5h<br>・udemyでフロントエンド講座<br><br>筋トレはしたが、読書せずに寝落ち<br>あと、クーラーこわれた。<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアとつながりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a><a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@社畜✕投資✕ブロガー (@ppmp65) <a href="https://twitter.com/ppmp65/status/1280596651963379712?ref_src=twsrc%5Etfw">July 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【第1回_もくもく会_超初心者】Vue.jsを学習する_インストールや準備

# Vue.js
JavaScriptのフレームワークです。
もくもく会をしていたので、環境を整えて学習していきます。

#### Vue.jsのいいとこは？
[vue.js公式サイト](https://jp.vuejs.org/index.html)に記載のある通り、「親しみやすく」、「融通が効いて」、「高性能」とあります。まさにこれがいいとこだと思います。
フロントエンド開発においてデータを表示と分離して開発する事が行えるので開発しやすいことはメリットです。

また、vueは[様々なライブラリ](https://github.com/vuejs/awesome-vue)が充実しています。
昨今では、気軽にjQueryの実装ができるために、開発者に依存した書き方で、物によってはコードが分かりづらい時があります。
vue.jsなら、書き方の決まりによって、自分も他者も分かり易くなります。

環境の準備をしたいと思います。

# NPMを用いたVueのインストール(Mac OS)
NPM(Node Package Manager)を利用すると、とても便利です。
NPMでVueをインストールするのに、Node.jsがインストールされてる必要があります。

#### Node.jsのバージョンを確認
```
$ node -v
```
### もしNode.jsがインストールされていなければ....
Homebrewのインストールをしてから、インストールをしましょう。
Homebrewがインストールされていたら、nodebrewからインストールしてください。

#### (インストールしてなければ)Homebrewのインストール
```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

#### Homebrewのバージョンを確認
```
$ brew -v
```
brewコマンドが使えていなければ、Homebrewはインストールできていないです。

#### Node.jsのバージョン管理のためにnodebrewをインストール
```
$ brew install nodebrew
```

#### nodebrewコマンドで確認
```
$ nodebrew -v
```
#### Node.js安定版のインストール
node.jsをインストールする時、最新版や安定版など、バージョン指定でインストールが可能ですが、ここでは安定版のインストールを行います。

```
nodebrew install-binary stable
```

#### Pathを通す(nodeコマンドが使えるようにします)
```
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
```

#### vue-cliのインストール
Vue.jsを使う環境を準備するためのコマンドラインインターフェースをインストールします。

```
npm install -g @vue/cli
```

#### プロジェクトを作成する
```
vue create vue_lesson2
```

#### vs codeを立ち上げる
```
code .
```

#### サーバーを立ち上げる
```
npm run serve
```
ローカルで見れるようになります。
http://localhost:8080/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20742/e6faac53-3dcb-d501-dc03-8e39637f8e9c.png)

次回以降、Vue.jsの中身について学習していきます(>_<)!
[Azure] サブスクリプション間やテナント間でSQL Databaseを中身ごとコピーする方法

## 要約

以下のコマンドをコピー先のSQL Serverで実行する

```
CREATE database [コピー先DB名] AS COPY OF [コピー元SQL Server名].[コピー元SQL Database名]
```

※ 以下注意点

- コピー元のSQL Serverにコピー先SQL Serverのログインユーザーと**同じユーザー名**、**同じパスワード**のユーザーを作成しておく必要がある
- 上記のユーザーは両方のSQL Serverで**`dbmanager`ロール**か**サーバー管理者**である必要がある
- 上記のユーザーはコピー元SQL Databaseで**`db_owner`ロール**である必要がある


## ちょっと詳しく

コピー元SQL Server、SQL Databaseとコピー先SQL Server、ログイン情報を以下のように仮定します。

- コピー元SQL Server
  - Server名：`oldserver`
  - コピー元SQLDB名：`olddatabase`

- コピー先SQL Server
  - Server名：`newserver`
  - ログインユーザー名：`newserveradmin`（サーバー管理者）
  - ログインユーザーパスワード：`fV7pSNBr`


### 1. コピー元SQL Serverにログインユーザーを作成
コピー元SQL Server(`oldserver`)にコピー先SQL Serverのログインユーザーと同名のログインを作成します。SSMSやAzure Dara Studioなどで`oldserver`にログインして以下のSQLクエリを実行します。

```
USE master;
CREATE LOGIN newserveradmin
WITH PASSWORD = 'fV7pSNBr'
```

masterDBにユーザーも作成します。この時ロールを`dbmanager`にしておく必要があります。

```
USE master;
CREATE USER newserveradmin FOR LOGIN newserveradmin;
ALTER ROLE "dbmanager" ADD MEMBER newserveradmin;
```

### 2. コピー元SQL Databaseにユーザーを作成
コピー元SQL Database（今回は`olddatabase`）にもユーザーを作成します。この時のロールは`db_owner`にする必要があります。以下のSQLクエリを実行します。

```
USE master;
CREATE USER newserveradmin FOR LOGIN newserveradmin;
ALTER ROLE "db_owner" ADD MEMBER newserveradmin;
```

### 3. SQL Databaseをコピー
SSMSやAzure Dara Studioなどでコピー先SQL Server(`newserver`)にログインします。ログインするユーザーは先ほどコピー元SQL Serverに作成した`newserveradmin`で。
そして以下のSQLクエリを実行します。

```
CREATE database newdatabase AS COPY OF oldserver.olddatabase
```
NavigationControllerで戻る画面を自在に書き換える

NavigationControllerを利用したページ移動をしていて、戻るページのスタックを自分の好きなように書き換えたくなった時があった。2ページ前に戻るとか、ある条件を満たした時だけ戻れるページの上限が変わるなど。


## NavigationController.viewControllerの仕組み
```Swift
navigationController?.viewControllers // [1pページ目, 2pページ目, 3pページ目, 今のページ]
```

NavigationControllerは上記のような感じで配列としてこれまで遷移したページを持っている。
基本的にはこれをpopしたりpushしたりする事で１画面遷移する。

## ViewControllerが入った配列
ViewControllerが入った配列なので、この配列を好きなように操作してやれば戻るページを書き換えられる。

ただ、基本的にはスタックとして使う事を想定しているはずなので行儀は良くない気がする。

## 例
UIViewControllerクラス内で

```Swift
let fugaView = self.storyboard?.instantiateViewController(withIdentifier: "FugaViewWrapController") as! FugaViewController
let hogeView = self.storyboard?.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController            
            
self.navigationController?.viewControllers = [fugaView, hogeView, self]
```

こうしてやると、これまでどんな遷移をしていようが次 hogeView → fugaView の順番に戻るようになる。

こんな感じで好きなようにカスタマイズ出来る、と思う。多分。
【インデント】私がタブインデントをめちゃくちゃオススメする理由

ソースを見やすくする工夫はいくつかある。
そのうちの1つが「インデント」だ。
このインデントについて説明する。
また、この記事でいうタブとは「ハードタブ」で、次のラインに揃えるものである。
# インデントとは？

```JavaScript:JavaScript
 let a = Math.random(); 
 if(a < 0.5){
    console.log("表");
 }else{
    console.log("裏");
 }
```

ただのコインの表と裏を出すようなプログラムだ。
とりあえず、このサンプルコードでは、見やすくするためにインデントを入れている。
if文の{}の中が右に来ているだろう。それが**インデント**だ。

もしこのインデントがなかったらどうなるだろう。

```JavaScript:JavaScript
 let a = Math.random();
 if(a < 0.5){
 console.log("表");
 }else{
 console.log("裏");
 }
```

このたった数行のコードでも読みやすさがガラッと変わる。
これがもし、何百、何千行を超えるコードならどうだろう。背筋がヒヤッとする。
ソースコードにインデントは必須だ。
![asdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377526/9c4ea2f3-14f9-247c-c8f9-c692c90bfad5.png)

# インデントの種類
インデントの付け方は人それぞれ。
タブ派もいるがスペース派もいる。同じスペース派でも、1文字か2文字か4文字がなど、文字数も色々ある。
そしてわたしがおすすめするのは、「タブ」だ。

# タブインデントのメリット
## キーを打つ回数が少ない
タブは、1ブロックの字下げなら1回キーを押すだけでいい。
2スペース派の2倍はやく、4スペース派の4倍速い。
そして、別に大した問題ではないのだが、今何回打ったかを気にしなくても良くなる。
## 間にマウスカーソルが行かない
タブは1文字カウントのため、タブのなかにカーソルがいくことはない。
インデントを消すときに、スペースだと1つ残ったりする。
ストレスがたまると、継続することが困難になる。
ストレスのもとは排除すべきだ。

【追記】スペースも、Shift + Tabのインデント削除で消すことができるそうです。

## 他の人のコードを見たときに見やすくなる
タブは、エディタからすれば「\t」である。
\tは、使う人の環境によって幅が変わるから、**その人にあった見え方**がする。
スペースインデントは、だれが見ても同じく見えるため、自分のインデントの幅が違う人だと違和感を覚える。

# まとめ
インデントにタブを使うと、次のようなメリットがある。

- キー打鍵数が減る
- マウスカーソルが合う
- 他の人にコードを見せやすい

メモ帳のデフォルトタブ幅が8文字なのはなぜだろうか。
別にコーディングで使いはしないが、あるYouTuberの「メモ帳でC#入門」をみてふと感じた。
設定で変更することもできるが、デフォルト時から少なくしていても、ほとんどの人は損をしないのに...
Ubuntu 20.04 LTSインストール時の初期設定メモ

Ubuntu20.02を3台くらいのPCにInstallして設定したので、自分的にコスパが良い設定をまとめておきます。
誰かの役に立てれば嬉しいです

#最初の最初にやること
- タッチパッド、マウスの速度をMAXにする
- DarkMode
- terminal 英語化
  - export LANG=en_US.UTF-8
  - .bashrc に書いておく
- フォルダ類の英語化
  - LANG=C xdg-user-dirs-gtk-update
- 隠しフォルダの表示


![Selection_399.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149791/c9d8a73f-63d8-28f6-0f96-0eb65773e6c2.png)

# ソフトウェアとアップデートの設定
![Selection_921.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149791/1840dd3f-e826-84b1-a5c0-72055aa96ad5.png)
![Selection_922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149791/f663e301-f90d-7297-8e0a-5b585d5b2dc9.png)

# Ubuntu SoftwareからInstall
## Terminator
分割できたりと何かと便利なTerminal
https://gnometerminator.blogspot.com/p/introduction.html
![](http://1.bp.blogspot.com/-pBBJoLyOUbs/Ti9BfXqRu7I/AAAAAAAADUk/Uw-4Zy9pAQU/s320/2008-08-17-terminator.png)

## gnome tweak
`capsLock to as ctrl`
でcapsLackをCtrlに変更
## Shutter
部分スクリーンショットやその後の軽い編集などができて便利。
ドラッグアンドドロップでスクショをUploadできるのも良い。
https://shutter-project.org/
![](https://shutter-project.org/wp-content/uploads/key_feature_032.png)

## CopyQ
コピーしたものを指定の数覚えてくれている便利ツール

https://copyq.readthedocs.io/en/latest/installation.html
おすすめ設定は下記から
https://yuis-programming.com/?p=1718	

# .depファイルとしてDLしてからInstallするもの
## Chrome
個人的にはChromeが一番好き
https://www.google.com/intl/ja_jp/chrome/

## VSCode
Ubuntu Storeにもあるが日本語入力でバグがある。
.depファイルからのInstallであればバグが治っている。
https://code.visualstudio.com/download

## Slack
こちらもVSCode同様、Ubuntu Storeにもあるが日本語入力にバグがある
https://slack.com/intl/ja-jp/

#その他
## Homebrew on Linux
パッケージ管理ツール
もともとMacユーザなのもあり、Ubuntuでもbrewが使えるのはありがたい。
https://docs.brew.sh/Homebrew-on-Linux

※Installが終わったら一回再起動が必要
## Homebrewで入れるもの
- Go
- Node.js
- yarn
- python
- fish
    - fish_configで適当に便利そうなものを設定
    - pythonを入れてからでないとErrorが起きるので注意

## Docker
https://docs.docker.com/engine/install/ubuntu/

## wine	
Windowsアプリケーションを動かすため。
現在はwine5のVersionになっており、かなり安定しているように思われる
https://wiki.winehq.org/Ubuntu

## Keyboardレイアウト変更
Mozcのツール→プロパティの設定から
henkan →ひらがな入力
muhenkan→IME無効化
すべての↑のKeyに同等の割当をする

※設定でフォントの設定を押したあとでないと出てこないため注意
Python 標準入力 まとめ

**Python3で外部からの入力値を扱うときのメモ**
キーボード入力値や、Paiza などのスキルチェックでの入力値を取得する方法を初心者なりにまとめてみた

#1 基本

入力値を読み取るには `input()` 関数を使う。
`input()`のカッコ内に文字列を入力すれば、その文字列がキー入力待機中に表示される
　　例) <img width="255" alt="スクリーンショット 2020-07-08 11.15.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669543/9b3e9dd0-31f0-0e93-965a-992e3aa579fd.png">

読み取れるのは(スペースなども含めた)一行のみの入力
→ 競プロなどで複数行入力されるときは、一行ごと(上から順に)に読み取る必要㊒

>a
>12
>abcd ef


が与えられたときは、

```Python:
A = input()
B = input()
C = input()

print(A)    #出力値: a
print(B)    #出力値: 12
print(C)    #出力値: abcd ef
```
となる

*注) `input()` では str (文字列) 型 として取得されるので、場合に応じて型変換が必要*

---

**参考**

| 欲しいデータ型 | 記述例 |
|:------------------:|:------------------:|
| 文字列型 | s = input() |
| 整数型 | n = int(input()) |
| 浮動小数点数型(小数値) | f = float(input()) |

---

#2 複数値の入力

##2-1　一行に数個のデータが与えられるとき


>N(1) N(2) N(3) …

データ数が少ないときは、リスト化するよりも変数に直接代入した方がラクちん

```Python:
A, B, C, … = map(int, input().split())    #データ数Nは不要
```
`split()` は カッコ内に入力した文字で文字列を分割してくれる。
なお、初期値(未記入のとき)ではスペースで分割される。
　　例) カンマで区切られた文字列 → `split(',')`

---

##2-2　データ数が多いとき
###2-2-1 横1列のとき


>N(1) N(2) N(3) N(4) … N(n)


このときは、リスト化する

```Python:
Nums = list(map(int, input().split()))
```

文字列ならば `int` ではなく、 `str` を使う


###2-2-2 縦１列のとき

>N
>N(1)
>N(2)
>︙
>N(n)

このときは、(1)リスト化する、もしくは (2)上から順に1個ずつ処理する

```Python:方法1
Nums = []
n = int(input())
for i in range(n):
    Nums.append(int(input()))   # Nums+=[int(input())] でも可
```
`append()` は、カッコ内のデータをリストの最後尾に添える関数
リストを追加すると、リストのまま追加される。
　　例) [1, 2, 4, [2, 3]]
`extend()` を使えば、リストの要素だけがリストに追加される

```Python:方法2
n = int(input())
for i in range(n):
    a = int(input())
    #以下、N(i) に対する処理内容を書く
```
#3　特殊な入力
##3-1　データ数が分からない縦列の入力

>N(1)
>N(2)
>N(3)
>︙
>N(n)

try-except構文を使い、データが入力されている間だけリストに追加する

```Python:
Nums = []
while True:
    try:
        Nums.append(int(input()))
    except:
        break
```


##3-2　多次元配列

>N
>a(1) b(1) c(1)
>a(2) b(2) c(2)
>︙　　︙　　︙
>a(n) b(n) c(n)

このときは、先にリストを作っておきfor文で代入

```Python:
n = int(input())
a = [0] * n
b = [0] * n
c = [0] * n

for i in range(n):
    a[i], b[i], c[i] = map(int, input().split())
```
Vue Router 直接URLでアクセスするとエラーが起きる

Vue.jsを使っていて、通常の画面遷移のルーティングは問題無いがURLを直打ちすると

```JavaScript
Uncaught SyntaxError: Unexpected token <
```

というエラーになってしまう現象が起きた。

## :bomb: index.html内のパスの設定が原因
これを

```
<script type="text/javascript" src="js/app.js"></script>
```

このように変えてやるだけ

```
<script type="text/javascript" src="/js/app.js"></script>
```

上のパターンだと直接URLを叩いた時とリンクから画面遷移した時で見ている場所が変わってしまう。
Rubyで配列の中の文字列を数値に変更する方法

```ruby
array = ["1", "2", "3", "4", "5"]
```

のように配列の中に文字列で数字の値がある時に、配列の文字列を数値に変更する方法を書きます。

#for文の方法

```ruby
array = ["1", "2", "3", "4", "5"]

intArray = []
for n in array
  intArray.push(n.to_i)
end

# intArray => [1, 2, 3, 4, 5]
```

`array`とは別の配列`intArray = []`を作成します。
`array`の値を`n`で取得して、`to_i`で文字列を数値に変更、`push`で`intArray`に値を代入していくという処理を繰り返します。

#mapメソッドの方法

```ruby
array = ["1", "2", "3", "4", "5"]

intArray = array.map{ |n| n.to_i }

# intArray => [1, 2, 3, 4, 5]
```

または

```ruby
array = ["1", "2", "3", "4", "5"]

intArray = array.map(&:to_i)

# intArray => [1, 2, 3, 4, 5]
```

`map`メソッドで配列`array`を繰り返し処理して値を`n`という変数に代入して、実行したい処理として`n.to_i`または`&:to_i`という処理を実行しています。
実行した処理を`intArray`に代入していきます。
こちらの場合は予め`intArray = []`のように定義しておく必要はありません。

`map!`を使用する方法もあり、こちらの場合は

```ruby
array = ["1", "2", "3", "4", "5"]

array.map!{ |n| n.to_i }

# array => [1, 2, 3, 4, 5]
```

のように`array`の配列を書き換えることができます。

#参考サイト
https://techacademy.jp/magazine/19868
https://uxmilk.jp/21695
Macでコマンドラインからsleep

コマンドラインからMacをスリープさせる時(ターミナル使ってる時、いちいちマウスとかに手を伸ばしてメニューからスリープを呼び出すのがめんどくさいダメ人間)、
よくこのコマンドが紹介されています。

~~~~
$ osascript -e 'tell application "Finder" to sleep'
~~~~
Finderを呼び出してスリープさせるのですが、10.9以降ではosascriptを使わなくてもスリープさせられるんですね。

~~~~
$ pmset sleepnow
Sleeping now...
~~~~
(コマンドを実行した時点で画面が真っ暗になります。"Sleeping now..."はスリープから復旧した時ターミナルに表示されています)

(良い子のみんなはしないと思いますが)sshとかでリモートでログインしていて、うっかり上記コマンドを実行すると「あ…」ってことになると思います。
「システム環境設定」の「ネットワークアクセスによるスリープ解除」にチェックを入れて、そとからsshで入ろうとしたのですが、反応ありませんでした。
pmsetのmanを見ると

~~~~
networkoversleep - this setting affects how OS X networking presents shared network services during system sleep. This setting is not used by all platforms; changing its value is unsupported.
~~~~

とあるので、すべての環境で「ネットワークアクセスによるスリープ解除」は有効になるとは限らないようです。手元の環境(iMac+10.13)ではスリープ後、外部からsshで入れませんでした(Port Scanしたらポートも開いてなかったので完全に寝落ちしてましたね)

リモートでディスプレイだけオフにする場合は以下コマンド(使い状況はあまり無いと思いますが)。

~~~~
$ pmset displaysleepnow
~~~~

ちなみにsleepコマンドは、あくまでもコマンド実行の際、次のコマンドまで待機させるだけ。

~~~~
$ date +%H:%M:%S && sleep 5 && date +%H:%M:%S
20:00:55
20:01:00
~~~~
Eclipse 2020を使っていたらビルドエラーが止まらなくなった話

先日JavaのSpringチーム開発を行っていたところ私を含むチームメンバーの２人に同じエラーが発生しほとんど操作不能になりました。
根本的な原因は分かりませんが結論からいうと最新版のeclipseだけに発生する現象だったようです。

###環境
- IDE
    - Eclipse 2020-6
    - SpringToolSuite4(Eclipse4.16)
- Java
    - 11 
- フレームワーク
    - Spring Boot
- OS
    - Windows / Mac共に発生 



###現象
スコープ外のオブジェクトへの参照やstaticメンバの参照エラーなどのコンパイルエラーが発生する状況で自動ビルドが行われると以下のようにビルドエラーが繰り返されてしまう。
Eclipseの再起動もしくはプロジェクトのプロパティ→builderからJava builderを外す[^1]まで止まらない。
[^1]: これをするとIDEがただのメモ帳と化す。
<img width="413" alt="スクリーンショット 2020-07-07 17.13.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658039/c8dc1c68-6488-e4bc-56bc-34716dd18f0f.png">

エラー詳細には
'Errors running builder 'Java Builder' on project 'なんとかプロジェクト'. java.lang.NullPointerException'
つまり「Javaビルダーの実行中にヌルポが発生した」とのこと。


###試した処置
- プロジェクトをワークスペースから完全に削除後再度 git clone
- JDKバージョンの変更
- 依存関係の再ビルド&再インストール

どれも全てダメでした。

##解決方法
Eclipseのバージョンを2019_12に落とした。

たったこれだけですが全く同じプロジェクトなのにビルドエラーが出なくなりました。
メンバー二人とも同じ状況なのでおそらくIDEのバグだと思います。
同じようなエラーを解決した記事が見つからなかったので共有します。
【Laravel】Bladeでレイアウトを作成する

#はじめに
LaravelのBladeテンプレートで使えるレイアウトの「継承」を利用し、複数の「セクション」を組み合わせてレイアウトを作成する機能をまとめます。

#図説
![コメント 2020-07-08 181953.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425289/d2d8d476-f647-a616-14e3-7fd28a5c3afe.png)

##extend
最初に記載すべき項目としてレイアウトの継承設定があります。

```php
@extends('layouts.*')
```
部品側のファイルに記載することで、土台側（親）のファイルを読み込んでレイアウトを継承します。
これを書かないとそもページ自体を作ることができないので必須です。

##sectionとyield
**section**

```php
@section('content')
@endsection
```
@sectionはページで表示するコンテンツの区画を定義する事ができ、同じ名前のyieldにはめ込まれます。

**yield**

```php
@yield('content')
```
@yieldはコンテンツの配置場場所を定義するもので、同じ名前のsectionが部品側のファイルにある場合コンテンツの内容が表示されます。

titleの様に変数名を渡す場合は@endsectionのような閉じタグを用意する必要がなく@sectionタグだけでコンテンツを定義する事ができます。

**parent**

```php
@section('sidebar')
  @parent
@endsection
```
sectionに対応する配置場所の定義はyieldが行いますが、今回「sidebar」にはyieldではなくsectionが用いられています。この場合ははめ込みではなく既にsection内にあった内容を上書きする形になります。
そうすると親のsectionにもともとあった内容が消えてしまうので、親のsection内容を残して表示させたい時は、子のsectionの中に「@parent」ディレクティブを用意してあげる事で、親のsection内容がそこに表示されるようになります。

##include
```php
@include('名前')
```
@includeはsectionのようにコンテンツとしてではなく、より単純にテンプレートをただはめ込んで表示させたい場合に使用します。なのでサブビューのファイルではコンテンツをsectionで囲う必要がありません。
includeでもって来たビューの内容を「サブビュー」といいます。
【Ansible】templateモジュールから独自関数を呼び出したい（macro）

###はじめに
<バージョン>
ansible 2.9.1

templateモジュールを使っていると、独自関数を作って呼び出したい場面が出てくると思います。
jinja2にはmacroという機能があり、独自関数を書いたファイルを他のj2ファイルから呼び出して
使えるようですが、templateモジュールでも使えるのか実際にやってみます。

###参考ファイル
___（1）Playbook___

```yaml:template_sample.j2
---
- name: template TEST
  hosts: localhost
  gather_facts: no
  vars:
    ansible_python_interpreter: /usr/bin/python3
  tasks:
    - name: 'template'
      template:
        src: base.j2        # macroを呼び出す元となるplaybook
        dest: result.txt
```

___（2）j2ファイル（base.j2：呼び出し元となるファイル）___
1行目：このj2ファイルと同じディレクトリに入っている、macro.j2内にあるmacroを読み込む
2行目：macro.j2内にあるtest1という独自関数に変数を引き渡す
3行目：macro.j2内にあるtest2という独自関数に変数を引き渡す

```jinja:base.j2
{% import "macro.j2" as macro %}
{{ macro.test1("Taro", "Tokyo") }}
{{ macro.test2("Hanako", "tennis") }}
```

___（3）j2ファイル（macro.j2：独自関数が書かれたファイル）___
関数の書き始めは「macro 関数名(変数1, 変数2,…)」として、
最後に「endmacro」で閉じましょう

```jinja:macro.j2
{% macro test1(var1, var2)%}
My name is {{ var1 }}
I live in {{ var2 }}
{% endmacro %}

{% macro test2(var1, var2)%}
My name is {{ var1 }}
I like {{ var2 }}
{% endmacro %}
```

###実行結果
想定通り実行することが出来ました。
同じような記述は、macroファイルに切り出してスマートなtemplateを作りましょう。

```txt:result.txt
My name is Taro
I live in Tokyo

My name is Hanako
I like tennis
```

# 関連記事
[【Ansible×NW自動化】templateモジュールでNW機器の設定を作りたい](https://qiita.com/masa2223/items/111071a3d7f972d4f5d5)
TestLink の RestAPI を curl コマンドでたたいてテストケースを追加する

#はじめに
https://qiita.com/bakachou/items/0f4a4f875d7e452e5fb1
の続きで、テストケースも自動というかテキストベースで直して登録したいという自分の要望。

まずは、手順と言うところを省いたテンプレート的なテストケースを追加できるようにしたい


#準備
https://qiita.com/bakachou/items/0f4a4f875d7e452e5fb1
の準備を参考にしてください

#テストケースの追加
以下のJSONを用意する

```bash
cat createTestCase.json
{
  "name":"Test Case ALFA2",
  "testSuiteID":74772,
  "testProjectID":1,
  "summary":"This is a summary for Test Case",
  "preconditions":"No preconditions",
  "order":100,
  "authorID":1,
  "importance":2,
  "executionType":1
}
```

上記で作成したJSONファイルを利用し以下のコマンドを実行する。

```bash
curl -i -H "PHP-AUTH-USER: ＜APIキー＞" -H "Content-Type: application/json" -X POST --data "@./createTestCase.json"   http://localhost/lib/api/rest/v1/testcases
```


「testProjectID」はテスト計画のIDであり、https://qiita.com/bakachou/items/0f4a4f875d7e452e5fb1 に記載した通りで取得できるのだが、「testSuiteID」をどうやって取得するのかがわからなかったが、「TestLink」の「テストスイートのエクスポート」で XML ファイルで出力されるが、その抜粋で「テストスイート」のIDが出力されていることがわかる。
これをJSONの「testSuiteID」に割り当てる


```
<testsuite id="74772" name="test2222" >
<node_order><![CDATA[1]]></node_order>
<details><![CDATA[]]></details> 
```

authorID は、テストケースのJSONデータから解析して誰がどのIDかを確認するしかない。
テストケース一覧の出力方法は、https://qiita.com/bakachou/items/0f4a4f875d7e452e5fb1 に書きました。


```
id:74768
tc_external_id:1
version:1
layout:1
status:1
summary:<p>ddddbbbb</p>
preconditions:<p>aaaaaaaaaaaaaa</p>
importance:2
author_id:2
creation_ts:2020-07-08 01:49:38
updater_id:2
modification_ts:2020-07-08 01:50:01
active:1
is_open:1
execution_type:1
estimated_exec_duration:null
tcversion_id:74768
name:testlink1111
keywords:null
customfields:null
```


#おわりに
JSONのデータを見ると、他にもテストケースの属性はいろいろあるので、これらを追加しつつ試していき記事にまとめていこうと思う

手順を含めたテストケースを追加したいのだけど、どうもうまくいかないので後々調査しする。
ソフトウェア開発における7つのムダ＋１　職場の活性化への気づき

もの作りに7つの無駄があるといわれています。
同じように、私たちソフトウェア開発にも7つのムダがあります。

**１．作りすぎのムダ**
　　顧客に使用されない機能、実際には不要な機能、真のビジネス価値を生まない機能などの余分な機能を作らない。
　　StandishのCHAOSレポートによるとソフトウエアの全機能の６４％は全くあるいは殆ど使用されていません。

**２．手待ち（停滞）のムダ**
　　仕様の提示遅れによる製造開始遅れでの待機、許可待ち、ビルド待ち、障害発生によるテスト待ち

**３．運搬のムダ**
　　打ち合わせ等で使用しない資料やPCの持参

**４．加工そのもののムダ**
　　開発現場で機能していない作業項目例えば余分な事務処理、報告書作成や作業分担の誤りによる過剰な作業

**５．在庫のムダ**
　　最終工程で使用されない文書や計画、コンポーネントなどの中間的な作業成果物と待ち状態で仕掛中のプログラム

**６．動作（作業）のムダ**
　　関係者の作業場所の移動や複数の開発ツールを使用して開発ツール間の切替・移行

**７．不良をつくるムダ**
　　バグの作り込み---要求仕様(要件）、設計、コードの欠陥

その他に、**人間の知恵を使わないというムダ**　この8番目のムダはモチベーションまで下げてしまいます。
ホワイトカラー含めて、とても注意しなければならないムダです。
頼むから、綺麗なコードを書いてください。お願いします

## 綺麗なコードとは、読みやすいコードのこと
具体的には２つだけ

1. 同じことを２回書かない
2. プログラマじゃない人が読んでも、何をしているのか分かるように書く

### 1. 同じことを2回書かない
こう書いてくれれば、何も問題ないんです。

```きれいなコード.ts
if (eatsApple) eatFruit(new Apple())
else if (eatsPeach) eatFruit(new Peach())

/**
* @private
*/
function eatFruit(fruit: Fruit) {
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
```

こう書かかないように、気をつけてください。

```:２回書いてるコード.ts
function eatApple() {
  const fruit = new Apple()
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
function eatPeach() {
  const fruit = new Peach()
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
```
cutFruit() ~ eatFruit() までが共通です。
共通の部分を外に切り出す、それだけです。


### 2. プログラマじゃない人が読んでも、何をしているのか分かるように書く
こういうコードを書いてくれたら、とても頼もしいです

```プログラマじゃない人が読んでも何をしているか分かるコード.ts
if (isWinter) eatApple()
else if (isEarlySummer) eatPeach()

/**
* @private 
*/
function eatApple() {
  eatFruit(new Apple())
}
/**
* @private 
*/
function eatPeach() {
  eatFruit(new Peach())
}
/**
* @private
*/
function eatFruit(fruit: Fruit) {
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
```

逆に、以下はプログラマじゃない人が読んでも分からないコードです。

```:プログラマじゃなかったら多分わからないし、プログラマも、ぱっと見て何をしているか分からないコード.ts
const month = new Date().getMonth() + 1
let fruit
if (month > 9 && month < 2) {
  fruit = new Apple()
}
else if (month <= 7 && month >= 5) {
  fruit = new Peach()
}
eatFruit(fruit)

/**
* @private
*/
function eatFruit(fruit: Fruit) {
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
```

それで、分かりやすいように、コメントをつける人もいると思うのですが、コメント部分を１つの関数に切り分けてくれた方がずっと読みやすいと思います。
つまり、次のようなコードも、読みやすくはないと思っています。

```:コメントがないと、ぱっと見て何をしているか分からないし、コメント書くくらいなら、関数切り分けて分かりやすい名前をつけてほしいコード.ts
// 今月の季節を調べる
const month = new Date().getMonth() + 1
const isWinter = month > 9 && month < 2)
const isEarlySummer = month <= 7 && month >= 5)

// 季節によって、旬のフルーツを食べる
if (isWinter) eatFruit(new Apple())
else if (isEarlySummer) eatFruit(new Peach())

/**
* @private
*/
function eatFruit(fruit: Fruit) {
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
```

コメントを書くくらいなら、次のように関数に切り分けた方が、はるかにすっきりと読みやすいコードになると思います

```:コメントを書くぐらいなら、関数を切り分けて、分かりやすい名前をつけたコード.ts
eatSeasonalFruit()

/**
* @private
*/
function eatSeasonalFruit() {
  eatFruit(getSeasonalFruit())
}
/**
* @private
*/
function getSeasonalFruit(): Fruit {
  const thisMonth = new Date().getMonth() + 1
  if (isWinter(thisMonth)) return new Apple()
  else if (isEarlySummer(thisMonth)) return new Peach()
}
/**
* @private
*/
function isWinter(thisMonth: number): boolean {
  return month > 9 && month < 2
}
/**
* @private
*/
function isEarlySummer(thisMonth: number): boolean {
  return month <= 7 && month >= 5
}
/**
* @private
*/
function eatFruit(fruit: Fruit) {
  cutFruit(fruit)
  putFruitOnTray(fruit)
  sitAtTheTableWith(fruit)
  eat(fruit)
}
```

要は、プログラマじゃない人が読んでも何をしているか分かるように書く、というのは、処理ごとに１つの関数に切り分けて、何をしているのか分かる名前をつけるということです。

もし初心者さんで、まだコーディングのこだわりを持っていらっしゃらない方は、ぜひ検討をお願いします。

そうすると、自然な文章を読むように、コードを読むことができるからです。

お願いします。
ShaderToy+openFrameworksでクリエイティヴヴィジュアルを＜その１＞

#ShaderToy+openFrameworks
画像処理とかビデオアートとかVJとかで、ShaderToy+openFrameworksって最強の組み合わせだと思うんですが、ofxShadertoyのサンプルが見当たらないのは何故でしょう？ShaderToyに興味ある人は達人が多いので、初歩的な技術解説は不要なのでしょうか？＜本当に無いんです。＞
私が見落としているだけでしょうか？
　というわけで、自力で試行錯誤しながら、たどりついたところまでメモ代わりに記録しておきます。＜その１＞はopenFameWorksでShaderToyのコードを表示するところまでです。

　先ず、openFrameworksのShaderToyのアドオン、ofxShadertoyをサーチしてダウンロードし、
addonsフォルダにコピーします。
(windows版用にコードを多少変更したような気がしますが、忘れましたので、思い出したら情報を追加します。）
　そして、projectGenerator.exeを起動して、アドオンにofxShaderToyを指定し、適当なプロジェクト名を【下図】のように設定して、緑のGenerateボタンをプレスします。

![コメント 2020-07-08 111927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/068e947a-97ff-fb66-b939-70c3eef286c7.png)

ここでプロジェクトが開きますので、
main.cpp をShaderToyの表示用に変更します。

```main.cpp
int main( ){
ofGLFWWindowSettings  settings;
	settings.setGLVersion(3, 2);    // <--- ofxShadertoy NEEDS the GL Programmable Renderer
	settings.setSize(640, 480);
	ofCreateWindow(settings);       // <-------- setup the GL context

	// this kicks off the running of my app
	ofRunApp(new ofApp());
}

```

次に　ofApp.h に
`#include "ofxShadertoy.h"`
と、
`ofxShadertoy shadertoy;`
を追加します。
そして、ofApp.cppのseup()と、draw()に下記のようなコードを追加します。


```ofApp.cpp
void ofApp::setup(){
	shadertoy.load("shaders/00.frag");
	ofSetFrameRate(60);
	shadertoy.setAdvanceTime(true);
	
	ofDisableArbTex(); // very important!!!
}
```
これは、ShaderToyのコードを読み込んで、表示の準備をします。

```ofApp.cpp
void ofApp::draw(){
	shadertoy.draw(0, 0);
}
```
上は、ShaderToyのGLSLを描画します。
コードの基本はこれだけです。
###ShaderToyのデータを用意する。
https://www.shadertoy.com/ にシェーダートイの例が沢山ありますので、この中からopenFrameworksで表示したいコードをコピペします。たとえば、
https://www.shadertoy.com/view/Msl3WH

![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/42ae5136-3966-c013-acf4-e55a7959f97b.png)

00.fragいうテキストファイルにコードをコピーして、dataフォルダの下にshadersフォルダを作成し、ここに00.fragを置きます。
__これはBufferを使っていない例です。__
以下のようにBufferを使ってWebcamの入力にイフェクトを加えることもできます。この例ではレイヤーは３層になってます。
https://www.shadertoy.com/view/wttSRM
（このようなopenFrameworks+ofxShadertoyでBufferの使う方法は＜その２＞以降で解説いたします。）

これで、準備ができました。
windowsのプロジェクトをgit
https://github.com/ultrahamlet/example01
に置きましたので、ビルドして走らせてみてください。

###Bufferを使った例や音声データを入力する例は＜その２で＞###
Djangoの管理者サイトを少しだけ改造したかった話

#やりたかったこと
- 選択したlist_filterを一括クリアするボタンをlist_filterタイトル横に配置したい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449926/347ad4a0-1d2a-13e6-da68-42f988fac452.png)

#方法
- Templateの「Change_list.html」をオーバーライドする

- app構成

```shell
C:Project Name
│  db.sqlite3
│  manage.py
│  
├─.idea
│      
├─Project Name
│  │  authentication.py
│  │  settings.py
│  │  urls.py
│  │  utils.py
│  │  wsgi.py
│  │  __init__.py
│  │  
│  ├─locate
│  └─__pycache__
│          
├─App Name
│  │  admin.py
│  │  apps.py
│  │  context_processors.py
│  │  forms.py
│  │  models.py
│  │  tests.py
│  │  urls.py
│  │  views.py
│  │  __init__.py
│  │  
│  ├─locate
│  ├─migrations
│  │  └─__pycache__
│  ├─templatetags
│  │  │  mytag.py
│  │  │  
│  │  └─__pycache__
│  │          mytag.cpython-37.pyc
│  │          
│  └─__pycache__
│          
├─templates
  │  __init__.py
  │  
  └─admin
      │  base_site.html
      │  index.html
      │  __init__.py
      │  
      └─App Name
          │  change_form_help_text.html
          │  change_list.html          ←このファイルを追加
          │  __init__.py
          │  
          ├─model name1
          │      change_form.html
          │      __init__.py
          │      
          └─model name2
                  change_form.html
                  __init__.py
```

- Change_list.html
 
以下のようにオーバーライドする

```html:Change_list.html
{% extends 'admin/change_list.html' %}
{% load admin_list %}
{% search_form cl %}
{% load i18n %}
{{ block.super }}

  {% block filters %}
    {% if cl.has_filters %}
      <div id="changelist-filter">
          <h2>{% trans 'Filter' %} <button id="clear" onclick="location.href=location.href.replace(/\#.*$/, '').replace(/\?.*$/, '');">clear</button></h2>
        {% if cl.has_active_filters %}<h3 id="changelist-filter-clear">
          <a href="{{ cl.clear_all_filters_qs }}">&#10006; {% trans "Clear all filters" %}</a>
        </h3>{% endif %}
        {% for spec in cl.filter_specs %}{% admin_list_filter cl spec %}{% endfor %}
      </div>
    {% endif %}
  {% endblock %}
```

#結果

- list_filterの解除自体は、追加したボタンをクリックした際に、現在のurlから検索クエリを抜いたurlを再設定することで実現した
 
- Templateのオーバーライドの方法がわかれば、adminサイトを少し改造するのに便利
Laravel 6で認証機能を入れる

# 開発環境構築
以下の環境を構築した上で、そのプロジェクトで実行しています。
https://qiita.com/ryuseino/items/e0e3a77245635b7cc101

# usersテーブル作成

とりあえずLaravelにデフォルトでついてくるMigrationを使ったusersテーブルでやります。
なのでまずはテーブル作成のコマンド実行。

```
php artisan migrate
```

# Composerパッケージインストール
以下のコマンドを実行することで認証が簡単に出来るようになります。

```
composer require laravel/ui "^1.0" --dev
php artisan ui vue --auth
npm install && npm run dev
```

# localhostを開く
開発環境構築後の確認と同じく、localhostを開いてみるとLOGINとREGISTERというリンクが上部に出ています。
<img width="1322" alt="スクリーンショット 2020-07-08 17.07.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607661/e383bd17-8fdf-de05-801e-5b237d48f12b.png">

それぞれ極々普通のログインと会員登録の機能になっています。
そんな訳で簡単に認証が作れることが分かりました。
この段階ではまだemailのverifyなどがないので、それらは後で追加する必要がありそうです。

# 参考になりそうなページ
https://readouble.com/laravel/6.x/ja/authentication.html
Node.jsで動くオンライン対戦リバーシを作ってみた

#ソース
https://github.com/inari2019/osero
正直かなり醜いコードだと思ってます。
#実際に作ったもの
http://pocketmikan.ml:3000/
※予期なくリンクが変わったり、封鎖している可能性があります。
#環境
バックエンド：Node.js(Express.js)
ソケット通信：socket.io
フロントエンド：javascript
描画：HTML5 Canvas
#構成
![無題の図形描画 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619412/42187d84-17b4-db32-edc7-51a280394bb9.jpeg)


#コードの解説
大体のことはgithubのコードに書いてるので割愛

実行の流れとしては
プレイヤーから駒を置く場所を受け取る(index,js)
↓
駒を置けるか確認したのち駒を置く(modules/gameclass.jsのput関数)
↓
置いた後の盤面データなどをプレイヤーに送信(index.js)

#リバーシのアルゴリズム
https://techacademy.jp/magazine/22767
まんまこれですすみませんでした

#終わりに
自分でもわかるぐらいひどいコードです。改善の余地しかありませんが、テストがあるので改善出来てません。
外国人がよくある、笑うほど、日本語の間違い方

自分が実際に間違った日本語となり、
普段、多少の日本語の間違いを大きな目で見たくれた同僚も思わず笑ってしまい、
指摘したので、よっぽどひどいなあと思いました。

その１：注意して入力してほしい項目の隣に、ビックリマック（ビックリマーク）を付けてください。
その２：SalesforceのApexのヒップサイズ（ヒープサイズ）は同期処理の場合最大6MBとなる。

共通して、長音と促音を区別できなかったですね。
まあ、昔からこの問題があり、なかなか治らないので。。
Gridsome,WP REST APIでビルド時に401エラーが出る

# 概要
GridsomeでWP REST APIをソースとして使おうとしたら躓いたので備忘録

# 起こったこと
ビルド時に401が返ってきてしまいコンテンツが取得できない

```gridsome.config.js
module.exports = {
  siteName: "Gridsome",
  plugins: [
    {
      use: "@gridsome/source-wordpress",
      options: {
        baseUrl: "https://*****.com", // required
        typeName: "blog",
        apiBase: "wp-json",
        perPage: 10,
        concurrent: 1,
      },
    },
  ],
  templates: {
    BlogPost: "/:year/:month/:day",
  },
};
```

```console
$gridsome develop
Gridsome v0.7.18

Initializing plugins...
Loading data from https://*****.com
Error: Status 401 - wp/v2/types
Error: Status 401 - wp/v2/users
Error: Status 401 - wp/v2/taxonomies
Load sources - 1.66s
︙
```

# 原因
WordPress側でREST APIのアクセスに制限がかかっていた

# 解決策
REST APIへのアクセス設定をデフォルトアクセスに設定する

### WordPressのダッシュボードからセキュリティに移動
![スクリーンショット 2020-07-08 18.34.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210932/bf395461-bb2f-e1ff-51e7-d192e35d9358.png)

### WordPressの微調整の項目の設定からREST APIをデフォルトアクセスに変更
![スクリーンショット 2020-07-08 18.35.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210932/590200e8-5c87-cc05-4dbb-380bb3ad1290.png)

### 再度ビルド
```console
$gridsome develop
Gridsome v0.7.18

Initializing plugins...
Loading data from https://*****.com
︙
Load sources - 295.88s
Create GraphQL schema - 1.01s
Create pages and templates - 0.15s
Generate temporary code - 0.08s
Bootstrap finish - 298.35s


 DONE  Compiled successfully in 4009ms              18:42:34


  Site running at:                                         
  - Local:                 http://localhost:8080/          
  - Network:               http://192.168.10.8:8080/       
                                                           
  Explore GraphQL data at: http://localhost:8080/___explore
```
今度はエラーを吐かずにビルドができました
これでWP REST APIからコンテンツを取得することができるようになりました

# 終わりに
本来であれば認証が通るようにするのが正しいのですが、今回は取得の確認を行いたかったのでWordPress側の設定を変更しました
おそらくgridsome.config.jsにheaderとしてBearerを設定するのがセキュリティ的に正解……のハズ

# 参考
[WP REST API 認証](https://ja.wp-api.org/guide/authentication/) このページ崩れてるのって僕だけですかね？
[Rest API restriction](https://wordpress.org/support/topic/rest-api-restriction/)
[Restrict WordPress REST API Access](https://ithemes.com/security/wordpress-rest-api-restrict-access/)
機械学習プロジェクトの勘所

それほど大した内容ではないのですが、私が機械学習プロジェクトをやった時にはまった経験をお伝えします。一切コードとかの話は出てきませんのでご注意ください。

# ビジネス課題

とある商品を販売する際に、**必ず**専門部署に問い合わせをする必要がある
→　専門的な知見が無いと判断ができない内容
→　専門的な知見を得るには数年はその業務に従事する必要がある
→　ゆえにこの専門的な知見を持っている人が少ない
→　人が足らずにこの部署がボトルネック（制約条件※）
※　ザ・ゴールに出てくるTOC的にはそういう位置づけ

このボトルネックを解消するため、機械学習を利用しようという話になりました。
ちなみに、この商品の潜在的な市場規模は大きく、これが実現できた場合のビジネスインパクトは非常に大きいです。（規模を言うと会社にバレる可能性があるので言えません）

# プロジェクトの進め方
このプロジェクトは以下のような形で進んでいきました。
1. 業務理解
2. 機械学習で置き換えることができる部分の検討
3. モデリング
4. 新しい業務フローの設計

それぞれ簡単に説明します。

## 1. 業務理解

- 営業がどのように案件をとってくるか
- そこからどのように照会・問い合わせが来るか
- どのように判断をしているか
- その後どのように契約になるか<br>
などをかなり細かい部分までヒアリングしました。

## 2. 機械学習で置き換えることができる部分の検討
プロジェクト的にはAIシステムと謳っておりました（予算が取りやすい！）が、大部分は普通のシステムで、一部に機械学習を取り入れるわけですから、ここからここまではシステムで処理をして、ここからデータを引っ張って、ここでモデルを通し・・・ということを考えていきます。

機械学習を取り入れる場合、ここで一つポイントがあると思っています。
それは、**今後もデータが得られ、得られたデータからモデルを再学習することができるか**ということです。
今回のプロジェクトの場合、専門部署の人たちの過去の判断を学習させるという方法もあります。

しかし、その方法をとると、新たにシステムが導入されてここで言うAIシステムが判断をするようになると、専門部署の人たちの判断したデータは新たに得られなくなります。そこで、今後も得られるデータを使って学習するというのが重要です。

## 3. モデリング
詳しくは話せませんが、専門部署からの要望もあり、なるべく精度を高めたいということでブラックボックスのアルゴリズムを採用して分類モデルを作成しました。

## 4. 新しい業務フローの設計
はっきり言って**めちゃくちゃ大事**です！どのように日々の業務オペレーションの中にこれを組み込むか、どうすれば問題なく使えるかということを考えるのは、業務理解が無いとできません。結構この部分を軽視する人が多い印象を持っていますが、これができないと結局使われない、オペレーションが回らないなどの問題が起こります。

結論から言うと、**一番はまったポイントがここ**になります。

何が問題だったかというと、分類モデルを使って業務はできるけれども、その後に説明責任があるのでそのように分類した根拠を知りたい（システムで表示したい）と言われたことです。

しかも、**それぞれの判断根拠が互いに矛盾しない**ことも付け加えられました。

例として、個人の住宅ローンデフォルトを年収から予測する問題を考えてみます。

|  |年収  |デフォルト確率 |
|---|---|---|
|A  |300  | 5%|
|B  |500  | 4%|
|C  |700  | 3%|
|D  |800  | 2%|
|E  |1200  | 1%|
|F  |2000  | 1.5%|

上の表のような形でモデルが予測したとします。例えば「Aのデフォルト確率が5%の理由は？」と聞かれたら、「年収が安いから」というのが判断の根拠になると思われます。
同様に、「Eのデフォルト確率が1%の理由は？」と聞かれたら「年収が高いから」というのが判断根拠になります。
では、Fの場合はどうでしょうか。Fはデフォルト確率1.5%ということでA～Dより年収が高いことからデフォルト確率が相対的に低くなると説明できます。しかし、Eとの比較では年収が高いにも関わらずデフォルト確率はEより高くなります。ロジスティック回帰などの古典的な手法を用いる場合は起こりませんが、ブラックボックスだとこれが起こりえます。


ということで、実際にはこれがもっと多数の変数間で起こるわけですから、どんなにデータをチェックしたところで、今後も矛盾が起こらないことを担保できません。つまり今回作成したモデルを運用できないということになりました。


# ではどうすれば良かったか

昨今のAIブームで、事業部側は中身を理解せずに「AIを導入したい」と言います。AIとはどんなものかをちゃんと理解してもらうには一から機械学習について勉強してもらうことになりますので現実的ではありません。
結局、機械学習を作る側が、こういう穴はないかということを隅々まで検討・確認してからモデリング等に移らないと、似たようなことが起こると思われます。しかし、穴がないか検討するには相応の業務知識が必要です。

結局、我々データサイエンティストやMLエンジニアの側もビジネス側に歩み寄る努力が必要で（私は相当歩み寄ってはいたのですが、それでも・・・）、それをしないと痛い目に遭いますよという話でした（おそらくプラットフォーマーだとあまり起こらない？）
Arch Linuxインストール時の、Wifi接続に関する備忘録

# この記事は
Arch Linuxをインストールする際にWifi接続を行う手順を、自分用に簡潔に記録しました。

インストールは基本的に、@TsutomuNakamuraさんの「[Arch Linux インストール俺々式完全版](https://qiita.com/TsutomuNakamura/items/b60518f8788e5e998744)」に従って行えば問題なく終わります。
このとき、インターネット接続が必須となるのですが、有線接続が使えなかった自分はWifiの設定にやや苦労したので、その際の解決法を記録しておきます。

# 結論から言うと
WPA/WPA2の場合は**wpa_supplicant**を使うと良いです。自分は**wifi-menu**が使えませんでした。

# 手順

## 全景
```
> ip link
> ip link set [interface] up
> iwlist [interface] scanning | grep "ESSID"
> wpa_supplicant -B -i [interface] -c <(wpa_passphrase [ESSID] [password])
> dhcpcd
> ping archlinux.org
```
- [interface] : インターフェースの名前
- [ESSID] : SSID名
- [password] : パスワード

## 1. インターフェースの名前を確認
```
ip link
```
まずはインターフェースの名前を確認する。
Wifiのインターフェースとして、自分の場合は「wlan0」というような名前が表示された。

## 2. インターフェースの有効化（不要なことが多い？）
```
ip link [interface] up
```
1.で取得したインターフェースが無効になっている場合はこのコマンドで有効化する。インターフェースの有効・無効については、「[Arch Linuxインストールメディア環境下でのWi-Fi接続(ワイヤレス設定）について | Unskilled?](https://unskilled.site/arch-linux%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E7%92%B0%E5%A2%83%E4%B8%8B%E3%81%A7%E3%81%AEwi-fi%E6%8E%A5%E7%B6%9A%E3%83%AF%E3%82%A4%E3%83%A4/)」の「有効・無効の見分け方」以下を参照。

## 3. SSIDを検索
```
iwlist [interface] scanning | grep "ESSID"
```
1.で取得したインターフェースの中から、接続したいWifiのSSIDを探す。見つからない場合は再度コマンドを叩くと表示されることがある他、インターフェースが間違っている可能性がある。

## 4. Wifiに接続
```
wpa_supplicant -B -i [interface] -c <(wpa_passphrase [ESSID] [password])
```
1.で取得したインターフェース名、3.で取得したSSID、Wifiのパスワードをそれぞれ入力して接続する。このコマンドはWPA/WPA2が対象のものだが、**まあ大概の機器はWPA/WPA2だろう**くらいのノリでこの備忘録を書いている。

## 5. ホスト情報の割り当て
```
dhcpcd
```
呪文。
IPアドレス等を取得して、各種設定を行う。
詳しくは「[dhcpcd - システム管理コマンドの説明 - Linux コマンド集 一覧表](https://kazmax.zpp.jp/cmd/d/dhcpcd.8.html)」を参照。

## 6. 接続を確認
```
ping archlinux.org
```
適当なアドレスにpingを打って、接続が完了したことを確認する。
pingの先は適当。

# まとめ
Arch Linuxって楽しいよね！
【Solidity】ブロックチェーン上の外部コントラクトの関数を実行する方法

ブロックチェーン上で公開されている外部のコントラクトの関数を呼び出すことができる。
呼び出すには最初にinterfaceを定義する必要がある。

例えば、ブロックチェーン上に以下のようなコントラクトが公開されていたとする。

```solidity
contract BloodType {
  mapping(address => string) bloodtypes;

  function setType(string _bloodtype) public {
    bloodtypes[msg.sender] = _bloodtype;
  }

  function getBloodType(address _myAddress) public view returns (string) {
    return bloodtypes[_myAddress];
  }
}
```

例なのでとても簡単なやつ。
イーサリアムのアドレスと血液型を関連づけられるものになります。

このコントラクトを呼び出したい場合は、まず以下のようなinterfaceを定義する。

```solidity
contract BloodInterface {
  function getBloodType(address _myAddress) public view returns (string);
}
```
ここでは呼び出したい関数（この例の場合はgetBloodType）のみを宣言する。
宣言では関数の中身（括弧{}を書いての処理）は書かない。

このinterfaceは自分のコントラクト内で使用することができる。

```solidity
contract MyContract {
  // 使用したいコントラクト(BloodTypeコントラクト)のイーサリアム上のアドレス
  address BloodInterfaceAddress = 0xaaaaa.....;
  BloodInterface bloodtypeContract = BloodInterface(BloodInterfaceAddress)

  function execFunction() public {
    // コントラクトから`getBloodType`を呼び出す
    string bloodtype = bloodtypeContract.getBloodType(msg.sender);
  }
}
```

これで外部の公開されているコントラクトの関数を呼び出せます。
呼び出せる関数はpublic、又はexternalのものに限られます。

注意点として、この例では説明を簡単にするため外部コントラクトのアドレスをハードコーディングしていますが、通常このような書き方はしません。

外部コントラクトのアドレスが変更された場合、このコントラクトも使い物にならなくなるからです。（ブロックチェーンにデプロイされたコントラクトは編集、更新ができないため）

よって、本来であれば後からアドレスが変更できるような形で保持する必要があります。
VPN越しのlinuxマシンにpingが通らない原因がdocker0だった

3ヶ月くらいずっと原因不明だったのがやっと解決したので備忘録として書き留めておく。

# 事象
⭕ローカルmac <-> ローカルmac
⭕ローカルmac <-> ローカルlinux
⭕ローカルmac <-> VPN越しmac
❌VPN越しmac <-> ローカルlinux

要は **リモートで何故かlinuxマシンに接続できない！** という状況が発生していた。

# 結論
VPN配下のIPアドレスと`docker0`のIPアドレスが衝突していることが原因だった。

- 今回の環境でVPN配下に割り振られるアドレス: `172.17.XXX.0/21`
- `docker0`のIPアドレス初期値: `172.17.0.1/16`

これを`docker0`のIPアドレス設定を変更し、dockerサービスを再起動することで解決した。

(情シスはこの事象既知なんだろうか:thinking:)


# やったこと

## わかっていること
- VPN越しmac -> ローカルlinuxへping: `Request timeout for icmp_seq XX`
- ローカルlinux -> VPN越しmacへping: `From 172.17.0.1 icmp_seq=XX Destination Host Unreachable`

### 事前に試してダメだったことのおさらい
今回の件には結局関係なかったけど一応チェックしといてねって箇所

- そもそもicmpが塞がれていないか(検証手段が正しいのか)
    - mac同士のpingは通るので塞がれていないことがわかる
- `host.allow` および `host.deny` の設定見直し
    - `hosts.allow` に `172.19.`と記述しても変化なかった
- firewall設定
    - 無効化しても変化なかった

## 自身のアドレスを確認
pingのエラーメッセージから、 `172.17.0.1`とかいうよくわからん経路でコケてることは分かっていた

ふとdocker周りのネットワークが気になったので、自身のアドレスをすべて確認してみることにする

```shell
$ hostname -I
172.19.XXX.XXX 172.17.0.1 172.18.0.1 192.168.XXX.XXX ...
```
`172.17.0.1`がいる？？？なんで？？？

```shell
$ ip a
### 略 ###

2: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.30.0.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 XXXX::XXXX:XXXX:XXXX:XXXX/64 scope link 

### 略 ###

```

`docker0`とかいう仮想インターフェイスがガッツリIPアドレス被りしている模様なので、これを変更してみる

ちなみに`docker0`はdocker for linuxのみでしか生成されず、これがlinuxへの疎通のみNGという理由にもなっていた


### docker0の設定変更

先人の大変ありがたい資料があるので、参考に設定を進める
https://qiita.com/msi/items/d9cc1a2fd3f0fed3a901

```shell
$ sudo vi /etc/docker/daemon.json
{
    "bip": "172.30.0.254/24"
}

$ sudo systemctl restart docker

$ ip a show docker0
2: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet 172.30.0.254/24 brd 172.30.0.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 XXXX::XXXX:XXXX:XXXX:XXXX/64 scope link 
```


### ping

```shell
# VPN越しmac -> ローカルlinux
$ ping 172.19.XXX.XXX
64 bytes from 172.19.XXX.XXX: icmp_seq=0 ttl=60 time=192.154 ms
64 bytes from 172.19.XXX.XXX: icmp_seq=1 ttl=60 time=238.941 ms
64 bytes from 172.19.XXX.XXX: icmp_seq=2 ttl=60 time=292.419 ms
64 bytes from 172.19.XXX.XXX: icmp_seq=3 ttl=60 time=257.762 ms
```
✌️success✌️
Cloud Run for Anthosを試す


#事前準備
GKEクラスタ作成します。
機能として「Cloud Run for Anthosの有効化」にチェックをつけます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/2d2aa85b-fa92-72e9-00bf-1c1eb68bb72c.png)

#External
クラスタ外からアクセス可能なサービスを作成します。
作成したGKEクラスタを指定します。
接続として外部を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/4da734bc-99d2-980c-e731-108a52fc9257.png)

サンプルのコンテナイメージ(gcr.io/cloudrun/hello)を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/f3d9049f-eae9-1e9c-e3e7-189e75807bda.png)

接続を確認します。外部からの接続は、Istio Ingress Gatewayを経由して行います。
デプロイしたサービスのURLの横の！マークをクリックします。curlコマンドが表示されるのでCloud shellなどで実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/64f97639-d8fe-16e6-3630-798cd3413dc1.png)

または、
GKEの管理画面のサイドバーから「Service と Ingress」を選択し、Istio-ingressのエンドポイント(External IP)を確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/e9ea984c-2629-1eef-04d8-e633b9294e07.png)

Hostヘッダーに作成したCloud RunサービスのURLを指定し、接続先IPアドレスにIstio-ingressのエンドポイント(External IP）を指定します。Portの指定は不要です。

```
$ curl -v -H "Host: XXX.default.example.com"  http://XXX.XXX.XXX.XXX
* Expire in 0 ms for 6 (transfer 0x555f9647bfb0)
*   Trying XXX.XXX.XXX.XXX...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x555f9647bfb0)
* Connected to XXX.XXX.XXX.XXX (XXX.XXX.XXX.XXX) port 80 (#0)
> GET / HTTP/1.1
> Host: hello-external.default.example.com
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< date: Wed, 08 Jul 2020 08:59:31 GMT
< x-envoy-upstream-service-time: 2819
< server: istio-envoy
< transfer-encoding: chunked
<
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Congratulations | Cloud Run</title>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="preload" as="font">
<link

-略-
</body>
</html>
* Connection #0 to host XXX.XXX.XXX.XXX left intact
```

#Internal
クラスタ外からアクセス可能なサービスを作成します。
作成したGKEクラスタを指定します。
接続として内部を指定します。
＊先程のサービスをコピーして作っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/64832f1e-adf4-282d-8edf-3378ef728b8b.png)

デプロイしたサービスのURLの横の！マークをクリックします。curlコマンドが表示されるのでCloud shellなどで実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/020b6e65-8908-f9dc-0eeb-3805676c9522.png)

または、
接続を確認します。クラスタ内からの接続のため、Podを起動してCurlを実行します。
Urlは、Cloud RunサービスのURLを指定します。

```
$ gcloud container clusters get-credentials <Cluster name> --zone <Zone name>
$ kubectl run curl  --image=radial/busyboxplus:curl -i --tty --rm
$ curl http://XXX.default.svc.cluster.local
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Congratulations | Cloud Run</title>
```
AWS EC2でApache Tomcatを接続

研修でAWSとTomcat使ってサーバー構築するので備忘録

#前提条件

- AWSにアカウント登録済
- セキュリティグループ構築済
- ネットワーク等も構築済

#手順
##EC2インスタンス作成
1. コンソールにログインするアドレスでログイン画面に飛んでログイン
2. EC2>インスタンス画面で、インスタンスの作成
3. もろもろ適切に設定（このとき既存のネットワークとかセキュリティグループを使った）
4. 最後まで設定できたら、キーペアの作成とかが出るので控える（今回は既存のものを使用）
5. インスタンス一覧画面から作ったインスタンスを探す。初期化とかも全部終わったらOK

##Apacheインストール
1. ```sudo yum -y install httpd``` Apacheのインストール
2. ```sudo service httpd start``` Apacheの起動
3. ```sudo chkconfig httpd on``` Apacheが自動起動するように設定
4. ```sudo chkconfig -–list httpd``` Apacheがちゃんと起動できてるか確認

##Javaインストール
（ここから大体rootユーザーでやってた）
1. ```sudo yum -y install yum-fastestmirror``` fastestmirrorのインストール
2. ```sudo yum -y install java-1.8.0-openjdk-devel``` Javaのインストール
3. ```java -version``` バージョンの確認（確認できれば入ってる）

##Tomcatインストール
1. ```curl -O http://ftp.meisei-u.ac.jp/mirror/apache/dist/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.tar.gz``` TomcatのDL
　※Tomcat公式サイトで適宜最新バージョンを確認してDLするようにしないとうまく解凍できなかったりする
2. ```tar -xvzf apache-tomcat-9.0.37.tar.gz``` 1でDLしたやつを解凍　うまく行くとファイルがずらーっと表示される
　※ずらーっとなるのが嫌だったらオプション部分をいじると多分表示されない
3. ```mv ~/apache-tomcat-9.0.37 /opt``` 2のファイルを移動
4. ```chown -R tomcat:tomcat /opt/apache-tomcat-9.0.37``` 移動させたファイルの所有権を全部tomcatユーザーとかグループに移行
5. ```vi /etc/systemd/system/tomcat.service``` viで以下のように書き込んでサービスの登録を行う

```
[Unit]
 Description=Apache Tomcat 9
 After=network.target

 [Service]
 User=tomcat
 Group=tomcat
 Type=oneshot
 PIDFile=/opt/apache-tomcat-9.0.37/tomcat.pid
 RemainAfterExit=yes

 ExecStart=/opt/apache-tomcat-9.0.37/bin/startup.sh
 ExecStop=/opt/apache-tomcat-9.0.37/bin/shutdown.sh
 ExecReStart=/opt/apache-tomcat-9.0.37/bin/shutdown.sh;/opt/apache-tomcat-9.0.37/bin/startup.sh

 [Install]
 WantedBy=multi-user.target
```

6. ```chmod 755 /etc/systemd/system/tomcat.service``` ファイル権限を755に変更
7. ```systemctl enable tomcat``` サービスを有効化

あとはブラウザで「パブリックIP:8080」を叩くとTomcatのページが表示されます。

#参考になるページ
https://weblabo.oscasierra.net/installing-tomcat9-centos7-1/
https://qiita.com/LowSE01/items/2c735f22d220f53a6b2f
https://www.oqiita.com/?p=1771