OmniAICreator/Qiita-1.07M huggingface dataset:
SQL データを登録する為のInsert文について

2019/11/30 追記・編集

PostgreSQLでテーブルにデータを登録する為のInsert文について書いていきます



<b>【入力した値をINSERTする場合】</b>

DBによっては次の書き方が効率的です。

```SQL
INSERT INTO テーブル名
VALUES
(
    10000
    ,8000
    ,2000
    ,500
    ,1500
)
```

数値型の場合のInsert文は次のように書きます

```SQL
INSERT INTO テーブル名
(
    columnName1
    ,columnName2
    ,columnName3
    ,columnName4
    ,columnName5
)
VALUES
(
    10000
    ,8000
    ,2000
    ,500
    ,1500
)
```


<b>雛形は次のようになります</b>

```SQL
INSERT INTO テーブル名()Values()
```




<b>【他のテーブルのデータをINSERTする場合】</b>

次にSelect文で抽出した値をテーブルにInsertする場合は次のようになります

```SQL
INSERT INTO GoldenTable2
(
    column1
    ,column2
    ,column3
    ,column4
    ,column5
    ,column6
)
SELECT 
    column1
 ,column2,column3,column4,column5,column6
from FromTable;

```




<b>雛形は次のようになります</b>

```SQL
INSERT INTO 登録先のテーブル名1 (登録先のカラム名) SELECT 登録元のカラム名 FROM 登録元のテーブル名2
```
yocto recipeの作成方法


- yocto-layer createでひな型作成
→カレントディレクトリにmeta-my-recipeディレクトリが生成される

```
. ./pokyscripts/yocto-layer create my-recipe
Please enter the layer priority you'd like to use for the layer: 6
Would you like to have an example receipe created?(y/n) y
Please enter the name you'd like to use for your example recipe: [default example]
Would you like to have an exmple bbappend the created?(y/n): n

New layer created in meta-recipes.
```

- recipe説明

```
SUMMARY = "hogihogi Initialization"      # recipe概要
SECTION = "hogihogi"                     # recipeが所属するセクション(一応ビルド時にチェックされる)
LICENSE = "CLOSED"                       # ライセンス名
LIC_FILES_CHKSUM = "file://COPYING;md5=ffffffffffffffffffffffff"# ファイル名＋md5
PR = "r0"                                     # Recipeのリビジョン
SRC_URI = "file://hogihogi.sh"              # ソーファイル定義
#inherit systemd update-rc.d
```
nvngから起動するため、rcS.d配下へのシンボリックリンク生成は行わない

```
INITSCRIPT_NAME = "hogighogi.sh"              
INITSCRIPT_PARAMS = "start 90 S . stop 90 ."   

do_install() {                                # タスク定義(実際に実行されるタスクはbitbake -c listtasks レシピ名で確認できる)
    install -d ${D}${sysconfdir}/init.d       # do_instllはmake installを実行
    install -m 0755 ${WORKDIR}/hogihogi.sh ${D}${sysconfdir}/init.d/hoighogi.sh
}

# タスクは上書き、追加可能
# タスク間は依存関係がある
# 自作のタスクを定義可能

PACKAGES = "hogihogi-init"
FILES_${PN} = "${sysconfdir}/init.d/hogihogi.sh"
```

- recipeのビルド
 1. meta-my-recipesのパスをbblayers.confのBBLATERSに追加する
 2. bitbake-layers show-layersでビルド環境レイヤーをチェックする
 3. bitbake exampleを実行

- 既存のrecipeのビルド方法
 1. .bbを直接変更しない
 2. ddappendファイルを作成して上書き
 3. .bbappendファイルを上書きするときはレシピ名(PN)とレシピのバージョン(PV)が同じである必要がある


<参考>
https://www.slideshare.net/iwamatsu/ss-31662659
https://qiita.com/propella/items/8d861d08c95ac08136d2
Unityでプレイ画面を動画やgifにする

# はじめに
Unity Recorderを使う。
Asset Storeのものは使えなくなっていたのでメモ。

バージョンは2019.2.1f1

参考:https://dkrevel.com/unity-explain/unity-recorder/
参考先の方が理解しやすいので↑だけを見ればこちらは見なくてok。


# Unity Recorderのインポート
Window>Package Managerを開く。
![スクリーンショット 2019-09-03 18.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446130/3c91a66e-3999-8087-7381-541aa01b6da2.png)

Advanced>Show preview packagesを選択。
![スクリーンショット 2019-09-03 18.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446130/d3b9d46f-8377-4d96-a912-527e09b44027.png)

Unity Recorderを選択しInstall。
![スクリーンショット 2019-09-03 18.10.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446130/30d5cea7-1036-3160-d1d1-bb1d790e32de.png)

これでインストール完了。


# 準備
Window>General>Recorder>Recorder Windowを開く。
![スクリーンショット 2019-09-03 18.15.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446130/38a994bf-5d15-b3dd-86fd-49fa4f0abaf7.png)

Add New Recordersをクリックし保存形式を選ぶ。
動画ならMovie。
![スクリーンショット 2019-09-03 18.18.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446130/b7a60b84-76f4-1e58-b731-bd793fca0916.png)

準備完了。


# 使う
プレイ中にSTART RECORDINGをクリックすると録画が始まる。
STOP RECORDINGで録画終了。

プレイ中でなくともSTART RECORDINGで自動的にプレイが開始される。
プレイを終了しても録画が終了される。

撮るたびに古い動画は上書きされるので残しておきたい動画は名前を変えておく。
![スクリーンショット 2019-09-03 18.27.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446130/ba654677-a60e-3cbc-d776-1936ff859a7b.png)このアイコンを押すと保存場所にいける。


# おわり
書き終わって参考にしたサイトを探しに行ったら参考先を薄めたような記事になっていた。
のでもう一度。
参考:https://dkrevel.com/unity-explain/unity-recorder/
VCのRuntimeライブラリー

VisualStudioC++で開発したアプリは新しいWindows環境で実行すると、
「MSVCR140.dll/VCRUNTIME140.dllがないため、プログラムが開始できません」というエラーが出た場合があります。VC++のRuntimeライブラリーを見つからないのは原因と考えられます。
対応方法は二つあります。
* Runtimeライブラリーをダウンロード/インストールする
* RuntimeライブラリーDLLをアプリに付属

VCのRuntimeライブラリーの入手は[こちら]です。
(https://visualstudio.microsoft.com/downloads/?rr=https%3A%2F%2Fwww.javadrive.jp%2Fphp%2Finstall%2Findex2.html)

ただ一般ユーザーに向かない方法と思います。

RuntimeライブラリーDLLをアプリに付属するのは一番簡単かもしれません。

以下のDebug用DLLファイルを以下のVS2017開発環境からコピーします
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Redist\MSVC\14.16.27012\debug_nonredist\x86\Microsoft.VC141.DebugCRT
C:\Program Files (x86)\Windows Kits\10\bin\x86\ucrt

```
concrt140d.dll
msvcp140_1d.dll
msvcp140_2d.dll
msvcp140d.dll
ucrtbased.dll
vccorlib140d.dll
vcruntime140d.dll
```

Release用DLLを以下のフォルダーからコピーします。
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Redist\MSVC\14.16.27012\x86\Microsoft.VC141.CRT
C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86

```
concrt140.dll
msvcp140.dll
msvcp140_1.dll
msvcp140_2.dll
ucrtbase.dll
vccorlib140.dll
vcruntime140.dll
```
UiPath19.8以降の「ロボットをコマンドで実行する方法」

UiPath19.8が2019年9月1日にcommunity editionで提供され始めて、いろいろ変わりすぎてびっくりしてます。笑

そして、公式サイトをみても何が変わったのかまとめられていないのが困る！（僕が見つけられなかっただけかも！）

今回は、9月2日（このときまだUiPath19.7）にバッチファイルでロボットを初めてコマンドから実行できるようにして、その30分後にUiPath19.8にアップデートされて、バッチファイルが動作しなくなった事件が発生したので、UiPath19.8用の「ロボットをコマンドで実行する方法」を記しておこうと思います。


# UiPath19.8以降のロボットをコマンドで実行する方法

**1. コマンドプロンプトを開きます**
**2. エクスプローラーでロボットまでのパスを確認します**

僕の場合はこれでした↓

`C:\Users\{ユーザー名}\AppData\Local\UiPath\app-19.8.0\UiRobot.exe`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/05863225-6d0a-ddf9-6631-d18fad6f892f.png)

**3.コマンドプロンプトに以下のスクリプトを入力してエンターを押します**

```
C:\Users\{ユーザー名}\AppData\Local\UiPath\app-19.8.0\UiRobot.exe execute --file "{実行したいロボットのXAMLまでのパス}"
```

例として当てはめるとこんな感じになります

```
C:\Users\{ユーザー名}\AppData\Local\UiPath\app-19.8.0\UiRobot.exe execute --file "C:\Users\{ユーザー名}\Documents\UiPath\Workflow-Inspector\Main.xaml"
```

ちなみに、実行したいロボットの指定ですが他にもいろいろ方法はあるみたいです。

# 既にパブリッシュ済みのロボットを実行する場合

```
C:\Users\naoki.oshiumi\AppData\Local\UiPath\app-19.8.0\UiRobot.exe execute -p "ロボットの名前"
```

例えば、以前僕はしりとりロボットを作ったので、パブリッシュ済みのロボットの中に「しりとりロボット」というのがあります


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/a27954dc-b689-3390-513e-6befdd15c79b.png)


このしりとりロボットを実行したい場合は、わざわざXAMLを指定する必要はなくて、`-p`というオプションを使えば名前を指定するだけで実行できます！（pはプロセスのp）

```
C:\Users\naoki.oshiumi>C:\Users\naoki.oshiumi\AppData\Local\UiPath\app-19.8.0\UiRobot.exe execute -p "しりとりロボット"
```

# 他にも...

ヘルプを実行したらこの結果がでてきました。

先程申し上げたように`-p`でプロセス名を指定するだけで実行できます。

`-f`で「実行したいxamlファイル」もしくは「project.json」までのパスを指定したら実行できます。

`--input`で入力引数を指定できるみたいです（JSONのフォーマットで）

`--folder`でオーケストレーターのフォルダーIDを指定できるみたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238739/b8361cb2-3829-7e31-0bd5-5eb42c914e26.png)

# おわりに

僕は、UiPathが公式で提供しているワークフロー品質検査ロボットを実行するバッチファイルを作成して、そこに「Ctrl+Shift+C」のショートカットキーを割り当てて、超簡単にロボットを立ち上げられるようにしてます。

普段はあまりコマンドでロボットを実行するとはないかと思いますが、もし必要になったときに参考にしてください！
Android StudioのプロジェクトをSVNでバージョン管理する

Android StudioプロジェクトをSVNで管理する際の除外するべきファイル郡を示します。
プロジェクトを作ると`.gitignore`が自動生成されるのでgitでは簡単だがSVNではちょいと手順。

# 除外するべきものたち

`.gitignore`が示す除外するべきものリスト
これらを除外しないで一緒にcheckoutしてしまうとビルドできない。svnの無視リストに追加しておく。

* プロジェクト名.iml
* .gradle
* .idea
* app/build
* app/app.iml
ActiveStorageでアップロードした画像が本番環境で表示されなくなる問題について

表題の件を対応しました。
問題がありましたらコメントいただきたいです。

# 環境
Rails 5.2.3
Ruby 2.6.3
Capistrano 3.11.0
AWS

# 問題
本番環境ActiveStrorageを使って画像アップロードをした。

アップロードしたその時は画像は問題なく表示されるが、
次のデプロイ作業をした時に404エラーが起こった。


# 原因
画像のアップロード先が [appname]/storage にデフォルトで設定されていた。
そのためcapistranoでデプロイすることで、以前アップロードされた画像ファイルがあるディレクトリは参照されず、[appname]/storage内の空のディレクトリを参照していた。
これが404のエラーの原因である。

そこで、アップロード先をshared/内にするよう設定変更をすることにした。

# 対策
1. storageディレクトリをpublic内に移動
2. public/storage にアップロード先するようにstorage.ymlで設定変更 

```ruby:storage.yml
local:
  service: Disk
  root: <%= Rails.root.join("public/storage") %>  ## 元は "storage"
```
３. 本番環境のpublic/storageに、sharedディレクトリからリンクを貼る設定。

```ruby:deproy.rb
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system", "public/storage"
```
クローラーエンジニアになるには？学習すべきことを解説

ビッグデータ・AIの台頭とともに、データ収集、活用の重要性が高まるようになりました。ビッグデータを収集するために、多くの企業は専門のクローラーエンジニアを採用しています。今回の記事では、「クローラーエンジニア」の仕事内容、学習すべきスキルについて解説したいと思います。


#クローラーエンジニアとは？仕事内容は？

簡単に言えば、クローラーエンジニアは[Webクローラー](https://www.octoparse.jp/blog/what-is-web-crawler/)を開発するエンジニアです。以前紹介したとおり、Webクローラーとはインターネット上に公開されているテキスト・[画像・動画などの情報を自動で収集](https://www.octoparse.jp/blog/bulk-download-images-from-links-top-5-bulk-image-downloaders/)し、データベースに保管するプログラムのことです。

クローラーエンジニアとして、ネット上掲載している情報を自動で収集できる「クローラー」プログラムを書かなければなりません。

多くの企業はデータを活用してビジネスチャンスにしていこうと取り組みを進めているでしょう。会社のビジネスによって、仕事内容もそれぞれです。

例えば、Google検索エンジンなどデータ集約型のWebサイトでは、数ミリ秒以内に特定のキーワードを含むページを提供できます。Webページをリアルタイムで見つけるのではなく、事前にスクレイピングして独自のデータベースに保存することは間違いありません。

また、価格比較など、情報比較を提供するWebサイトがあります。これは、Webクローラーを介してさまざまなショッピングWebサイトにある製品の価格をスクレイピングし、各ショッピングサイトの価格をまとめて表示します。ショッピングサイトの価格は時々変化しますが、比較サイトでスクレイピングされたデータは削除されないため、価格トレンドを提供することができます。

 

#クローラーエンジニアになるには、学習すべきことは？

 

##1.　少なくとも1つのプログラミング言語

コーディング基礎は、すべてエンジニアに不可欠です。実際、クローラーの開発は簡単な仕事ではなく、使用するプログラミング言語に精通し、関連するフレームワークとライブラリに詳しくすることが重要です。もちろん、スクレイピングの主流はPythonですね。

 

##2.　タスクキュー

クローリング作業が膨大な量のデータを処理するとき、システムに多大な負荷がかかり、システムは停滞するかハングアップするかして支障を来たす可能成があります。したがって、非同期分散処理できるタスクキューが必要です。タスクキューを使うと、複数台のマシンでワーカーを構成して分散処理を行うことで、高いスループットを発揮します。

後からワーカーにマシンを追加することで、処理性能とデータ保持容量をスケールアウトすることもできます。ワーカーがタスクの処理に失敗した場合、タスクキューはキューに再試行メカニズムを適用するため、タスクは限られた回数だけ再試行されます。

一般的に使用されるタスクキューサービスはKafka、Beanstalkd、Celeryなどです。

 

##3.　データベース

言うまでもなく、データを保存するにはデータベースが必要がです。ここではNoSQLのMongoDBをお勧めします。MongoDBはスケーラビリティが高く、容易にスケールアウト（水平スケール）できるので、大量のデータを高速に処理することが可能です。

 

##4.　HTTPとHTMLの知識

スクレイピングするのはWebページのデータだから、Webページの構造を理解する必要があります。

HTTPとはWebサーバとWebブラウザ用の通信プロトコルです。私たちはInternet ExplorerやGoogle ChromeなどのWebブラウザを使用してWebサイトにアクセスします。そもそもWebページの正体はHTMLタグを使って構成されている文書ですが、閲覧したいページや画像、動画などをWebサーバに要求して、内容に応じてWebサーバがレスポンスを返します。レスポンスを受け取ったWebブラウザは画面上にページや画像、動画などを表示します。

 

##5.　クローラーブロック対策

クローラーエンジニアはクローラーを開発する人と言っても、クローラーブロック対策を了解するのも重要です。一般的なクローラーブロック対策は次のとおりです。

###（1）アクセス頻度制限

頻繁にアクセスする場合、WebサイトがこのIPをしばらくブロックすることがあります。その一方、クローラーを開発するとき、クローラーが人間のような頻度でWebページにアクセスするようにしようとすることができます。

###（2）ログイン制限

ログインのステップを追加位して、クローラーのアクセスを拒否するのは普通ですね。ただし、現在のクローラーは、ログインをシミュレートし、Cookieを追加することでログインを解決することもできます。

###（3）Header制限

通常、SafariやChromeなどのブラウザを使ってWebサイトにアクセスする場合、Headerやオペレーティングシステムの情報があります。クローラーでアクセスする場合、そのようなHeaderはありません。

###（4）動的なJavaScriptコンテンツ

一部のWebページにはJavaScriptを介して生成されるコンテンツがあります。つまり、JavaScriptを使うと、新しいコンテンツが表示されたり変化します。このような動的なWebページをスクレイピングするのは難しいです。

###（5）CAPTCHA

CAPTCHAはコンピューターと人間を区別するバクロニムです。ゆがんだ文字列と数字が使われるCAPTCHAは人間にとって理解しやすいですが、クローラーにとってそれを認識するのが難しいです。

###（6）IP制限

この方法では、特定のIPが永久にブロックされる場合がありますが、実際のユーザーに迷惑をかけてしまう可能性があります。

 

 

#まとめ

いかがでしたか？クローラーエンジニアは思ったような退屈な仕事ではなく、学ぶべきこともたくさんありますね。

もちろん、社内のエンジニアリソースが足りないであったり、そもそも技術的なスタッフがいなったり、わざわざエンジニアを雇う予算がない場合もあります。幸いに、[Octoparse](https://www.octoparse.jp/)のような[Webクローラーツール](https://www.octoparse.jp/blog/top-20-web-crawling-tools-for-extracting-web-data/)を使って、誰でもクローラーを開発でき、誰でもクローラーエンジニアになれます。自社にノウハウがないが、課題解決にデータを収集したい場合は、ぜひWebクローラーツールを試してみてください。
Markdown記法 メモ

#Markdown記法 Qiita

##バッククオート
よく使う 
｢`｣ これは､
｢バッククオート｣という｡

｢shift + @｣ ＝ ｢`｣

##背景をつける①

```
`背景をつける①`
```
↓表示↓
`背景をつける①`

##背景をつける②

```
```背景をつける② ```
```

↓表示↓

```
背景をつける②
```

##シンタックスハイライト


``` 
```index:たいとる
あああ  ``` 
```
↓表示↓

```index:たいとる
あああ
```

----

```
```ruby:たいとる
puts "Hello world"  ```
```
↓表示↓

```ruby:たいとる
puts "Hello world"
```



##文字を太く

```
デフォルト **太字**
```

↓表示↓
デフォルト **太字**



##チェックボックス

```
- [x] ruby
- [ ] rails
```

↓表示↓

- [x] ruby
- [ ] rails


##リンク

```
[参考になるリンク](https://qiita.com/)
```

↓表示↓
[参考になるリンク](https://qiita.com/)


知っているとそれなりに仕上がりそうだな〜と思ったものをまとめました｡

---
追記2019/09/17
###文字色変える方法
参考になる記事があったので貼っておきます｡
[Qiitaのマークダウンで色をつける方法[140色]]
(https://qiita.com/twipg/items/d8043cd4681a2780c160)
Spring bootサンプルアプリケーション: 掲示板

# 目的
このアプリケーションを作るのは、Spring frameworkを構成する、いろいろなコンポーネントの流れを説明するため。あるいはSpring frameworkのコンポーネントを練習できるプレイグラウンドとして使われる。

# 機能
- 決められた時メッセージを表示すること
- メッセージを表示する前、許可すること
- 多言語ユーザーインターフェイス

# 使われる主要なコンポーネント
- Spring Boot 2.1.X
- Spring MVC 5.1.X と thymeleaf 3.0.X
- Spring Security 5.1.X
- Spring JDBC 5.1.X
- Dozer 5.5.X

# データベース
データは埋め込み H2 データベースに記憶する。スキーマとデータはアプリケーション起動時がインポートされ、それからアプリケーション終了時全てのデータがなくなった。

# 必要なもの
- Java SE Development Kit 8以降
- インタネット接続

# コンパイルと実行
Apache Mavenラッパーがついていて、だからパッケージマネージャが用意されなくでもいい。

## コンパイルする (Microsoft Windowsの場合)
```
mvnw package
```

## 実行する (Microsoft Windowsの場合)
```
mvnw spring-boot:run
```
アプリケーションを閉じたい時、Ctrl+Cを押してください。

# アカウント
| ユーザーネーム | パスワード | 権限 |
|:-------- |:-------- |:----------- |
| user1    | user1    | USER        |
| user2    | user2    | USER        |
| admin    | admin    | USER, ADMIN |

# ソースコード
ソースコードは[ここ](https://github.com/saladlam/spring-noticeboard)でダウンロードできる。
普段はGitHubだけどGitLab案件に放り込まれて上手くgit clone出来なかった人のために

## 診断
1. GitHubを使っている時は`.ssh`以下のConfigファイルにgithubのHostを書いていたか
2. 鍵ファイルはデフォルトの`id_rsa`で作成して何も考えずに使っていた
3. GitLabで新たに鍵ファイルを作成したか

以上3つのどれかに当てはまれば読んでください。

## 原因 - デフォルトで読みに行かないファイル名
>ssh接続の際「~/.ssh/id_rsa」、「~/.ssh/id_dsa」、「~/.ssh/identity」しか
>デフォルトでは見にいかない

新しく作成した鍵ファイルは上記の名前とは違うファイル名で作成しませんでしたか？
その場合は自動で読みに行ってはくれません。

参考
https://qiita.com/shizuma/items/2b2f873a0034839e47ce

## 対策 - ~/.ssh/configを作成しその中に

```
Host gitlab
  User {user}
  Port 22
  HostName {hostName}
  TCPKeepAlive yes
  identitiesonly yes
  identityFile {sshKey}
```

GitLabのgit cloneのコピペ部分に`git@gl.projects:account/app/test.git`とあるとします。
また鍵ファイルは`~/.ssh/gitlab_id_rsa`に作成したとします。

とすると上記の`{}`で囲った部分は下記のようになります。

```
Host gitlab
  User git
  Port 22
  HostName gl.projects
  TCPKeepAlive yes
  identitiesonly yes
  identityFile ~/.ssh/gitlab_id_rsa
```

参考資料
https://qiita.com/0084ken/items/2e4e9ae44ec5e01328f1

```
Host                   ホスト名
  HostName             ホストのアドレスかIPアドレス
  User                 ログインユーザ名
  IdentityFile         ログインするための秘密鍵のパス
  Port                 ポート番号(デフォルトは22)
  TCPKeepAlive         接続状態を継続したい場合：yes　継続しない場合：no
  IdentitiesOnly       IdentityFileが必要な場合：yes　必要ない場合：no
  ServerAliveInterval  一定期間サーバからデータが送られてこないときに、タイムアウトする秒数。(例) 120
```

## テスト
下記の記述で接続できればGit Cloneも可能です！

```
ssh -T gitlab    // configのHostで指定した任意の名前
```

## クローン

デフォルトの鍵ファイル名でやっていたときは何も考えずにGitHubやGitLabのコピペ場所の物をコピーしてきて
`git clone` + コピペ文字列
で出来ていましたが今回はconfigファイルを読みに行ってもらいます。

```
git clone gitlab:account/app/test.git
```

デフォルトの時に比べて`:`より前が変わっている事がわかりますね！

例）

```
# デフォルト
git clone git@gl.projects:account/app/test.git

# configを読む
git clone gitlab:account/app/test.git
```
Spring boot example application: notice board 

# Objective

I write this application is for explain the mechanism of different component of Spring framework. This can also be used as playground for testing components of Spring Framework.

# Function
- Display notice on stated time
- Approval before display
- Multi language UI

# Main component used
- Spring Boot 2.1.X
- Spring MVC 5.1.X with thymeleaf 3.0.X
- Spring Security 5.1.X
- Spring JDBC 5.1.X
- Dozer 5.5.X

# Database
Data stored in embedded H2 database. Schema and data is imported when application start and all data will be lost after application shutdown.

# Prerequisite
- Java SE Development Kit 8 or above
- Internet connection

# Compile and run
Apache Maven wrapper is included, no addition package manager is necessary.

## Compile (On Microsoft Windows)
```
mvnw package
```

## Run (On Microsoft Windows)
```
mvnw spring-boot:run
```

Open browser and enter "http://localhost:8080". Press Ctrl+C to stop.

# Account
| Username | Password | Authorities |
|:-------- |:-------- |:----------- |
| user1    | user1    | USER        |
| user2    | user2    | USER        |
| admin    | admin    | USER, ADMIN |

# Source code
You may download source code from [here](https://github.com/saladlam/spring-noticeboard).
centos6でLetsEncryptの自動更新

#問題

古いOSでLetsEncryptと同居はいろいろ問題に出会う。
pyhtonバージョンを最新にしないといけない。そこにヒロー登場だ。 ~~pyenv!~~ pythonではvirtualenvを使おう

下記の定期更新(cron)でいつからかエラーになっていた。


```bash
/etc/letsencrypt/renewal/subdomain.domain.com.sh

省略
ons/2.7.1/lib/python2.7/site-packages/botocore/session.py", line 335, in get_scoped_config\n    raise ProfileNotFound(profil[profile aws8-r53]
e=profile_name)\nbotocore.exceptions.ProfileNotFound: The config profile (aws4-r53) could not be found\n'
省略
```

pyenv global 3.7.4　に設定され、python version はちゃんと3.7に表示されるのに
awsコマンドがpython2.7で実行される

#解決1

awscliをpyenv globalを切り替え後、改めてインストールする

pyenvは参考まで

```bash
pyenv global system
pip uninstall awscli
pyenv global 3.7.4
pyenv version
pip install awscli

mv /usr/bin/aws /usr/bin/aws_bak
ln -s /root/.pyenv/shims/aws /usr/bin/aws
```

#解決2

The config profile (aws4-r53) could not be found

awscliがバージョンアップでprofile内容の仕様が変わったよう。これ分かるのに半日つぶれた・・・

[aws4 aws4-r53] -> [aws4-r53]

```
cat /root/.aws/credentials 

[aws4 aws4-r53] -> [aws4-r53]
aws_access_key_id = XXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXX
region = ap-northeast-1
```

#参考
https://certbot.eff.org/lets-encrypt/centosrhel6-apache
Autodesk Inventor API Hacking (Context Menuの表示)

# 0. はじめに
Context Menuとは、右クリックすると出てくるMenuのことです。
それをカスタマイズしてみよう、という話しです。

# 1. Context Menu表示のしくみ
Inventorの場合は、ユーザー(AddIn開発者)がContext Menuを表示するには、予めMenuを作っておき右クリックEventでそれを表示するのでは**ありません。**
特に何も設定していなくても、右クリックをすればMenuが表示されます。
![ContextMenu1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424028/4591db37-c483-5311-c0fc-3be6a7c907fb.png)
上の画像は、自作AddInで`InteractionEvents`実行中に右クリックをしたものです。
空に近い、最低限のMenuが自動で用意されて表示されます。
自前のMenuを表示するには、動的にこのMenuをカスタマイズします。

# 2. Menu表示をHookする
Context Menuが表示される前に、次のEventが発生します。

```C#
Inventor.CommandManager.UserInputEvents.OnLinearMarkingMenu
```

これをHookして、表示内容を動的に書き換えるわけです。似たようなものに、`UserInputEvents.OnContextMenu`がありますが、これは互換のためなのか、現在のAPIドキュメントには記載されていません。マーキングメニューの導入と同時に、改定されたのでしょう。
なお、名前にMarkingMenuとありますが、`カスタマイズ` → `マーキング メニュー` → `クラッシク右クリック メニューを使用`にチェックを入れていても、このEventでHookできます。

さて、Menuに1行追加するには、次のようなcodeになります。

```c#
private void UserInputEvents_OnLinearMarkingMenu(ObjectsEnumerator SelectedEntities,
                                                 SelectionDeviceEnum SelectionDevice,
                                                 CommandControls LinearMenu,
                                                 NameValueMap AdditionalInfo)
{
    LinearMenu.AddButton(insertingMenuItemButton);
}
```

シンプルにMenuに1行追加するには`AddButton()`を使います。他にも色々ありますが、それらについてはAPI Helpを参照してください。
さて、この`AddButton()`の引数は、`ButtonDefinition`です。つまり、Menuに項目を追加するためには、1項目(1行)ずつ`ButtonDefinition`を作る(`Inventor.CommandManager.ControlDefinitions.AddButtonDefinition()`を実行する)必要があります。これらは一度作っておけば、使いまわしできます。
なんとも邪魔くさい話ですが、逆を言えば、Inventorで使える大よそ全ての機能をContextMenuに追加出来ます。

# 3. 選択されたことを知る
Menuに表示されているのは、`ButtonDefinition`ですので、選択されると`OnExecute`Eventが発生します。Ribbon上でButtonが押されたのと同じですね。

#4. やってみた & チェックボックス
さて、実際に追加してみました。
![ContextMenu2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424028/7126373b-c3c8-5ca9-5f04-8d6f6d0a67bb.png)
1行目の`投影する`がそれです。ここで、テキストの左にチェックが入っていることに注目してください。
これをどのように実装するのかで結構悩んだのですが、答えは簡単でした。

```c#
ButtonDefinition.Pressed = true;
```

これで、チェックが入ります。選択する度にトグルしたいのなら、`OnExecute`は次のようになるでしょう。


```c#
private void MenuItemButton_OnExecute(NameValueMap Context)
{
    MenuItemButton.Pressed = !(MenuItemButton.Pressed);
}
```

# 5. 注意点
`UserInputEvents.OnLinearMarkingMenu`はグローバルなEventなので、Inventor実行中は常に有効です。
自作コマンドの実行中だけHookしたいのであれば、`InteractionEvents.OnActivate()`/`InteractionEvents.OnTerminate()`でEventを追加/削除すると良いでしょう。


# 99. 親の記事に戻る
[Autodesk Inventor API Hacking (概略)](https://qiita.com/yamarah/items/cee08eb8f2b7aecbda83)
Ruby on Rails ビューファイル に リンク を 表示する

# 目的

- Ruby on Railsで作成したビューファイル内にリンクを作成する。  
※本記事はRuby on Rails超初心者の筆者がまとめたものです。情報が正確ではない可能性があります。誤を発見したらそっと教えていただけたら幸いです。

# 押さえるポイント

- 基本的にビューファイル内でのリンクは`<a>`ではなく`link_to`メソッドを使用する。
- リンク先のURLはルーティングファイルに書かれたものと同じもので指定する。
- ビューファイルはhtml形式なのでそのまま`link_to`メソッドは書けない。
- <%= %>を使用してリンクを書く。
- <a herf="URL">リンク先</a>とlink_to("リンク先", "URL")

# 書き方の例

- 下記にRuby on Railsのビューファイルにてリンクを作る処理を記載する。

``` html
<%= link_to("リンクにする文字", "URL") %>
``` 

# より具体的な例

- ビューファイルにリンクを作成する。
- リンク先のURLは`localhost'30000/about`とする。
- リンクとしてクリックできるようにする文字は`概要はこちら`とする。
- 下記にRuby on Railsのビューファイルにてリンクを作る処理を記載する。

``` html
<%= link_to("概要はこちら", "/about")%>
```
MDX-DeckとCode Surferを使うとスライドもコーディングできる

# 筆者の技術前提
- javascript初心者
    - npmにようやく慣れてきた程度
    - reactは超初心者。勉強方法教えてください。
- markdownは結構書いた経験がある（仕事でも議事録とか）
- 論文をtexで書いてきたので、文書をコーディングすることに拒否感はない。

# モチベーション
- 某セミナーでパワポ（Office、Google）ではないスライドばっかりだったのに衝撃を受けて。

# ディスビッグバネイト先(TL;DR)
基本的にこれをパクって要素つまんで記載する方針ですので、下記サイトで満足した場合はそのまま戻らずに閉じましょう。
## 日本語の解説記事
- [Takumonさんの「MDX-DeckとCode Surferでスライドを作ろう！」](https://takumon.com/2018/12/23/)
- [ガンガン作り変えているJesseさん](https://code-surfer-v3.naturalclar.now.sh/12)

# 作ってみたもの
pythonのハイライトが微妙な気がするが、やりたいことはできている
https://taniyuu.github.io/mdx-sample/
もうちょっとmdxに慣れる必要はある。

## 詰まったところ
- code surferが7か月前から止まってるので、MDX-Deckの最新版と互換性がなく？ビルドエラーになった
https://www.npmjs.com/package/code-surfer
    - わかんなかったので、Takumonさんのサンプルをかなり丸パクリすると動いた
    https://github.com/Takumon/mdx-deck-sample

## もうちょっと調査して書きます。
関連記事：[ドキュメント，テキスト化への旅 vol.1 スライド](https://qiita.com/high-u/items/aef51c3651b120880c63) 
様々な類似ツールを調査したうえで、試しています。
Project Euler 004を解いてみる。「最大の回文積」

#Project Euler 004
[004](http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%204)
>左右どちらから読んでも同じ値になる数を回文数という. 2桁の数の積で表される回文数のうち, 最大のものは 9009 = 91 × 99 である.
では, 3桁の数の積で表される回文数の最大値を求めよ.

->[次の問題](https://qiita.com/radiol/items/7cd16716ef77a28dfc2c)
## 考え方
回文数の判定のため、数字の並びを反転する関数を考えました。
10で割った余りを利用して一の位から順番に数字を抜き出し、resultに足します。次のループでresultに10をかけて桁を左にずらしています。
アルゴリズムとして割とスッキリできたと思います。

```Python:euler004.py
def number_reverse(n: int) -> int:
    """
    正の整数nを反転させた整数を返す。
    n=1234 -> result=4321
    :param n: int
    :return: int
    """
    result = 0
    while n > 0:
        result *= 10
        result += n % 10
        n = n // 10
    return result
```

###追記
コメント頂きましたので修正いたしました。strへの型変換を行うと速度が遅くなるかなと思っていたのですが、上のアルゴリズムとstrに型変換して[::-1]で逆順を比較したところ、型変換のほうが2.5倍くらい早いという結果になりました。
おそらくwhile内の計算量 > 型変換ということなのでしょう。

```Python
def str_main():
    n = 10 ** 3 #3桁を対象
    answer = 0
    for i in reversed(range(n // 10, n)): #iは999~100の順で生成
        for j in reversed(range(i, n)): #jは999~iの順で生成
            temp = i * j
            if temp < answer: #最大値を求めるのでi*jがansより小さいなら以降の判定は不要 
                break
            str_temp = str(temp) #乗算した結果を文字列[str]に変換
            if str_temp == str_temp[::-1]: #スライス機能を使い、[::-1]で反転した文字列を取得
                ans = temp
        if i * (n - 1) < answer: # iはどんどん小さくなるので、i*jの取りうる最大値(=i*999)よりanswerが大きければ以降の処理は不要。
            break
    print(answer)


if __name__ == '__main__':
    str_main()
```


## コード
内包表記で100~999のそれぞれを乗算したsetを作成しlistに変換。setから変換することで重複を削除しています。i * jではiとjは入れ替え可能なのでi ≦ jとしています。
`sort(reverse=True)`で逆順にしてforでループを回しています。
かなり無駄な数のリストを作ってしまっているのでこの部分をどうにかスッキリしたいところですが、
良い案が思いつかないので、そのまま回しています。

```Python:euler004.py
def main():
    n = 10 ** 3 # 3桁を対象
    num_list = list(set(i * j
                        for i in range(n // 10, n)
                        for j in range(i, n)))
    num_list.sort(reverse=True)
    for n in num_list:
        if n == number_reverse(n):
            print(n)
            break


def number_reverse(n: int) -> int:
    """
    正の整数nを反転させた整数を返す。
    1234->4321
    :param n: int
    :return: int
    """
    result = 0
    while n > 0:
        result *= 10
        result += n % 10
        n = n // 10
    return result


if __name__ == '__main__':
    main()
```
`結果
906609
main処理時間: 0.16022491455078125 sec.
`
Rust Hello World - Debugging on Docker

Rustのハローワールドをしようと思い、Visuao Studio CodeのRemote Containerを使って環境を作りました。

[dbgso/vscode-devcontainer-rust](https://github.com/dbgso/vscode-devcontainer-rust) にソースは上げています。

# 使い方

1. ソースをcloneしてVisual Studio Codeで開く
2. 表示されたダイアログをクリックしてコンテナ内で開く
3. あとは流れで

っていう感じです

## ソースをcloneしてVisual Studio Codeで開く

```
$ git clone https://github.com/dbgso/vscode-devcontainer-rust.git rust-code
$ code rust-code
```

## 表示されたダイアログをクリックしてコンテナ内で開く

これで`Reopen in Container`を選んで、コンテナ内で開きます。

![](https://camo.qiitausercontent.com/f57c1f5989a79a862b46bc86d6a14115a37a21f9/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3333303531342f39633039333066302d393135652d656461322d383938302d3035623130313461353936642e706e67)

## あとは流れで

残りは色々な設定を自動でしてくれるので、指示されるままにいけば良かったです

### コンテナのビルド

 Dockerfileに定義された準備処理が走ります。

動作させるだけであれば`rust-lldb`のインストールだけで良いですが、`project_init` というプロジェクト初期化のライブラリも入っています。

```Dockerfile
FROM rust:1.36

RUN cargo install project_init
RUN apt update && apt install -y rust-lldb 
```

### デバッグ用ファイル取得

しばらく待機します

```
Acquiring platform package for CodeLLDB.
Package is located at https://github.com/vadimcn/vscode-lldb/releases/download/v1.3.0/vscode-lldb-x86_64-linux.vsix
Downloading...
Downloaded 0%
Downloaded 6%
Downloaded 12%
Downloaded 18%
Downloaded 24%
Downloaded 30%
Downloaded 36%
Downloaded 42%
Downloaded 48%
Downloaded 54%
Downloaded 60%
Downloaded 66%
Downloaded 72%
Downloaded 78%
Downloaded 84%
Downloaded 90%
Downloaded 96%
Installing...
Done.

```

### Rust(Rust Language Server) のインストール

`*.rst`のファイルを開くとこんなダイアログが出るので、`Yes`を押してインストールしておきます。

<img width="449" alt="スクリーンショット 2019-09-03 17.46.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330514/fb1b346e-bdac-6302-569c-760b29423e4f.png">

## 実行


### `launch.json`の作成

自動作成してもらいます。

`F5`キーでデバッグ実行しようとすると、ダイアログが出るので`LLDB`を選択します。
以下のようなダイアログが出たら`Yes`で

<img width="431" alt="スクリーンショット_2019-09-03_17_14_47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330514/75a8269e-40e4-9eaf-14b1-e0aba8ea5c2f.png">

### ブレークポイントで止める

あとは普通にブレークポイントをセットして`F5`キーで実行すればブレークポイントで停止できます。

<img width="1440" alt="スクリーンショット_2019-09-03_17_14_20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330514/fac27678-96b3-2ab1-b7a0-cf0985428a3a.png">


# まとめ

C++からの流れでRustを触ってみましたが、非常に楽でよかったです。
補完やフォーマッタ、リファクタ機能も標準で動いてとても良い感じです
今後がっつり触る機会があるかもしれないので、その時は今回の環境を活用していきます。



# 参考

[Rust のデバッグ環境構築 - Qiita](https://qiita.com/yamoridon/items/3be3f0515a79567a0588)

[Rustの環境構築 with VSCode - Qiita](https://qiita.com/udayan28/items/e59afd39a7ab16911c25)
【Yasm】コンパイル&インストールする方法

#概要
Linux/MacにYasmをインストールする。

#手順
##1. ソースコードダウンロード
[こちら](http://www.tortall.net/projects/yasm/wiki/Download)から`Source .tar.gz`をクリックしてソースコード(`yasm-1.3.0.tar.gz`)をダウンロードする。

##2. 解凍
```shell:
$ tar -xvf yasm-1.3.0.tar.gz
$ cd yasm-1.3.0
```

##3. コンパイル
```shell:
$ ./configure
$ make
```

##4. インストール
```shell:
$ sudo make install
```

##5. 確認
```shell:
$ yasm --version
```
確認できたらソースコードは不要なので`yasm-1.3.0`は削除しても良いです。

#Happy Hacking :sunglasses: !

#参考
http://www.tortall.net/projects/yasm/wiki
複数のGitアカウントを使い分ける方法

## はじめに
初めまして、[ｋ．ｓ．ロジャース](https://www.wantedly.com/companies/ks-rogers)の西谷です。

私がリモートワークを行う上で意外に困ったのがGitアカウントの使い分けです。
同じPCで会社と個人で別々のアカウントを利用したい場合は`.gitconfig`の中身を毎回書き換える必要があり煩雑でした。
また、`.gitconfig`の変更を忘れて会社リポジトリに個人アカウントでコミットしてしまうこともあります。

ローカルの時点で気づけばいいのですが、PRがマージされた後だとどうしようもなくなります。
そこで、今回は自動でGitアカウントを切り替える方法を共有出来たらと思います。

## 環境構築
[direnv](https://direnv.net)を導入します。
direnvは設定ディレクトリ以下の環境変数を切り替えるツールです。
ディレクトリ別の環境変数を切り替えてGitアカウントを変更する方針です。

```
brew install direnv
```


インストール後`.bashrc`に以下を追加します。

```
eval "$(direnv hook bash)"
```

`source ~/.bashrc`して反映します。

## コンフィグの設定
direnvの設定は`.envrc`を作成します。
`.envrc`にGitアカウントの設定を追記します。

```
export GIT_COMMITTER_NAME='user'
export GIT_COMMITTER_EMAIL='hogehoge@example.com'
export GIT_AUTHOR_NAME='user'
export GIT_AUTHOR_EMAIL='hogehoge@example.com'
```

作成後、`direnv allow`すると有効になります。

## 動作例
例として、ディレクトリ構造は次のようにします。

```
.
├── private
│   ├── hoge-pj
│   │   ├── README.md
│   │   └── hogefile
│   └── .envrc (個人用の設定)
└── work
    ├── hoge-pj
    │   ├── README.md
    │   └── hogefile
    └── .envrc (職場の設定)
```

privateとwork直下で`direnv allow`を実行します。

実行後、privateディレクトリ以下のリポジトリでコミットした場合はログは次のようになります。
<img width="599" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274674/d3804869-1814-9232-15da-886228474c5b.png">

workディレクトリの場合はこちらです。
<img width="584" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274674/4c9ee260-b27d-2a58-2079-91e140db363e.png">


## おわりに
今回はGitアカウントの切り替えを導入しました。
これでconfigファイルの変更を忘れて、違う名前でコミットしてしまうような事故は無くなると思います！

間違いや他にいい方法等あればご指摘頂けたらと思います。

### Wantedlyでもブログ投稿してます
Techブログに加えて会社ブログなどもやっているので、気になった方はぜひ覗いてみてください。
https://www.wantedly.com/companies/ks-rogers
kaggle notebookの技術仕様のメモ

・実行時間9時間
・５GBの自動保存ディスクスペース(/kaggle/working)
・16ギガバイトの一時的なスクラッチパッドディスクスペース（/ kaggle / workingの外側）

CPUの仕様
・4 CPUコア
・16ギガバイトのRAM

GPUの仕様
・2 CPUコア
・13ギガバイトのRAM

1時間の何もしないとコードが保存される。
コミットの場合は6時間以内の計算が行える。
Windows 10でTortoiseGitにて、アカウント情報の削除方法の色々

Windows 10でTortoiseGitを使う場合、1回設定してしまえば、ずっと使える機能に遭遇する。

怠惰の権化たる自分にとっては、とても便利な機能ではあるが、アカウントを切り替える際にとても邪魔になる。

アカウントが消えなくて、結果1日半戦ったので、消し方を書いておく。


## 消し方色々
消す方法は１つではない…というか、消せなかったら段階的に別の方法を試していく。

### 資格情報マネージャーから消す
一度ウィンドウでログイン情報入力した物は、その後入力せずに良いというwindowsの便利機能『資格情報マネージャー』に入っている。

タスクバー『検索』ボックスで『資格情報マネージャー』と入力し、起動。
『Windows 資格情報』→『汎用資格情報』に、『git:https://【該当gitサーバ】』があれば消す。

あとはcloneなりpushなりすると『ネットワーク資格情報の入力』が出てくるので、新しいアカウントでログインし直せばOK。

大概はコレで問題は解決する。


### TortoiseGitの情報を見直す
『フォルダ内を右クリック』→『TortoiseGit』→『設定』→『Git』→『資格情報』
ここに該当の情報がある場合がある。

何も設定していなければ『manager - 全てのwindowsユーザー』。
その場合は、何も気にせずスルー。


### git設定を確認する
『フォルダ内を右クリック』→『TortoiseGit』→『設定』→『Git』。
そこで『ローカルリポジトリの設定』『このユーザの設定』『全ユーザの共通設定』を見直す。

これらの内容は基本的に『Windows 資格情報』やTortoiseGit設定の『資格情報』の内容に依存するので、基本的には直接いじることはない。

ここでおかしい場合は、これより前の段階でおかしな情報に、遭遇しているハズ。


### .ssh設定を確認する
『C:\Users\【ユーザ名】\\.ssh\』に『id_rsa』等があれば、そこに設定されている可能性がある。

httpsからgitしていた場合、関係ない。


### netrcファイルを削除
2重認証アカウントでも楽に使うことが出来るnetrc設定。
『C:\Users\【ユーザ名】\\_netrc』※windows以外では『.netrc』
あまりオススメはされていない存在なので、気兼ねなく消せる。


### これでも解決しない…
全体にgrepかけて、祈るようにファイルを探してみましょう！
WindowsでもGitBushで使えます！

```
grep -r 【消えないユーザID】 ./*
```

見付けたらラッキー！
名前を変えてよう！　※自己責任
消したら戻せなくなるので、名前を変えても残してはおいてください。
まぁ、残しておいたとしても、直せるとは限らないけどね！
※自己責任！　本当に自己責任！

もし、これがあった場合、教えて下さい！


## まとめ
基本的に資格情報マネージャの方法だけ知っておけば、基本的に困りません。
これで解決しなかったときが、この記事の真価ですとも。

解決したとき、歓喜します、本当に…
python Bottleの基本2 Bootstrap4

#Web serverを簡単に作成できることは、[「基本1」](https://qiita.com/hiratarich/items/9eaf8ccf3957d107d539)で説明した。
iPhoneやAndroidなどのスマートフォン向けにWeb　コンテンツを作成するのは、少々難しい。たいていの場合、プログラマは、デザイン的な作業はしないのであまり詳しくない。
HtmlとCssを駆使してデザインしていくのだが[Bootstrap4](https://getbootstrap.jp)を使えば簡単に実現できる。
Bootstrap4の解説には、「CDN とテンプレートを使ってモバイルファーストなサイトを構築できます。」とある。
>CDNとは、コンテンツデリバリネットワーク（Content Delivery Network）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/ee8104b5-0cb4-04fc-3987-34cf54ca6a25.png)
#「レスポンシブウェブデザインでモバイルファーストを実現しています。」と書いてある意味は、
一般的には、CSSとJavaScriptsを駆使して作成するのだが、多くの場合、レスポンシブになっていない。
Bootstrapの意味は、くつひものようなプログラムといういみです。
昔、ミニコン時代紙テープを読み込むプログラムをBootstrapと呼んでいて、ミニコンのパネル短いプログラムを2進スイッチから入れて使用した。

#基本形は、以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/b5070c7e-a200-8c8b-ce8b-c486cdc3c2a7.png)


```ex2.py
# bottleの基本2
from bottle import *
html='''
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8" />
    <title>Hello World</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>            
    </head>
<body>
<div class="container body-content">%s</div>
</body>
</html>'''

@route('/')
def home():
    return html%"<h1>Hello World</h1>"
HOST,PORT='localhost',8080
if __name__ =='__main__':
    run(host=HOST,port=PORT)
```
```
<div class="container body-content">%s</div>
.....
return html%"<h1>Hello World</h1>
テンプレートの%sにHello Worldを挿入している。
```
#これでは、ありがたみがわからないので５個のボタンを作ってみよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/0f3fca74-d7ec-2408-8f22-c7727aba525f.png)

```
def home():
    btn="".join(["<button class='btn btn-primary' style='margin:1em;width:100px;'>%s</button>"%x for x in '東京,神田,お茶の水,四谷,新宿'.split(',')])
    return html%btn
```

きれいに配置されていることがわかる。
正規表現で特定の文字を抜き出す

あるDOMにスクレイピングをかける。

```python:test1.py
print(driver.find_element_by_id('hoge').text)
```
するとhogehoge3fugafugaと表示される。
これは想定通りの動き。

このテキストはアクセスするたびにランダムに変わり、
必ず以下の3パターンのどれかになる。

- hogehoge3fugafuga
- hogehoge5fugafuga
- hogehoge10fugafuga

この間に挟まった数字だけを抜き取りたい。

pythonのsplit関数を使えば造作もないが見栄えが汚い。

そこで正規表現を使えないかと考えた。

teratail先生に問い合わせて自分で試行錯誤した結果これが答えだった。

```python:test1.py
import re
print(re.search(r"(3|5|10)", driver.find_element_by_id('hoge').text))
```

1時間も考えずにとっとと先生に頼ればよかったと反省。
Downdetector との正しい付き合い方

# この記事について
Downdetector (ダウンディテクター) について勘違いしている人が多数見受けられるので、正しい使い方(?)をまとめたものです。

# AWS東京リージョンの大障害
[2019/08/23にAWS東京リージョンで大障害が発生](https://aws.amazon.com/jp/message/56489/)しました。
サービスが停止して阿鼻叫喚した方、仕事にならないと諦めて帰った方、など、悲喜こもごもだったのではないかと思います。

そんな障害発生している際、主にSNS界隈で以下のような地図をよく見かけませんでしたでしょうか？
![dd_map.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169018/3a684795-7503-6285-7a02-486692312dd1.png)
この地図は Downdetector ( `ttps://downdetector.jp/` ←あえてリンクにはしません ) が提供している障害発生マップです。
上の画像は8/23の実際のAWS障害時にスクリーンショットを撮ったものです。

この地図をパッと見て、どのように感じるでしょうか。
「 『Amazon Web Service の障害発生マップ』で、東京と大阪が赤くなっているから、そこで大障害が発生しているんだな」と思う方が多数だと思います。
しかし、**この地図が表している情報は「障害が発生している事実」ではありません**。

--- 
**\<追記 2023/11/13>**
2019年当時は上記のようなスクリーンショットをSNSに貼るのが主流でしたが、現在は以下のようなスクリーンショットが主流のようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169018/353e180f-a6b9-e067-d7a0-86c3d1f47af2.png)
この折れ線グラフの爆上がり量を見て「障害」と短絡的に判断している人が多数のようですが、**このグラフが表している情報は「障害が発生している事実」ではありません**。
**\<\/追記>**

# Downdetector が提供している情報とは？
## この Downdetector のページに表示されている情報は何？
そもそも、この情報の元ネタは何なのでしょうか？

Downdetectorのサイトによると、以下のような記載があります。

>ダウンディテクターの機能について
>
>ダウンディテクターは様々な情報源から障害状況レポートを収集します。 収集したデータをリアルタイムで分析することにより、私たちのシステムはかなり早い段階で自動的に障害やサービスの中断を探知することが可能です。 分析するレポートの情報源のひとつがツイッターです。

（`ttps://downdetector.jp/downdetector-nitsuite/` より引用）

**\<追記 2020/09/29>**
2020/09時点では以下のような記述になっています。

>Downdetectorの仕組み
>Downdetectorは、弊社のウェブサイトやモバイルアプリに提出されたレポートや、Twitterなど、一連のデータソースから、ステータスレポートを収集します。弊社のシステムではレポートがリアルタイムに検証・分析されるため、障害やサービス停止が発生した際には、初期の段階で自動的に検出することが可能となっています。 

(`ttps://downdetector.jp/about-us/` より引用)
**\</追記>**

つまり、Downdetectorが表す情報は、実際に障害が発生しているという事実ではなく、**ユーザからの申告やツイッターなどのSNSなどで「障害なんじゃね？」とザワザワしている状況** です。
グラフの表示は、発生中の障害の規模ではなく **「ユーザのザワザワ度合い」** でしかありません。

## 「流れ弾」的な誤報の可能性も
上記の通り、Downdetector は、ツイッターを始めとするSNSの情報を重要視しているようです。
ここで、

> AWSの東京リージョンで障害が起きているらしい。困った困った。

こんなツイートを「AWSの障害」と判断してくれるのは理解できると思います。
そうではなく、

> AWSの東京リージョンで障害が起きているらしいけど、おれはAzureを使ってるから大丈夫だよーん。

こんなツイートがあると、どうやらDowndetectorは 「Azureの障害」とも判断してくれるようです。完全な流れ弾です。
あくまでSNSの情報を機械的に解析しているだけでしょうから、こんな判定ミスが発生してしまうのも仕方ないと思います。

実際問題、2018年12月に Softbank が大きな通信障害を起こした際、ドコモやauが流れ弾をくらった実績があるようです。
https://www.itmedia.co.jp/news/articles/1812/07/news081.html

# まとめ
- Downdetector は、障害の事実や障害の規模を伝えるサイトではなく、SNSの情報やユーザからの口コミを集約して可視化している「まとめサイト」です
- Downdetector の情報は、障害情報としての信憑性は高くないと言わざるを得ません
- 誤報も発生します

ということで、Downdetectorの情報だけを見て障害発生中と認識するのは危険であることは、ここまで読めばわかっていただけるのではないかと思います。
**Downdetector方面でざわついているのをきっかけにして、公式の障害情報を確認したり、自分で裏取りの確認をしたり、** というやり方が正しい使い方ではないかと思います。

# おまけ
IT系のメディアでも勘違いしている人が多数います。困ったものです。
例
- `ttps://www.itmedia.co.jp/enterprise/articles/1908/23/news111.html`
- `ttps://www.itmedia.co.jp/news/articles/1705/09/news086.html`
【初心者向け】HTMLテンプレートのPugを使ったら作業効率が上がった話

# はじめに
Web歴1年半の僕がPugを始めたらHTMLを書くのが10倍楽になったので記録として残します。

# 使った経緯
新卒のHTML&CSS研修中、LPを何個か作っていました。
3個目に差し掛かった辺りから、「あ〜、なんか飽きてきたな」と思い始め、楽な方法を探しました。
そこでPugを見つけました。

# Pugってなに？
>PugはHTMLを簡単に書くためのテンプレートエンジンで、CSSでいうSassのようなものです。
>PugはNode.jsで動いており、一部書き方がJavaScriptっぽいところがあります。

別の言い方をするとHTMLの拡張言語といったところでしょうか。
CSSでいうSassという例えが僕は一番しっくりきます。

# メリット

### 閉じタグ忘れがなくなる
HTMLでは開きタグと同時に閉じタグも必要になります。
今まではタグを変更するときに閉じタグも一緒に変更するのが少し面倒でした。
HTMLを書いたことがある人ならば一度は思ったことがあるのではないでしょうか。

### JavaScriptライクな書き方
他の言語同様、繰り返しや分岐処理が可能。

### 保守性が高い
HTMLのページや要素を追加する場合なども予め変数で用意しておけば追加するだけで他をいじる必要がない。



# どんな感じ
```index.pug
-
  var pages = [
    {
      name: "TOP",
      url: "./index.html"
    },
    {
      name: "MEMBERS",
      url: "./members.html"
    },
    {
      name: "COMPANY",
      url: "./company.html"
    },
    {
      name: "CONTACT",
      url: "./contact.html"
    }
  ]

header.l-header
  div.p-header
    div.p-header__inner
      h1.p-heder__logo
        a(href="index.html") HUMANS
      button.p-header__hamburger(aria-label="メニュー" type="button")
        span
        span
        span
      nav.p-header__globalNav
        ul.p-header__globalNav__list
          each page in pages
            li.p-header__globalNav__item
              a(href=page.url) #{page.name}
```


↓こんな書き方をすると...

```index.html
<header class="l-header">
  <div class="p-header">
    <h1 class="p-header__logo"><a href="index.html">HUMANS</a></h1>
    <button class="p-header__hamburger" aria-label="メニュー" type="button"><span></span><span></span><span></span></button>
    <nav class="p-header__globalNav">
      <ul class="p-header__globalNav__list">
        <li class="p-header__globalNav__item"><a href="./index.html">TOP</a></li>
        <li class="p-header__globalNav__item"><a href="./members.html">MEMBERS</a></li>
        <li class="p-header__globalNav__item"><a href="./company.html">COMPANY</a></li>
        <li class="p-header__globalNav__item"><a href="./contact.html">CONTACT</a></li>
      </ul>
    </nav>
  </div>
</header>
```

こうなります！

書き方はHTMLと多少違うという点で覚えることはありますが、慣れてくるとかなり速いスピードでかけるようになります。

ちなみにPugはVueのテンプレートタグでも使用できます。ありがたい。


# 終わりに
今回はマークアップの部分を効率的にかけるようになりましたが、こういった考えは日々持つべきだなぁと改めて感じました。
プログラマの三大美徳にもある「怠慢」を体現したように感じました。

その他の美徳に関しては[コチラ](https://beginner-to-engineer.tech/three-great-virtues/)を参照

参考文献:
- [HTMLを超簡単に書けるPugとやらをまとめてみました！](https://note.mu/n_oshiumi01/n/na0c14d85f3a0)
- [PugでHTMLコーディングを効率化・メリットと使い方を知る](https://tech.qookie.jp/posts/info-pug-feature/)
AWS Glueについて

AWS Glue? 
なにそれ美味しいの？レベルが現状。
その為キャッチアップの内容をざっくりまとめていく。それに伴い、気になった用語等々も併せて拾っていく。

## AWS Glueとは
- データ処理を自動化
- 日々行われるデータ収集やETL処理を自動化およびサーバレス化

👉 **サーバレスでデータの加工が出来るヨ**


#### ETLって？
- `Extract` (抽出する)
- `Transform` (変換)
- `Load` (格納)

リモートソースから情報を取得し、定義されたフォーマットとスタイルに変換し、データベース、データソース、またはデータウェアハウスにロードする統合アプローチのこと

### Glueの文脈での用語
- データストア：  
未加工のCSV, JSONによるログデータやアプリで使用している既存のDBなど
- データカタログ ：  
データ分析のために整備された領域
- クローラ：  
様々なデータストアからデータカタログに集約させる
- ジョブ：  
データカタログ内のデータをETLする

Glueはフルマネージドであり、その処理はスケールアウトするため、ユーザはデータ規模やインフラ運用を意識することなく、データを加工するスクリプト(ETLの"T"に対応)の作成に集中することが出来る。
ほかにも、Glueは、下記機能を備えている

- データカタログ上のテーブルメタデータのバージョン管理機能
- クローラでの入力データからのスキーマ自動推論機能
- クラシファイアでの検査に基づきスキーマの変更を検知する機能  
など

#### クローラ
データストアのデータをデータカタログに移住させるために使用する機能。

##### 目的
1. 散在する複数のデータストアそれぞれの見張り、最新データの発見
2. それらのデータをデータカタログへと集約
3. データカタログを最新に保つ

##### 出来ること
- クラシファイア(デフォ有、カスタム可)という要素を通じて、カラム名変更・型変換などの簡単な変換処理
- 半構造データをテーブルの形式に整える
- スキーマの変更検知

作成されたクローラには、ジョブ実行方法(オンデマンドか、スケジュールベースか、イベントベースか)が定義されている。
たとえば、クローラを定期実行させておくことで、データカタログがデータストアに対しおおむね最新であることが保証される。

#### ジョブ
より分析に適した形にするために、ETL処理をする機能

##### 目的
クローラを使って単にデータをデータカタログへと移住させただけでは、クエリを叩けてもデータが使いにくく、ユーザにとって分析が難しい場合がある。
このとき、より分析に適した形にするために、ETL処理を行うため。

Glueにおけるジョブとは、ETL作業を実行するビジネスロジック。
ジョブが開始されると、そのジョブに対応するETL処理を行うスクリプトが実行される。
こちらもクローラと同様に定期実行などの自動化が可能である。

##### 備考
ユーザは、ジョブ作成者として、抽出元(データソース)、およびロード先(データターゲット)を定義する。
ただし、データソースおよびデータターゲットは、どちらもデータカタログ上のデータです。
ユーザは、ジョブ処理環境を調整したり、生成されるスクリプトをビジネスニーズに基づいて編集したりする。


最終的に、Apache Spark API (PySpark) スクリプトが生成される。
👉自動生成...すごい...近未来感...

##### 参考
https://qiita.com/kuronat/items/675ddf16b466c5477f22
InvalidSignatureException: The request signature we calculated does not match the signature you provided. の解決

AWSのアクセスキーによる認証で、以下のエラーが発生して1時間手こずったので備忘録。

```
InvalidSignatureException: The request signature we calculated does not match the signature you provided. 
```
原因は、AWSのアクセスキーの発行では、Access Key ID と Secret Access Key が発行されますが、
このとき発行された Secret Access Key が原因でした。

こちらにissueとしてもあがっていました。
https://github.com/aws/aws-cli/issues/602
> it is still the case in June 2018 that secrets that have the slash (/) character in them may make the PHP client not work (PHP 7 on Windows 10 in my case), returning the signatures do not match error. In this situation, just generate another pair of keys that is safer.

Secret Access Key にスラッシュ（/）文字が含まれる場合、このエラーが発生することがあるそうです。
Base64のエンコードで問題が発生しているようです。

この状況での解決策は、アクセスキーの再生成です。

issueにも書かれているように、私も別のキーペアを生成し直すことで解決できました。
git  branchでエディタが立ち上がらないようにする方法

## git branchで標準エディタが立ち上がるのをやめたい

- ターミナルでgit branchを打つと自動的にエディタが立ち上がり、下記のようになって、毎回`q`押さないと戻れなくなってストレス・・・だったの設定変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85076/c8fce6be-7def-27bb-f78a-43b215c68bcf.png)


## git branchでエディタを立ち上げずにブランチを見る方法


- ターミナルを立ち上げて、下記をコピペ→Enter！


```
git config --global pager.branch false
```

ググってもあまり解決方法出ていなかったので、あまり皆さん気にしていないのですかね・・・？
同じような思いをしている方の参考となれば嬉しいです。
【備忘録】お気に入りのVS Code拡張機能

# 自分が気に入っているVS Codeの拡張機能
どの環境でもセットアップできるようにメモ程度に残します。
CodingもMarkdownなどのテキスト編集も近々VS Codeに統一しようかなと思ってます。

## VS Codeの見た目
- [Iceberg](https://marketplace.visualstudio.com/items?itemName=harg.iceberg)
- [vscode-icons](https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons)

## Python関連
- [Anaconda Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-python.anaconda-extension-pack)
- [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
- [code-python-isrot](https://marketplace.visualstudio.com/items?itemName=freakypie.code-python-isort)
- [cornflakes-linter](https://marketplace.visualstudio.com/items?itemName=kevinglasson.cornflakes-linter)

## コーディング全般
- [Bracket Pair Colorizer](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer)
- [Better Comments](https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments)
- [Code Runner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner)
- [Trailing Spaces](https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces)

## Debug
- [Output Colorizer](https://marketplace.visualstudio.com/items?itemName=IBM.output-colorizer)

## Git関連
- [gitignore](https://marketplace.visualstudio.com/items?itemName=codezombiech.gitignore)
- [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)

## Markdown関連
- [Markdown PDF](https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf)
- [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)

## ファイル操作
- [Duplicate action](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-duplicate)

## その他便利系
- [Resource Monitor](https://marketplace.visualstudio.com/items?itemName=mutantdino.resourcemonitor)
- [Partial Diff](https://marketplace.visualstudio.com/items?itemName=ryu1kn.partial-diff)
- [Path Autocomplete](https://marketplace.visualstudio.com/items?itemName=ionutvmi.path-autocomplete)
- [Rainbow CSV](https://marketplace.visualstudio.com/items?itemName=mechatroner.rainbow-csv)
- [Regex Previewer](https://marketplace.visualstudio.com/items?itemName=chrmarti.regex)
- [Settings Sync](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync)
- [YAML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)
BigQueryで週毎のユニークユーザーの推移を出すクエリ書くのに苦労したのでメモ

## 背景

BigQueryで週毎のユニークユーザーの推移を見たかった。これにめっちゃ苦労したのでメモ。
もっといいやりかたあるよってのがあれば教えていただけるとうれしいです。

### テーブル定義
こんなログインlogテーブルがあって、一度でもログインしたユーザーをユニークユーザーとして加算していく。

![スクリーンショット 2019-09-03 16.23.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20307/d17676dd-a0b1-a179-2aae-821f5cf590e2.png)

### 結論

まず、分析関数よくわからない方はこちら -> [分析関数（ウインドウ関数）をわかりやすく説明してみた](https://qiita.com/tlokweng/items/fc13dc30cc1aa28231c5)
めちゃくちゃわかりやすいですこの記事。

やり方としては、まずはユーザーの初回ログインの中間テーブルを作ってからユニークユーザーを計算する。
この中間テーブルをわざわざ作る理由としては、BigQueryでは 分析関数のOrder by + distinct を使うことがができないから。

[BigQuery Window ORDER BY is not allowed if DISTINCT is specified](https://stackoverflow.com/questions/42567564/bigquery-window-order-by-is-not-allowed-if-distinct-is-specified)
[BQ公式: 標準 SQL 関数と演算子#集計分析関数](https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators?hl=ja#aggregate-analytic-functions)

日埋めなしバージョン

```sql

# 初回ログインの中間テーブル
WITH user_with_first_login_date AS (
  SELECT
    company_id,
    shop_id,
    user_id,
    TIMESTAMP_TRUNC(MIN(timestamp), WEEK) AS login_date
  FROM
    `login_log`
  GROUP BY 1,2,3
)

## Window関数で週毎の累計UU数を集計
SELECT
  company_id,
  shop_id,
  login_date,
  SUM(COUNT(user_id)) OVER(PARTITION BY company_id, shop_id ORDER BY login_date) AS uu
FROM
  `user_with_first_login_date`
GROUP BY
  1,2,3
ORDER BY
  1,2,3

```

日埋めありバージョン

```sql
# 日埋め用のテーブル
WITH dates AS ( SELECT DISTINCT(TIMESTAMP_TRUNC(timestamp, WEEK)) AS login_date_c FROM `login_log`),
company_shop AS (SELECT company_id, shop_id FROM `login_log` GROUP BY 1, 2),
company_shop_dates AS ( SELECT * FROM dates, company_shop),

# 初回ログインのテーブル
  user_with_first_login_date AS (
  SELECT
    company_id,
    shop_id,
    user_id,
    TIMESTAMP_TRUNC(MIN(timestamp), WEEK) AS login_date_u
  FROM
    `login_log`
  GROUP BY
    1, 2, 3 ),

# 日埋めテーブルのJOIN    
  uu_count AS (
  SELECT
    c.company_id,
    c.shop_id,
    c.login_date_c,
    COUNT(user_id) AS uu
  FROM
    company_shop_dates AS c
  LEFT OUTER JOIN
    user_with_first_login_date AS u
  ON
    c.company_id = u.company_id
    AND c.shop_id = u.shop_id
    AND c.login_date_c = u.login_date_u
  GROUP BY
    1, 2, 3)

# 足し上げる    
SELECT
  company_id,
  shop_id,
  login_date_c AS login_date_u,
  SUM(uu) OVER(PARTITION BY company_id, shop_id ORDER BY login_date_c) AS uu
FROM
  `uu_count`
ORDER BY
  1, 2, 3
```
Python3.6.xとPillowでカラーモードを一括変換

# 複数画像のうち、カラーモードがCMYKの画像だけを別フォルダにコピーし、RGBに一括変換する

## 環境・使用アプリなど
- Mac
- Python3.6.8
- Visual Studio Code
- Pillow

## Visual Studio Code とPython機能拡張をインストール
- [Visual Studio Code Download](https://code.visualstudio.com/download)
- [Python extension for Visual Studio Code](https://marketplace.visualstudio.com/itemdetails?itemName=ms-python.python)


## Python3をインストール
anyenv、pyenvを使用してPythonのバージョン管理をする
参照：[anyenv、pyenvでPythonバージョン管理、仮想環境作成、仮想環境でIDLE起動（Mac）](https://qiita.com/yoko_u/items/ca4e77d1a25dd527f247)

今回はPython3.6.8を使用
Python3.7.3では、Pillowをインストールしても「PROBLEMS」に「Unable to import 'PIL'」と表示されて、実行できない。（まだPython3.7.xはPillowに対応していない？）
参考：https://teratail.com/questions/130649

# Visual Studio Codeのターミナルで仮想環境を作成し、有効化する

```
$ cd <仮想環境を作成するディレクトリのパス>
$ python -m venv <仮想環境名>
$ cd <仮想環境名>
$ source bin/activate
```

## Pillowをインストール

```
$ pip install Pillow
```

## Pythonスクリプトを作成

```cmyktorgb.py
import os
from PIL import Image
from PIL import ImageCms
# OS機能のモジュールのインポート
# 画像の読込み、作成などを行うためのImageモジュールのインポート
# カラープロファイルを管理するImageCmsモジュールのインポート

os.makedirs('cmyktorgb-icc', exist_ok=True)
# ディレクトリ'cmyktorgb-icc'を作成

# カレントディレクトリの全画像をループする
for filename in os.listdir('.'):
    if not (filename.endswith('.jpg') or filename.endswith('.jpeg')):
        continue
        #.jpg、.jpeg以外はスキップ

    im = Image.open(filename)
    # イメージを開く
    if im.mode == 'CMYK':
        im = ImageCms.profileToProfile(im, inputProfile, outputProfile, renderingIntent=0, outputMode='RGB')
        im.save(os.path.join('cmyktorgb-icc', filename))
```
指定するプロファイルのファイルパスは、Macの場合「ColorSyncユーティリティ」を使用して調べることができる
例）
- inputProfile（adobeのカラープロファイル）: '/Library/Application Support/Adobe/Color/Profiles/Recommended/USWebCoatedSWOP.icc'
- outputProfile（sRGB IEC61966-2.1）:'/System/Library/ColorSync/Profiles/sRGB Profile.icc'

## Pythonスクリプトの実行
VS Codeのcmyktorgb.pyを開いた画面で、右クリック（Ctrl+クリック）して表示されたメニューから「Run Python File in 
Terminal」を選択して実行する

## 仮想環境の無効化
```
$ deactivate
```



## 参考
- [Pillow](https://pillow.readthedocs.io/en/4.0.x/index.html)
- [ImageCms Module](https://pillow.readthedocs.io/en/4.2.x/reference/ImageCms.html#cmsprofile)
- [Conversion from CMYK to RGB with Pillow is different from that of Photoshop](https://stackoverflow.com/questions/38855022/conversion-from-cmyk-to-rgb-with-pillow-is-different-from-that-of-photoshop)