OmniAICreator/Qiita-1.07M huggingface dataset:
rails_admin + cancancanで「undefined method `new' for nil:NilClass」というエラーが出る

# 結論から

``config/initializers/rails_admin.rb``の設定を次の様に変更したら直りました。

```ruby:config/initializers/rails_admin.rb
RailsAdmin.config do |config|

  ...

  # 変更前
  config.authorize_with :cancan

  # 変更後：
  config.authorize_with :cancancan

  ...
 
end
```

# 環境

|項目|version|
|:-:|:-:|
|ruby|2.5.1|
|rails|5.2.3|
|rails_admin|2.0.0|
|cancancan|3.0.1|

# どうやってこの解法が分かったか

<img width="1275" alt="スクリーンショット 2019-11-14 午後9.42.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178570/ecf2a465-42f1-7a8d-bb4f-4ff58fcf4eec.png">

こんな感じでエラーが出たのですが、この中の

```ruby
klass = RailsAdmin::AUTHORIZATION_ADAPTERS[extension]
```

で``klass``がnilになってるのが原因でした。

extensionの値を調べると``cancan``が入っており、一方で``RailsAdmin::AUTHORIZATION_ADAPTERS``を調べると、``cancan``というキーはなく、``cancancan``というキーが入っているみたいでした。

そのため、``cancan``という設定に関係しそうな箇所を変更すれば直るかもしれないと思い試した所、解決しました。

# 所感

大抵の記事には

```ruby:config/initializers/rails_admin.rb
RailsAdmin.config do |config|

  ...

  config.authorize_with :cancan

  ...
 
end
```

という様に``cancan``と書いてあるので、引っ掛かりやすそうですね。
Javaにおける入力した5個の数字の内、最大値と最小値を求める

初投稿です。文章やコードに読みにくい部分や足りない部分があるかもしれませんが、温かい目で見ていただけると幸いです。
#まえがき
本日は Java において、「自分が入力した5個の数字の中から最大値と最小値を求める」というプログラムを作っていきたいと思います。説明の流れとしては実際に書いたコードの写真をお見せした後に具体的に言葉で説明していきたいと思います。ちなみに開発環境はEclipseを使っています。

#実際にプログラムを作る
##コードの記述
```Java
package max_min;
import java.util.*;

public class Max_Min{

   public static void main(String[] args){
      //TODO 自動生成されたメソッド・スタブ
      Scanner scanner=new Scanner(System.in);
      double max=0;
      double min=0;
      int i;
      double a;

      System.out.println("5個の数字の中から最大値と最小値を求めます。");
      
      for(i=1;i<6;i++){
         System.out.print(i+"つ目の数字:");
         a=scanner.nextDouble();

         if(a<=min){
             min=a;
         }else if(a>=max){
             max=a;
         }
      }
         System.out.println("最大値は"+max+"です。");
         System.out.println("最小値は"+min+"です。");
   }
}
```
これが実際に書いたコードになっています。具体的に説明していきますね。

まず、プロジェクト名は「Max_Min」、パッケージは「max_min」、クラスは「Max_Min」と名付けて作成しています。

そして実際に打ち込まれた数字を読み取るために、2行目に「 import java.util.*; 」を記述し、外部ライブラリの「Scanner」を使って入力された数字を読み取っています。

さらに、最大値と最小値を表す変数 max と min は 0 を初期値として設定しており、入力された数字の順番で1つずつ大小関係を調べ、現在の最小値より小さな数が入力されたならば変数 min に、現在の最大値より大きな数が入力されたならば変数 max に代入する操作を if 構文の中に記述しました。

##実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532357/dc388af3-a260-5f12-c409-4377db39afbb.png)

実行結果は上記のようになりました。
変数 max と min は double で定義しているので最後は小数の形で表記されます!
#まとめ
最大値と最小値を求めるプログラムは、一見簡単そうに見えますが実際作ってみると難しい部分があったりしました!
でも決して不可能ではなく、基礎が詰まっているようなコードでもあるので、是非初心者の方は実戦練習の第一歩だと思って取り組んでみるのもありかなと思いました!!
#あとがき
最後まで目を通してくださった方々、ありがとうございます!!!
始めにも書きましたが初投稿であったので読みにくい部分があったと思います。
もしこの記事の書き方やコードの書き方に関して反省点や改善点があればコメントを頂けると幸いです...!!

また、他にプログラムが作成出来次第記事を投稿しようと思いますので、そちらもよろしくお願いします!
ありがとうございました!!
MySQL で Python を書く

# Mysql Workbench Scripting Shell
みんな知っているMySQL Workbench
![mysqlworkbench.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176789/9435dcc3-08ea-f90a-5a1c-7f1af1ed84f4.png)

MySQL Workbench の Scripting -> Scripting Shell という項目からSQLの実行をPythonで制御できるエディタが開ける

<img width="834" alt="mysqlworkbench2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176789/e1b7ef0f-84bf-3ca5-37c5-a006bbcf63be.png">

エディタを新規に起動するとすでにテンプレートでPython スクリプトが記述されているが、この`import grt`という一行が重要で、これによって Mysql Workbench のエディタがPythonで制御できるようになっている。

例えば`grt.root.wb.sqlEditors[0].executeScript()`関数を使えばPython script 内の文字列をSQLとして実行できる
文字列にはstring formatが適用できるので変数を柔軟にSQLに組み込むことができる

# スクリプト例
例えばある表Aの上位100件に対して、表Aのcountyカラムに応じたレコードを表Bに挿入する処理などは次のように書ける

```py
import grt
#import mforms
query_select = "select * from table_A limit {};"
query_insert = "insert into table_B (country) {};"
result = grt.root.wb.sqlEditors[0].executeScript(query_select.format(100))

n = result[0].rowCount -1
for i in range(0, n):
    country = result[0].stringFieldValueByName("country")
    editor.executeScript(query_insert.format(country+"_duplicated"))
    result[0].nextRow()
```

SQLマスターにならないと書けないような処理でもPythonで書けば簡単に書けることが結構あります
一番のボトルネックは自分がコードを書く時間という格言もありますので、積極的にMySQLでPythonを使っていきましょう
【Docker】Rspecテスト用データベースの仮想環境構築

## 概要
以前作成したアプリでDocker開発環境の構築をしました。
今回の内容は前回記事の発展系なので、下記もご覧ください。
[前回記事](https://qiita.com/AK4747471/items/39ddacfde6a235103277)
それまではテストコードが問題なく通ってはいたんですが、新しいテーブルを追加したところテスト用データベースでエラーが・・・。

どうやら開発環境用データベースはDocker内部に、テスト用データベースをDockerの外側に構築していたので、開発環境で追加したテーブルをデータベースに反映できなかった模様。

意外と詰まったので、備忘録的にまとめようかなと思っています。

## バージョン
・Ruby（2.5.1）
・Ruby on Rails（5.2.3）
・MySQL（5.6）
・Docker(19.03.4)
・docker-compose(1.24.1)

## 結論
実はごくごく簡単でした。
docker-compose.ymlでtest-dbというコンテナを追加するだけです。
ただその時に、データベース名、パスワード、ユーザー名など必要になってきます。

docker-compose.ymlで設定したデータベース名などを、database.ymlに反映するだけ、という感じですね

ちなみに、テスト用データベースもSequelProで確認したかったので、開発環境データベースのポートとは違うポートを解放してます。

```yml:docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.6
    environment:
      MYSQL_DATABASE: docker_development
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: root
      MYSQL_PASSWORD: password
    volumes:
      - ./mysql/mysql_data:/var/lib/mysql # データの永続化
    ports:
      - "4306:3306" # ホストからゲストへポートフォワード。sequelProと繋ぎたいので、3306ではなく4306をポートに指定
    
  # Docker内部でテスト用のデータベースが必要になるので記述
  test-db:
    image: mysql:5.6
    environment:
      MYSQL_DATABASE: docker_test
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: test_root
      MYSQL_PASSWORD: password
    ports:
      - "4307:3306" # ホストからゲストへポートフォワード。sequelProと繋ぎたいので、3306ではなく4307をポートに指定 

  web:
    build:
      context: .
      dockerfile: Dockerfile
    # 一度サーバーが起動すると起動し続けるので、rm -f /workdir/tmp/pids/server.pidで、dockerが起動する度に一旦停止させる
    command: /bin/sh -c "rm -f /workdir/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    depends_on:
      - db # DB側のコンテナが出来上がってからwebを実行する
    ports:
      - "3000:3000" # ホストからゲストへポートフォワード
    volumes:
      - .:/workdir # ソースコード変更したらDocker側も即反映されるように
```

```yml:database.yml
(省略)
test:
  <<: *default
  database: my_new_gear_test
  username: test_root
  password: password
  database: docker_test
  host: test-db
(省略)
```

これでdocker内部に入ってRspecのテストを実行しても、問題なく通るはずです！
初心者によるプログラミング学習ログ 160日目

# 100日チャレンジの160日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

160日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>160日目<br><br>Udemyでwebサイトコーディング<br><br>んで、寝落ち。<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><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <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%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1194707921608724483?ref_src=twsrc%5Etfw">November 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
使用エディタの変遷

Adobe Dreamweaver → HTML Project2 → Sublime Text → 現在はAdobe Brackets
AtomまたはVisual Studio Code に乗り換えるか悩み中。
TeraPad、Notepad++を併用。

#Adobe Dreamweaver
説明不要。テーブルレイアウト時代は大変お世話になりました。
テキストエディタとしては正直動作が重いけどWeb開発環境としては優れているので、大量のファイルを一括更新したいときなどは今でも使用している。

#HTML Project2
動作が軽い上にキーボードショートカットを任意かつ簡単に設定できるという素晴らしいエディタ。
Windows 10に移行したタイミングで動作が安定しなくなったため、泣く泣く Sublime Text に移行。
http://kaneto.o.oo7.jp/hproj2/htmlproject2.html

#Sublime Text
ちょうど「恋に落ちるエディタ」が話題になったタイミングで移行。Zen-Coding(現Emmet)もこのタイミングで導入。
日本語対応がいろいろ面倒だった……
http://www.sublimetext.com/

#Adobe Brackets
使用中。
大量のファイルを含むプロジェクトを開くとフリーズする仕様はなんとかしてほしい。

#TeraPad
超軽量かつ優秀な定番エディタ。普通のテキストを書くときはこちらを使用していた。今でもたまに使用している。
https://tera-net.com/

#Notepad++
普通のテキストを書くときにもマルチカーソルを使いたくてTeraPadから移行。コーディング以外ではこちらを使用。
https://notepad-plus-plus.org/
Adobe Bracketsで使用している拡張機能

Adobe Bracketsで使用している拡張機能の備忘録。

2020-03-06 PHPランタイムエラー対応を追加

#テーマ「Quick Dark」
テーマスクロールバーを使用：✔
フォントサイズ：15px
フォントファミリー：'Source Han Code jp', '源ノ角ゴシック Code JP', 'ＭＳ ゴシック', 'MS Gothic', sans-serif

#Emmet
HTML/CSSの入力補完機能。旧Zen-Coding。
これがないともうコーディングできない。
※逆Emmetなる拡張もある。余裕があれば試す

デフォルトのショートカットを変更する
デバッグ→ユーザーキーマップを開く
    "overrides": {
		"Tab": null,
		"Ctrl-E": "io.emmet.expand_abbreviation_with_tab",
        "Ctrl-Q": "navigate.toggleQuickEdit"
    }

#全角空白・スペース・タブ表示
全角空白・半角空白・スペース・タブを制御文字で表示できる。
なぜデフォルトで表示できないのか……。

#Brackets Tree Icons
ファイル一覧に大きめのアイコンを表示できる。地味に便利。

#brackets-file-tree-exclude
プロジェクトを開くときに、指定したファイルやディレクトリを除外することができる。
大量のファイルを含むプロジェクトを開くとフリーズするので、対策として必須。

#Color Highlighter
カラーコードで指定している色をハイライトで表示できる。とても便利。

#colorHints
一度使用した色指定をコードヒントとして表示できる。

#Select Lines
行番号をクリックして行選択ができるようになる。

#Brackets Tools
- 空白行の削除
- 改行の削除
- 行頭の連番を削除
- 重複行の削除
- 単語リストを配列に変換

などの機能を追加できる。
https://qiita.com/assialiholic/items/7ee66c7097abae3c32ad

#Beautify
コードを自動整形してくれる。

#brackets-compare
分割画面で表示した2つのファイルの内容を比較できる。

#Brackets Key Remapper
Bracketsのショートカットをカスタマイズできる。

#Display Shortcuts
ショートカットキー一覧を簡単に表示・検索できる。

#Brackets CSS Class Code hint (Root Path OK)
ID名・class名をコードヒントで表示できる。

#Brackets Sass Hints
変数やmixinの名前等、SASS特有のコードのヒントを表示できる。

#JSONLint Extension for Brackets
JSONファイルのエラーをチェックする。

#PHP SmartHints
PHPのコードヒントを表示する。

#W3C Validation (by Umoxfo)
Brackets上でHTMLの文法をチェックできる。

#More HTML5 Code Hints
HTML5のコードヒントを拡張。picture要素やsrcset属性までサジェストできるようになる。

#~~Indent Guides~~
インデントのガイド線を表示。
→「全角空白・スペース・タブ表示」と重複しているので無効に

#~~Paste and Indent~~
コピペしたコードのインデントをリアルタイムで修正してくれる
→HTMLではインデントを使っていないので無効に

#設定の変更
ファイル＞試験ライブプレビューを有効にする　✔

#PHPランタイムエラーに対処
そういえばバージョンアップしたらこんなエラーが出るようになったんだった……

PHPの公式サイトから最新版(2020/3/6時点では7.4.3)をダウンロード
https://windows.php.net/download#php-7.4
「VC15 x64 Thread Safe」→「Zip」をダウンロード

→ダウンロードしたファイルをCドライブ直下に追加

→Bracketsの環境設定からPathを通す

```brackets.json
"php": {
 "executablePath": "C:/PHP_3.7.4/php.exe"
}
```

参考：Brackets 1.14での PHPランタイムエラーの対処法
https://ichioshi.news/2019/06/02/brackets1-14/
[漏洞预警]利用Padding Oracle攻击Apache Shiro远程代码执行

### 漏洞描述
2019年9月8日,Apache官方发布了编号为SHIRO-721的漏洞通告.该漏洞是利用`Padding Oracle Attack`攻击Shiro应用.该攻击方式不再需要以往方式中的key.攻击者可使用合法的`RememberMe cookie`作为Padding Oracle攻击前缀,构造`RememberMe`字段的值触发Java反序列化攻击.
### Apache编号
SHIRO-710
### 漏洞威胁等级
高危
### 影响版本
1.2.5
1.2.6
1.3.0
1.3.1
1.3.2
1.4.0-RC2
1.4.0
1.4.1
### 漏洞验证
攻击者利用`Padding Oracle Attack`构造出`RememberMe`字段后段的值结合合法的`RememberMe cookie`即可完成攻击

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/b4368a75-50e4-4db6-c645-d0a4b54c8636.png)
### 修复建议
升级至1.4.2-release-vote1
### Reference
https://issues.apache.org/jira/browse/SHIRO-710
配列をインスタンス変数として動的に利用したい

##作業環境
Windows 10 
PyCharm

## コード

```
class ClassPosition():
    def __init__(self, xx, yy, rr):
        self.x = xx
        self.y = yy
        self.r = rr

class ClassTest():
    def __init__(self):
        self.arr = []

test = ClassTest()
for i in [0,1,2,3]:
    test.arr.append(ClassPosition(i, i + 1 , i + 2))
    print(test.arr[i].x, test.arr[i].y, test.arr[i].r)
```


## 実行結果

```
0 1 2
1 2 3
2 3 4
3 4 5
```

##あとがき
　pandasのdataframeで取得したデータを整理して利用する場合に、このように配列をインスタンス変数として動的に利用できたらと思ったらこうなりました。
　他に書いているサイトが見つからなかったので、意味はあると思います。

## おまけ↓
pythonで配列を動的に利用したい場合

## コード

```
p = []
for i in range(4):
    p.append(i)
    print(p[i])
```

## 実行結果

```
0
1
2
3
```
CloudFunction周りTIPS

備忘用メモ

# 定期実行
下記のような形式でコードベースでスケジュール登録まで可能。
https://firebase.google.com/docs/functions/schedule-functions?hl=ja

``` javascript
functions.pubsub.schedule('every 1 hours').onRun((context) =>{
});
```
内部的にはGCP側のスケジューラに自動で展開している。
こちらから登録したスケジュールをGCP側で弄ることも可能らしいが、
動作保証対象外とのこと。

# 割り当てメモリ/タイムアウトの延長

``` javascript
functions.runwith({
  timeoutSeconds: 120,
  memory: '1GB' as const
})
```
RunWithに必要な値を渡して呼べば可能。
デフォルトの256MBだと単純な計算はまだしもpuppeteerを起こしたりとかし始めると足りないので変更は必須

# 変数の登録
FirebaseのCLIから以下のように登録が可能

```
firebase functions:config:set hoge.fuga=hogepiyo
```
読み取り側は以下のように行けます。

``` javascript
functions.config().hoge.fuga
```

ちなみに、反映にはdeployが必要
AI（artificial intelligence）：人工知能

### AI（artificial intelligence）：人工知能
「『計算』という概念と『コンピュータ』という道具を用いて『知能』を研究する計算機科学の一分野」を指す語

**■ 製作について**
プログラミング言語はC++のほかPythonが広く使われている。 
深層学習（ディープラーニング）を利用するには微分、線形代数、確率・統計といった大学レベル以上の数学知識が必要となる。
脳シミュレーションを行うには脳神経科学の知識も重要となる。
また、最適解を導くアルゴリズムも考えなければならない。
<br>

**■ 今後のAI普及について**
現状そこまで普及しているか身近で感じることは少ないが、、
2020年に携帯電話の5G（第五世代）ネットワークがサービス開始される計画があり、ともにAI革命が起きるといわれている。
　⇒　[なぜAI革命は2020年に突然起きるのか](https://www.bizcompass.jp/original/re-trend-161-2.html)


#### ■ 年齢別年収比較
**システムエンジニア年齢別平均年収**

|      年齢|       年収 |    月額給与 |
|---------:|----------:|------------:|
| 20～24歳 |  313.5万円 |    19.6万円 |
| 25～29歳 |  390.5万円 |    24.4万円 |
| 30～34歳 |  429.0万円 |    26.8万円 |
| 35～39歳 |  489.5万円 |    30.6万円 |


**AIエンジニアの年齢別年収**

|      年齢|                  年収 |    月額給与 |
|---------:|---------------------:|------------:|
| 20～24歳 |             570.0万円 |    35.6万円 |
| 25～29歳 |  660.0万円～710.0万円 |    44.4万円 |
| 30～34歳 |  680.0万円～780.0万円 |    48.8万円 |
| 35～39歳 |  786.0万円～890.0万円 |    55.6万円 |

AIエンジニアってそれなりの知識、技術は必要ですがその分、収入が良いことがわかります。


###■ AI導入事例
**画像認識**
・コンクリートの劣化を画像にて判別する
⇒　[河川のコンクリート護岸劣化検知](https://ai.brainpad.co.jp/case-study/53/)

・商品利用実態を解析
⇒　[SNS投稿画像による商品利用実態の解析](https://ai.brainpad.co.jp/case-study/156/)

**データ分析**
・ゲームの検証作業を自動化
⇒　[深層強化学習によるゲーム攻略AIの開発支援](https://ai.brainpad.co.jp/case-study/2631/)

・リアルタイム分析
⇒　[バレーボールのリアルタイム分析への機械学習の活用](https://ai.brainpad.co.jp/case-study/143/)

#### スポーツにおけるAI導入
- 野球
    - 某有名野球チームは、親会社がIT企業ということもありAIにかなり力を入れた練習、戦略を行っているらしい。球場に設置したカメラで投手、野手、打者の投球、打球、走塁のプレーを、次々データ化し投手専用のアプリの作成などを行っている。<br>
- ゴルフ
    - 対象となる人の体にセンサーをつけて、その動きをコンピュータで解析する技術が開発されている。その結果、見本となるフォームと比較し指摘をしてくれる。
- 体操
    - 選手の体の動きを3Dでとらえ、それをAIに学習させた正しい動きと比較して技の完成度を測る。


　その結果、こんな名言まで生まれています。
　　**「AIは名監督であり名コーチだ」**
<br>

#####★☆おまけ☆★
スーパーマリオを最短でクリアするっていう企画があります。

動的な障害物に対しても最善な回避動作を瞬時に判断するアルゴリズムであったり、速度とジャンプ角度の計算が求められる。
⇒[スーパーマリオのジャンプのアルゴリズム](https://qiita.com/morian-bisco/items/4c659d9f940c7e3a2099)


海外ではスーパーマリオを人工知能で攻略し、秒速クリアに挑戦するみたいなこともやっています。
⇒[スーパーマリオを人工知能で攻略](https://withnews.jp/article/f0150711000qq000000000000000W0230901qq000012241A)
Thunderbirdが起動しなくなった際の復旧メモ

Thunderbirdは終了時のタブ構成が、次回起動時に復旧されます。
検索フォルダが問題のある状態で開かれてしまったようで、画面を切り替えようならフリーズする。閉じようにも異常終了してしまうので閉じれない、というループに陥っていました。

この問題に対しては、Profile内の`session.json`を初期化する、という方法で脱出できました。
`session.json`はその名の通り、開いているタブなどの状態が記録されているようです。

# 環境

- Thunderbird 60.9.1 64bit
- Thunderbird Portable 60.9.0 32bit

- Windows 10 Enterprise (DaaS仮想端末)
- Windows 10 Pro (TB Portable 起動端末)

社用端末の環境ですが、雁字搦めのDaaS仮想環境なので特殊な構成にしてあります(既定はOutlookとかいう産廃)。

- Thunderbird
    - 管理者権限が無い為、%APPDATA%\programs\内に配置
    - Profileはパーミッション付与がおかしい為に不具合を起こすので、ここには置かず、共有フォルダを見に行く
- Thunderbird Portable
    - トラブルシュート用
    - 容量問題とパーミッションがおかしい問題から逃れるために、SMB共有フォルダ上にProfileを配置
    - 度々問題を起こすので、共有フォルダに直接アクセスしてトラブルシュートするために、Thunderbird Portable内のProfileに配置
[Windows10] ファイルが保存できないのは Windows Defender の設定かも

# ファイルの保存ができないぃぃぃぃぃ
何らかのファイルを編集して保存しようとしたら「ファイルが見つかりません。ファイル名を確認して再実行してください。」と怒られた。

# Windows Defender の設定を確認
そんなときは、「Windows Defender」の設定を確認してみてください。
スタートメニュー　＞　設定　＞　Windowsセキュリティ　＞　ウイルスと脅威の防止　＞　ランサムウェア防止の管理

ここにある「コントロールされたフォルダーアクセス」という項目が「オン」になっていたら、それが犯人です。

![defender.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376864/7812260d-c4c2-7a2e-2e67-c1cbe9729ea9.png)

ある日突然ファイルの保存ができなくなったので調べてみて、ここの設定を変えたら保存できるようになりました。
ただ、この設定は標準では「オフ」のはずで、自分で「オン」にしない限りは発動しないので、なぜ「オン」になってしまったのかは不明ですが、みなさんも保存できなくなったらここを確認してみると良いかもしれません。

なお、この機能の本来の目的は機能の名前の通り「ランサムウェア防止」で、確かにこの機能で不正な書き込みを防止することができます。ただ、いかなるファイル保存もNGとなると、ちょっと不便ですね。

「オン」の状態で、書き込みを許可するアプリケーションを設定することもできますので、セキュリティ対策の度合いを考えて設定いただければと思います。
Visual Studio Code + Markdown Preview Enhancedでタイミング図を描く

初Qiita。使い方がよく分からない。

Visual Studio CodeでMarkdown Preview Enhanced(MPE)拡張を使うためのメモ。
いつも使おうと思うと使えなくなっているので備忘のため記録。
環境はWindows7 64bit / Windows10 64bit (どちらも同じ現象だった)


Visual Studio Codeは普通にインストール
https://code.visualstudio.com/download

Extensionsで拡張機能をインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/765d4cc5-53f3-58c7-39e5-8ff7a5d911f6.png)


"Markdown Preview Enhanced"を検索して"Install" (偽者に注意)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/da496bd6-bdb6-0aed-c8ab-70700ef18e54.png)


試す。

ファイルを新規作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/ab376b55-f331-afc5-fa8b-da0ad9977323.png)

WaveDrom (https://wavedrom.com) という書式に従って信号を記述
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/b74c3c98-b3d3-0db3-55be-ba0ee87236f9.png)

Command Paletteを開いて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/f8403695-3d48-9e04-4518-8dcdf94f7d82.png)

MPE Open Previewコマンドを叩こうとすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/524e6f62-0381-91e9-322b-fe3707ace94b.png)

エラーが出て使えない！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/168b0efe-3ec6-db84-c034-c70d7dc498a5.png)

しかしここでMPE Open Preview to the sideを叩くと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/a08e67bf-89fe-cafb-2446-a2da2902a9f8.png)

なぜか使える。そしてこの後はMPEの他のコマンドも正常に使えるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/2127d9c8-bb41-49c9-9140-2969d0eee2c9.png)


Visual Studio CodeのバグなのかMPEのバグなのか
そもそも私が使い方を分かっていないだけなのか分からないが、
とにかくこのような手順を行うと使えるようになる。

タイミングチャートを描くこと自体がそれほどないので、
たまに描こうと思って起動すると使えなくて時間を浪費する。
というのを3回繰り返したのでいいかげん記録に残しておく。

(でもライブプレビューが動いてないのでやっぱり何か決定的に使い方を間違えてる気がする…。)

Tip:
If you come across the error "command 'markdown-preview-enhanced.openPreview' not found",
then try the command "markdown-preview-enhanced.openPreviewToTheSide".


※QiitaもVSCodeも導入したばかりなので手探り。
何か気付いたら後で追記します。
ローカル開発環境構築②

##今回の内容
1. 仮想マシン設定
2. Cybereduckの設定
3. PHPの設定
4. 終了の仕方
5. 学習の再開
6. Transmit の使い方 ※cyberduckじゃないFTP 
7. hostsファイルを編集する


##仮想マシン設定
前回設定した、仮想環境にて、vargentのプラグインのインストール、OSを最新にする。
そして、gitをインストールして、スクリプトをダウンロードする。
基本的に、ターミナルへコピペで完了する。※少し、DLに時間がかかる。

```
サーバーへログイン。 ※改装の移動必要。
vagrant 

# OSを最新状態にアップデート（時間かかります）
sudo yum -y update

# スクリプトを入手するためのgitをインストール
sudo yum -y install git

# gitを使ってアプリケーション設定用のスクリプトをダウンロード
git clone https://github.com/dotinstallres/centos6.git

# centos6フォルダができるのでそちらに移動
cd centos6

# スクリプトを実行（時間かかります）
./run.sh

# もろもろの設定を反映
exec $SHELL -l
```

##Cyberduckの設定
- 環境設定で、エディタをデフォルトに設定。
    - atomに設定。
- プロトコル：SFTP
- サーバ：192.168.33.10
- ユーザー名：vagrant 
- パス: vagrant 
- ブックマークの設定： myCentOS_dotinstal

##PHPの設定
- cyberduck のフォルダの中に、新規フォルダ php_lessons を作成
- その中に、index.phpを作成、エディタで開く。atom. コマンドKでエディタ開く。

```index.php
<?php

echo "hello world";
```

- ターミナル上で、php_lessonsディレクトリに移動。
> php -S 192.168.33.10:8000
- webで見れるようになる。
    - http://192.168.33.10:8000 にアクセス。
    - 確認。ok


##終了の仕方 ※PHP のWEBサーバが立ち上がっている場合
- ターミナル上で、ctrl+c 
- exit ※仮想マシンのログアウト
- vagrant suspent ※仮想マシンの停止
- exit ※ターミナルの終了

##学習の再開 
**仮想マシンの起動**
- cd 
- cd MyVagrant
- cd MyCentOS
- vagrant up ※仮想マシンの起動
- vagrant ssh ※仮想マシンにログイン

**cyber duck の起動**
- ブックマークにてログイン
- home / vagrant / に新規フォルダを作成。 
    - 今回は、ruby_lessonsを作成。
- 新規ファイルを追加。hello.rb
    - コマンドKでエディタ起動。

```hello.rb
puts "hello"
```

### ターミナル終了
- ブラウザで実行確認するために、ターミナル上で
- 階層移動。 cd ruby_lessons
- ruby hello.rb

###trasmitの使いかた
基本的に、cyberduckを使うので、省略。
一応、ドットインストールのURL
https://dotinstall.com/lessons/basic_localdev_mac_v2/38513

##hostファイルの編集
- 開発環境にて、192.168.33.10に任意の名前をつけることができる。らしい。
- 現状、特に使う必要性がないので、今は省略。
- etc/hosts の中に 192.168.33.10 xxx.com などとつければ、xxx.com:8000とブラウザに入力すればアクセスできる。
- 主に、ローカル開発環境下のPC上のみで可能。

 

#今回の学び
- ローカル開発環境はよく使うので、やり方は何度もつかうことでなれなければいけないと感じた。
- すぐに忘れてしまう。
- やっと、rubyの方に勉強が進められる。
Laravel のマイグレーションで created_atとupdated_atのデフォルトを設定する

多少考えたので、メモとして残しておきます
5.2以降対応のはずです

下記のようなマイグレーションがあるとします。

```php

 public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 100)->index()->comment('名前');
            $table->timestamps();
            $table->softDeletes();
        });
    }

```

`timestamps()`は
>NULL値可能なcreated_atとupdated_atカラム追加

と二つのカラムを生成します。

実装を見ると、まんま呼び出しているだけです

```php:vendor\laravel\framework\src\Illuminate\Database\Schema\Blueprint.php

/**
     * Add nullable creation and update timestamps to the table.
     *
     * @param  int  $precision
     * @return void
     */
    public function timestamps($precision = 0)
    {
        $this->timestamp('created_at', $precision)->nullable();

        $this->timestamp('updated_at', $precision)->nullable();
    }


```


'timestamp'に現在時刻をデフォルトを設定する
`useCurrent()`があります。

上記の通り`void`なので、繋げられません。
`Call to a member function useCurrent() on
null`とエラーが出ます。

なので、下記のように二つに分けて設定しましょう

```php

 public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 100)->index()->comment('名前');
            $table->timestamp('updated_at')->useCurrent()->nullable();
            $table->timestamp('created_at')->useCurrent()->nullable();
            $table->softDeletes();
        });
    }

```
Rustでuseを使ってパターンマッチング時にバリアントごとにEnum名を入力しなくてもいいように楽をしようとすると罠にはまる話

こんにちは、megumishです。
今日はRustを書いてるときにはまりがちな一つの罠を紹介したいと思います。

# 0. 実証環境
Rust: 1.39.0 Stable (2019/11/14時点)

# 1. Enumの普通のパターンマッチ
まず普通にパターンマッチするとき、次のように書くかと思います。

```rust:main.rs
fn main() {
    message(UserKind::Normal);
    message(UserKind::Guest);
    message(UserKind::Special)
}

fn message(user_kind: UserKind) {
    match user_kind {
        UserKind::Normal => println!("普通"),
        UserKind::Guest => println!("ゲスト"),
        UserKind::Special => println!("特別"),
    }
}

enum UserKind {
    Normal,
    Guest,
    Special,
}
```

# 2. useを使った楽をしたパターンマッチングの書き方

しかし、さきほどのように書くとパターンマッチングの際にいちいちバリアントごとに `UserKind::` とつけなくてはなりません。

このようにしたくないとき、以下のようにuseを使って省略して書く時があります。

```rust:main.rs
fn main() {
    message(UserKind::Normal);
    message(UserKind::Guest);
    message(UserKind::Special)
}

fn message(user_kind: UserKind) {
    use UserKind::*;
    
    match user_kind {
        Normal => println!("普通"),
        Guest => println!("ゲスト"),
        Special => println!("特別"),
    }
}

enum UserKind {
    Normal,
    Guest,
    Special,
}
```

このように書くと、 `UserKind::` といちいち書く必要がなくなり楽です。よさげですね！！！

# 3. useを使った楽をしたときの罠

さて、次に以下のようにタイポをしてしまったときのケースを考えます。

```rust:main.rs
fn main() {
    message(UserKind::Normal);
    message(UserKind::Guest);
    message(UserKind::Special)
}

fn message(user_kind: UserKind) {
    use UserKind::*;
    
    match user_kind {
        Normal => println!("普通"),
        // タイポだ！！！
        Gest => println!("ゲスト"),
        Special => println!("特別"),
    }
}

enum UserKind {
    Normal,
    Guest,
    Special,
}
```

このとき、バリアント名が間違っているためコンパイルは通ってほしくないと考えると思います。
けれども、このコードのコンパイルは通り無慈悲にも以下のような想定しないであろう出力をしてしまいます。

```
普通
ゲスト
ゲスト
```

# 4. パターンマッチと任意の値の束縛

通常、パターンマッチ時に任意の値を入れたいときに次のような記述をするかと思います。

```rust
match user_kind {
    Normal => println!("普通"),
    x => println!("普通ではない"),
}
```

なぜ突然こんな話をしたいかというとこれにさっきの罠が起こったヒントがあるからです。

# 5. なぜ意図しない結果となってしまったかの理由

さきほどの意図しない結果がでてしまったときのパターンマッチ部分をもう一度見てみましょう。

```rust:main.rs
...
    match user_kind {
        Normal => println!("普通"),
        // タイポだ！！！
        Gest => println!("ゲスト"),
        Special => println!("特別"),
    }
...
```

ここで前項での説明が役に立ちます。このとき、`Gest`という名前はどのバリアントにも当てはまらないため`Gest`という名前に値が束縛されてしまっているのです。

試しに `Gest` を `Hoge` などの適当な値に置き換えてみても同じ結果になるかと思います。

# 6. 結論：罠を踏まないために

`use` による楽をしないというのがまず一つの解決策なのですが、
それ以外にも使っていない束縛があるよという警告をRustのコンパイラーが出してくれるはずなのでそちらも参照すると良いかもしれません。

以上がRustのちょっとした罠の話でした。ありがとうございました。
意外と知らないbundlerの小技

## bundle installされたGemのディレクトリをエディタで開く

```shell
$ bundle open <gem>

# example
$ bundle open rspec
→ vendor/bundle/ruby/2.6.0/gems/rspec-3.8.0が開く
```

## 不要なGemの削除

```shell
$ bundle clean
```

以下のように、`bundle install`されたもののうち不要なGem（古いバージョンを含む）が削除される。

```
$ bundle clean
Removing graphql (1.8.13)
```

## bundle install（2回目以降）

はじめに`bundle install --path vendor/bundle`した後は、`.bundle/config`にPATH情報が保存されて、以降は`bundle`で`bundle install`される。

```shell
$ bundle
```

```ruby:.bundle/config
---
BUNDLE_PATH: "vendor/bundle"
```
python インスタンス変数でDictionaryとかListとかのサンプル

## python クラス内のインスタンス変数で配列とかDictionaryを宣言するサンプル

##作業環境
Windows 10 
PyCharm

## コード
急いでいるのでコードのみメモ。

```
class ClassTest():
    def __init__(self):
        self.t: Dict = {'東京':900, '横浜':300, '大阪':250, '名古屋':200, '福岡':150}
        self.u = dict(a=1, b=2, c=3)
        self.v: List[int] = [["はい", 50, 100], ["いいえ", 100, 100]]

    def __del__(self):
        pass   # デストラクタ

test = ClassTest()
print(test.t['東京'])
print(test.u['a'])
print(test.v[0][0])
```


## 実行結果

```
900
1
はい
```

##あとがき
　自分用のメモです。
ヒストグラム・散布図をJupyter Notebook上で表示する

Matplotlibを使ってJupyter Notebook上でヒストグラムや散布図を表示させる方法です。

この記事の内容は、以下の記事に従って準備したJupyter Notebookの環境で試しています。
[Jupyter NotebookをDockerを使って簡単にインストールし起動（nbextensions、Scalaにも対応） - Qiita](https://qiita.com/suzuki-navi/items/37615024d4748aac6688)

この環境でブラウザで8888番ポートにアクセスして、Jupyter Notebookを使うことができます。右上のボタンのNew > Python3をたどると新しいノートを開けます。

また、この記事では適当なランダムで作成したCSVファイル
https://github.com/suzuki-navi/sample-data/blob/master/sample-data-1.csv
を使っています。

# データ準備

各種importとデータを読み込みます。

```
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("sample-data-1.csv", names=["id", "target", "data1", "data2", "data3"])
```

`df`はDataFrameのオブジェクトになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/38a06947-00af-b548-dae4-eb0aac594747.png)

CSVからの読み込みとDataFrameの扱いについては前回の記事参照。
[DataFrameに対する基本操作を試す - Qiita](https://qiita.com/suzuki-navi/items/6bd8377ca7974779a822)

# ヒストグラム

Matplotlib documentation
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html#matplotlib.pyplot.hist

```
plt.hist(df["data1"])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/8012cf59-f95a-44d1-2750-b871b8fc2f03.png)

`bins`というオプションで横軸の分割する数を指定できます。

```
plt.hist(df["data1"], bins=30)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/bf7a0556-bdf8-7b16-bc45-c7de65489922.png)

`range`で横軸の範囲を指定できます。

```
plt.hist(df["data1"], range=(-100, 100))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/0f3d6104-0c14-5a71-a6b6-7d4cdfb81b1c.png)

`density=True`を指定すると、縦軸の合計が1.0になるように正規化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/df4ef11c-94f1-bd96-57a9-d049ba2513ae.png)

# 散布図

Matplotlib documentation
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.scatter.html#matplotlib.pyplot.scatter

```
plt.scatter(df["data1"], df["data2"])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/d0a478e6-3764-650b-92d9-5d3a423b67a1.png)

`c`に整数の列を指定すると、その値ごとに色分けしてくれるようです。

```
plt.scatter(df["data1"], df["data2"], c = df["target"])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/e9ed2f33-d70e-974c-541b-199a739fe974.png)

点がたくさんある場合は`alpha`を指定するとよさそうです。`0.0`で透明、`1.0`が不透明で、その中間を指定すれば濃淡がわかります。

```
plt.scatter(df["data1"], df["data2"], c = df["target"], alpha=0.5)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/225014b7-3364-96c2-a0b6-c2f724242ec7.png)

`xlim`, `ylim`というメソッドで横軸の範囲を指定できるようです。

```
plt.xlim(-50, 50)
plt.ylim(-5, 5)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/3217c3a1-626e-f322-846d-95a20469008f.png)

以上。
gsubとgsub!(Ruby)

gsubメソッドを使用してみました。
置換をしてくれるメソッドです。

```
string1 = "seven"
puts string2 = string1.gsub(/seven/, 'eleven') # => eleven
puts string1 # => seven
puts string2 # => eleven
```
次にgsub!としてみた場合レシーバを置換したものに完全に置き換えました。

```
string1 = "seven"
puts string2 = string1.gsub!(/seven/, 'eleven') # => eleven
puts string1 # => eleven
puts string2 # => eleven
```
次に置換に対応する文字列がなかった場合です。
置き換えるものがないとレシーバに変化は無いです。

```
string1 = "seven"
puts string2 = string1.gsub(/a/, 'eleven') # => seven
puts string1 # => seven
puts string2 # => seven
```
置換に対応する文字列がなく！を使った場合です。
返り値はnilになります。

```
string1 = "seven"
puts string2 = string1.gsub!(/a/, 'eleven') # => nil
puts string1 # => seven
puts string2 # => nil
```
レシーバと返り値の関係を意識できるように記述しました。
高階関数を活用してネストされたオブジェクトを安全にCRUDする

社内での質問がきっかけで高階関数でなんとかなりそうと思いサクッと作ってみたのでメモ。
オブジェクトがない場合は空オブジェクトを自動で作成するようになっているので最近話題のOptional Chainingとはちょっと違います。  

\# タイトルの「安全に」はオブジェクトなくても子や孫のツリーを実現できる意図でつけました、nullやnumberなどに対してオブジェクトを追加しようとするとエラーになります

\# コメントで0や''といったfalsyが値としてセットできない指摘がありましたのでnullも入るように修正しました、ありがとうございます

```javascript
/**
 * Create, Read, Update, Delete
 */
function crud(obj, key, value) {
  let result = obj[key];
  if ((typeof result) === 'undefined') { // 値がまだなければ空オブジェクトで初期化
    result = obj[key] = {};
  }
  if ((typeof value) !== 'undefined') { // value指定ありの場合は値を書き換える
    result = obj[key] = value;
  }
  // key指定なしの場合はチェーンで呼べる無名関数ではなく値そのものを返す(Read用途)
  return (key, value) => (typeof key) !== 'undefined' ? crud(result, key, value) : result;
}

var obj = {};
// [Create + Update] obj.a.b.c = 123;
crud(obj, 'a')('b')('c', 123);

// [Read] obj.a.b.c;
console.log(
  crud(obj, 'a')('b')('c')()
); // 123

// [Delete] obj.a = null;
crud(obj, 'a', null);

// aを確実に空にしつつ配列としてセット
crud(obj, 'a', {})('y', [])(0, 'first'); // { a: { y: ['first'] } } 
```

高階関数面白い。
[jinja2] .j2テンプレートファイルのifはスペースを空けないとエラーになる

rundeck用のymlファイルを書いていて、通知のところだけ環境ごとに分けたいなーって思ってこんな感じに設定しました。

`{{ rundeck.jobs.is_notification }}` に、本番環境ならtrueが、その他ならfalseが返ってきて通知の分を出し分けたいって感じです


```yml
- description: '15分毎にhogeを実施'
  name: hoge_job
  nodesSelectedByDefault: true
{% if rundeck.jobs.is_notification %}
  notification:
    onfailure:
      plugin:
        configuration:
          webhook_url: {{ rundeck.jobs.notification.slack_webhook }}
        type: SlackNotification
  notifyAvgDurationThreshold: null
{% endif %}
  schedule:
    month: '*'
    time:
      hour: '*'
      minute: '*/15'
      seconds: '0'
    weekday:
      day: '*'
    year: '*'
```

実行してみるとエラー。 なんだか前の行と一緒にされているみたいです。

```perl
TASK [hoge_jobs : exec hoge] ***************************************
fatal: [hoge_ip]: FAILED! => {
  ...
  "stderr": "Error: Jobs Document was invalid for format yaml: mapping values are not allowed here\n in \"<reader>\", line 3, column 3:\n
  "Request failed: 400 Bad Request"
  ...
}
```

# 解決方法

結構悩んだのですが、1行空けるだけで解決します。

```yml
- description: '15分毎にhogeを実施'
  name: hoge_job
  nodesSelectedByDefault: true

{% if rundeck.jobs.is_notification %}
  notification:
    onfailure:
      plugin:
        configuration:
          webhook_url: {{ rundeck.jobs.notification.slack_webhook }}
        type: SlackNotification
  notifyAvgDurationThreshold: null
{% endif %}

  schedule:
    month: '*'
    time:
      hour: '*'
      minute: '*/15'
      seconds: '0'
    weekday:
      day: '*'
    year: '*'
```

ymlは改行が挟まっていても読み込めるので見栄えが悪くなる以外は問題ないです。本当にこの解決方法しかないのかな。。。。

一旦これで。
mosquittoでブリッジ接続の状態を判断する

## システムトピック

以下に定義されているトピックをサブスクライブするとmosquittoの管理情報を取得できる。

https://mosquitto.org/man/mosquitto-8.html

## ブリッジ接続状態の確認

下記のトピックでサブスクライブすると、mosquottoとブリッジ接続ができているかどうかを確認できる。

* state 1 : 接続成功
* state 0 : 接続失敗

※ 状態の更新はkeepalive_intervalに基づいて行われる。
※ 環境によっては、パスワード、ユーザIDを指定する必要がある

```bash
mosquitto_sub -v -t \$SYS/broker/connection/# -h localhost -p 1883
$SYS/broker/connection/client_name/state 1
$SYS/broker/connection/client_name/state 0
```
画面表示（ｽｸﾘｰﾝｼｮｯﾄ）から、QRｺｰﾄﾞを読み込んで、ﾃﾞｺｰﾄﾞするC#の単体ｱﾌﾟﾘ⇒テキスト書き出し版




[画面表示（ｽｸﾘｰﾝｼｮｯﾄ）から、QRｺｰﾄﾞを読み込んで、ﾃﾞｺｰﾄﾞするC#の単体ｱﾌﾟﾘです](https://qiita.com/santarou6/items/a130ea953dbe1c10dc3c)

の続きで、テキスト書き出し版

```c#:screen_qr_decode.cs
//c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /reference:QRCodeEncoderDecoderLibrary.dll /target:winexe screen_qr_decode.cs
//ILMerge /out:QR_OUT.exe screen_qr_decode.exe QRCodeEncoderDecoderLibrary.dll

using System;
using System.Windows.Forms;
using System.Drawing;
using QRCodeEncoderDecoderLibrary;

public class screen_qr_decode
{
 public static void Main(string[] args)
 {
    try{
    QRDecoder   QRCodeDecoder;
    Bitmap      QRCodeInputImage;
    QRCodeDecoder = new QRDecoder();
    QRCodeInputImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);

    Graphics g = Graphics.FromImage(QRCodeInputImage);
    g.CopyFromScreen(new Point(0, 0), new Point(0, 0), QRCodeInputImage.Size);
    g.Dispose();

    QRCodeInputImage.Save("temporary.png", System.Drawing.Imaging.ImageFormat.Png);

    byte[][] DataByteArray = QRCodeDecoder.ImageDecoder(QRCodeInputImage);

    //string Result = System.Text.Encoding.GetEncoding(932).GetString(DataByteArray[0]);
    string Result = System.Text.Encoding.UTF8.GetString(DataByteArray[0]);
    //string Result = System.Text.Encoding.GetEncoding(51932).GetString(DataByteArray[0]);

    // 文字列を置換するようなﾋﾞｼﾞﾈｽﾛｼﾞｯｸ（もしあれば）
    //string str1 = Result.Replace("ω", "　");
    //str1 = str1.Replace("Ω", "\t");

    string str1 = Result

    MessageBox.Show(str1);
    
    DateTime dt = DateTime.Now;
    string dt_s = dt.ToString("yyyyMMdd_HHmmss");

    
    System.IO.File.WriteAllText(@".\" + dt_s + ".txt", str1);


    }
    catch(Exception ex){
        MessageBox.Show("読み取りエラー\n\n"+ex);
    }

 }

}
```
python3は動いてるのに、pipenvが動かない？

pathの問題なんて、考えれば当たり前なのですが、自戒のために置いておきます。

## やろうとしたこと
仕事用のMacbookAirを買ったので、とりあえずpython3でpipenvをインストールしようとした。

デフォルトで入ってないので[公式のMacのページ](https://www.python.org/downloads/mac-osx/)からインストーラーを使って入れた。

```
$ python3
bash: python3: command not found

$ python --version
Python 2.7.10

# インストーラーでpython3を入れる
$ python3 --version
Python 3.6.5

$ pip3 install pipenv
```

よーしこれでpipenvが使えるぞ〜
と思って打ってみると

```
$ cd /work/dir
$ pipenv install
bash: pipenv: command not found
```
`command not found` 入れたのに、なんで〜？
python3もpip3も動いたのに…。

いったいpipenvはどこに？

```:.bash_profile
# Setting PATH for Python 3.6
# The original version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/3.6/bin:${PATH}"
export PATH
```
```
$ cd /Library/Frameworks/Python.framework/Versions/3.6/bin
$ ls
2to3			pipenv			python3.6-32
2to3-3.6		pipenv-resolver		python3.6-config
easy_install-3.6	pydoc3			python3.6m
idle3			pydoc3.6		python3.6m-config
idle3.6			python3			pyvenv
pip			python3-32		pyvenv-3.6
pip3			python3-config		virtualenv
pip3.6			python3.6		virtualenv-clone
```

あれパスの通った場所に、pipenvありますねぇ…なんででしょうねぇ…
ポックポクポク…チーン…あっ…

```
$ cd
$ source .bash_profile 
$ pipenv --version
pipenv, version 2018.11.26
```

インストーラーでやったから、プロファイルが勝手に再読み込みされるわけなかった。
`sudo apt install python3`に慣れすぎて、頭が回らなかったというオチでした。

python3 とか pip3 とかは既存の$PATH `/usr/local/bin` に実体が入ってたので、動いたのです。

クソ記事でごめんなさい。
縦書きにするCSS「writing-mode」がtableタグの中で効かない時

検証 → iOS 13.1.3 、ブラウザ: Chrome, Safari
※見ているデバイスや、サイトのHTML・CSSなどの構成によっては下記の通りにならないかもしれません。

# こんなデザインを実現したい

スマートフォンのデザイン。
<img width="374" alt="縦書きのデザイン例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40940/7430c4f5-ab46-7b66-6060-be9001def494.png">
左側のthを縦書きにしたい。
tdは`rowspan`や`colspan`で合体している。

# 1.左側のthタグを縦書きにするには

thタグに直接`writing-mode`をかけてもならなかった。
spanタグで囲んでspanに`writing-mode`をかけると適応された。

writing-mode
https://developer.mozilla.org/ja/docs/Web/CSS/writing-mode

```html
<tr>
    <th><span>縦書き</span></th>
</tr>
```

```css
.table tr:not(:first-child) th span {
    writing-mode: vertical-lr;
}
```

# 2.適応はできたようだけど、縦書きにならない

<img width="501" alt="縦書きCSSがうまくいかない表" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40940/51f32f10-5860-8a18-07d6-4c0355b50ffe.png">


thタグに高さ(min-height)を指定して解決した！
潰れていた模様。

```css
.table tr:not(:first-child) th {
    min-height: 3.6em;
}
```

# 全てのHTMLとCSS
※ 一部の細かいところは省略

<img width="499" alt="縦書きCSSの表　完成例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40940/9567e561-f431-b6f6-2d36-7647da26ace3.png">


```html
<table class="table">
    <tr class="title">
        <td></td>
        <th>タイトル</th>
        <th>タイトル</th>
    </tr>
    <tr>
        <th><span>縦書き</span></th>
        <td rowspan="2" colspan="2">
            <strong>テキストが入ります</strong><br>
            <span>テキストテキストテキストテキストテキスト</span><br>
            <span>※ テキストが入ります。</span>
        </td>
    </tr>
    <tr>
        <th><span>縦書き</span></th>
    </tr>
</table>
```

```css
.table {
    border-left: 1px solid #ccc;
    border-top: 1px solid #ccc;
    border-collapse: collapse;
    letter-spacing: .1em;
    margin: 0 0 20px;
}
.table th,
.table td {
    border-bottom: 1px solid #ccc;
    border-right: 1px solid #ccc;
}
.table td {
    line-height: 1.8;
    padding: 20px 6%;
    text-align: center;
}
.title th {
    background: #efefef;
}
.table tr:first-child th {
    padding: 17px 2% 18px;
    width: 43%;
}
.table tr:not(:first-child) th {
    background: #e3e3e3;
    letter-spacing: .2em;
    min-height: 3.6em;
    padding: 1em 1%;
    width: 1.5em;
}
.table tr:not(:first-child) th span {
    -webkit-writing-mode: vertical-lr;
    -ms-writing-mode: tb-lr;
    writing-mode: vertical-lr;
}
```
Webpackで名前にハイフンを含むモジュールをimportする

# どうすればいいか

ケバブケースの名前をキャメルケースに書き換える。

例：
moment-duration-formatというモジュール名なら
`import momentDurationFormat from 'moment-duration-format'`

と書く。

# 何がしたかったのか

Webpackを使ってJavaScriptをクライアントサイドで実行している環境で、moment-duration-formatという、時間（期間）の表示を簡単にするライブラリ（Nodeモジュール）を導入したかった。

webpackを使っているので、ES Moduleスタイルで
`import moment-duration-format from 'import-duration-format'`と書いた。

# どんな問題が起きたか

moment-duration-formatは時間を扱うライブラリであるmomentを拡張するライブラリであるためimport部は以下のようになるが

```javascript:index.js
import moment 'import-duration-format'
import moment-duration-format from 'import-duration-format'
```

javascriptでは`-`が算術演算子として予約済みなせいか、`moment`が一つのシンボルとして認識されてしまう。

なぜかVSCodeの画面では `import ... =' can only be used in a .ts file.` というエラーメッセージとなっている。
![EditableProgram_js_—_gachi-taite-designer-web.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99567/18e81626-a293-d95a-d3bb-1ee7833c820f.png)

ブラウザ上のJavaScriptコンソールでは`Module parse failed: Identifier 'moment' has already been declared` と上の行でmoment本体をimportしていることと関連したエラーメッセージとなっていた。
![Developer_Tools_-_Vivaldi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99567/ddb92570-4c99-f36b-def8-5c0309be6c76.png)

なおmomentのimportをコメントアウトした場合のエラーメッセージとしては `Module parse failed: Unexpected token`となり、import文の途中で算術演算子が登場することを怒られるようだ。
![Developer_Tools_-_Vivaldi2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99567/272536e5-759b-44a2-86de-5d0952bd8d64.png)
最短コードで100ループしてみる

最短のコードで100ループさせる方法を考える遊び。

```javascript
for(let _ in [...Array(100)])console.log(_)
```

```javascript
[...Array(100)].forEach(_=>console.log(_))
```

```javascript
(i=>{do{console.log(i)}while(i--)})(99)
```

```javascript
for(let _ of Array(100))console.log(_)
```

```javascript
(i=>{while(i--)console.log(i)})(100)
```

```javascript
let i=100;while(i--)console.log(i)
```

```javascript
for(let i=100;i--;)console.log(i)
```

```javascript
// ちょっと反則感
[...Array(100)].map(console.log)
```

@shiracamus さんコメントありがとうございました！
コマンドプロンプトのcdコマンドでDドライブに移動するには？

# はじめに
ふと、コマンドプロンプトでcdするときにDドライブに移動したことなかったなと思って調べてみました。

# 使用ツール

- コマンドプロンプト

# 何も考えずにやってみた

ユーザディレクトリからDドライブ直下に移動してみます。

```
C:\Users>cd D:\
```
↓

```
C:\Users>
```
移動できませんでした。

# 調べてから再チャレンジ

[こちら](https://qiita.com/Nemy/items/3ab1f91010ea9908d67)を参考にして再チャレンジしてみましょう。

```
C:\Users>D:
```
↓

```
D:\>
```
移動できました。

# そのほかのやり方

## dスイッチ

```
C:\Users>cd /d D:
```
↓

```
D:\>
```
正直`D:`のほうがシンプルだし、dスイッチ使う意味がよくわからないな。

## pushdコマンド

```
C:\Users>pushd D:\
```
↓

```
D:\>
```

こちらはpopdコマンドを使用することで元のフォルダに戻れるとのことです。
パス通さないと使えないみたいですけど。

```
D:\>popd
```
↓

```
C:\Users>
```


# 参考サイト
[コマンドプロンプトでDドライブに移動する](https://qiita.com/Nemy/items/3ab1f91010ea9908d67)
【メモ】Seaborn のhueに数値データに変換可能なものをいれるとAttributeErrorになる

# 環境
seaborn==0.9.0

# 問題

seaborn のlineplot でhueに数値データに変換可能なものをいれると`AttributeError: 'str' object has no attribute 'view'`となる

# 解決策
paletteでcolorを陽に指定すればよい(https://github.com/mwaskom/seaborn/issues/1515)
下の方法は10色までしか対応していないと思われるので、それ以上の色を使うなら別途paletteを指定する必要はある。(参考：https://seaborn.pydata.org/tutorial/color_palettes.html)

```python3
import pandas as pd
test_df = pd.DataFrame(
[{"a": 0.0, "b": 1.0, "c": "1"},
 {"a": 0.0, "b": 1.0, "c": "2"}]
)
num_colors = len(test_df["c"].unique())
current_palette = sns.color_palette()
palette = current_palette[:num_colors]
g = sns.lineplot(x="a", y="b",hue="c", palette=palette, data=test_df)
```

https://github.com/mwaskom/seaborn/issues/1515#issuecomment-408436200
を参考にしました

# 原因
hueがducktypingで、数値に変換可能なら数値として解釈されてしまうことが原因。バグはwipらしいのでバージョンを上げたら解決するかも
[UE4]　ブループリントをコピーペースト

ブループリントがただのテキストだと分かりましたか？
マウスで選択し、CTRL + Cをしたら、ノートパッドなどにペーストを出来ますよ！

変更する前のセーブ、それかまるで他のブループリントでロジックをコピーしたいときに非常に便利な機能です！

![2019-11-14_17h36_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369484/48a57a6a-af4d-6f56-c246-7b1d160a98a1.png)

![2019-11-14_18h00_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369484/f099c8c9-f536-200c-65bc-ccd51f4b3296.png)
Go言語での文字列操作に関して覚えておきたいこと

##前提知識
###Goでの文字の扱い
文字列にインデックスでアクセスすると、byteになる（byteはuint8のエイリアス）。

```Go
func main() {
  a := "abc"
  fmt.Printf("%T\n", a[0]

  str := "abc"
  for i := 0; i < len(str); i++ {
    fmt.Printf("%T\n", str[i])
  }
}
//出力結果　
//uint8
//uint8
//uint8
//uint8
```
文字列をrangeでループすると、runeが得られる。int32はruneのエイリアス。

```Go
func main() {
    a := "abc"
    for _, s := range a {
  	    fmt.Printf("%T\n", s)
    }
}
//出力結果
//int32
//int32
//int32
```
出力されるのはASCII。

```Go
func main() {
	str := "abc"
	for i := 0; i < len(str); i++ {
		fmt.Println(str[i])
	}
	for _, s := range str {
		fmt.Println(s)
	}
}
//97
//98
//99
//97
//98
//99
```
％xを使うことで、UTF-8でのbyte表現を出力できる。

```Go
func main() {
	str := "abc"
	for i := 0; i < len(str); i++ {
		fmt.Printf("%x\n", str[i])
	}
	for _, s := range str {
		fmt.Printf("%x\n", s)
	}
}
//61
//62
//63
//61
//62
//63  
```

###rune
コンピュータは、扱う文字によってはバイトを複数組み合わせて文字を表現する。しかし、文字の数を扱う際には、マルチバイト文字が存在する以上byteを単位として数えるのは都合が悪い。そこで、一つの文字が一つだけ持つコードポイントを利用する仕組みがGo言語には用意されている。それがruneである。

###文字コードとコードポイント
####文字コード
人間が使う文字も最後には0と1の並びとしてコンピュータには解釈されるが、人間の使う文字にはそれぞれに番号が割り振られており、その番号が文字コードである。文字コードはいわば実際の文字とコンピュータが解釈する2進数の中間に位置し両者を対応づける存在と言える。この文字コードは符号化方式という文字集合を構成する文字の表現方式によって違いが出る。この符号化方式は、GoではUTF-8が使用されている。
####コードポイント
この文字コードと紛らわしいのがコードポイントで、コードポイントは文字集合(Unicodeなど)に属する文字に順々に割り振った数値のこと。つまり、コードポイントは2進数と関連はなく、文字集合が同じなら各文字のコードポイントは符号化方式（UTF-8、UTF-16など）によって違いがなく共通である。コードポイントは文字集合の種類によって異なる。

符号化方式、文字集合あたりの知識が曖昧な人は以下のリンク先のページを読むことをオススメします。
http://equj65.net/tech/charcode/


###マルチバイト文字

- 1バイトで表せるのは10進数で0〜255まで。
- つまり、1バイトでは0〜127までに割り当てられているASCII文字と、128〜255までにおさまる文字（各文字コードで異なる）しかコンピュータ上で表せない。

しかしそれでは困るので、0〜255までに割り当てられている文字以外も表すために複数のバイトが使用される。そのように複数のバイトを使用して表される文字をマルチバイト文字と言う。

##マルチバイトの文字列操作例
マルチバイトの文字列の操作例。
###文字列を逆順にする場合
Goでマルチバイトの文字をそのまま逆順にしようとすると、マルチバイトの関係でうまく行かない。

```Go
func main() {
  a := "あいうえお"
  fmt.Println(badReverse(a))

}
func badReverse(s string) string {
  output := ""
  for i := len(s)-1; i >= 0; i-- {
    output += string(s[i])
  }
  return output
}
// 出力結果
//ããããã
```


マルチバイトを扱うために、文字列をruneにする。rangeで文字列にアクセスすると、runeが得られるがrangeだと昇順になるので、この場合は使えない。

```Go
func main() {
  a := "あいうえお"
  fmt.Println(reverse(a))
}

func reverse(s string) string {
  var output bytes.Buffer
  runes := []rune(s)
  for i := len(runes)-1; i >= 0; i-- {
    output.WriteRune(runes[i])
  }
　　return output.String()
}
//出力結果
//おえういあ
```

###文字列の文字の数を数える場合
マルチバイト文字があると、lenで文字列を数えてもバイト数を数えることになってしまうので期待通りの結果が得られない。runeのスライスに変換して長さをlen()で出すか、unicode/utf-8にあるRuneCountInStringを使う。

```Go
func main() {
	str := "Hello, 世界"
	fmt.Printf("Byte: %d \n", len(str))
	fmt.Printf("Rune: %d \n", utf8.RuneCountInString(str))
	fmt.Printf("Rune: %d \n", len([]rune(str)))
}
```
###文字列の一部を切り出す場合
ここでも同様に、マルチバイトであることを考慮してruneに変換してから切り出す。

```Go
func main() {
	str := "あいうえお"
	fmt.Println(str[0:3])

	r := []rune(str)
	fmt.Println(string(r[0:3]))
}
//あ
//あいう
```
##参考
http://equj65.net/tech/charcode/
5分で作るPHP開発環境(Docker-compose)

PHPの開発環境が欲しくて色々調べたところ、XAMPPなんて便利なものがあるらしい。
ただここはインフラエンジニアらしくdockerで作ることにした。
ネットに散々ナレッジは落ちてるが、環境が違ったり情報が古かったりと中々動いてくれなかったので、トラシューなども含めてメモしておく。
###動作検証環境
- macOS
 - Sierra vr10.12.6
- docker
 - Docker version 19.03.1
- docker-compose
 - docker-compose version 1.24.1
<br>
<br>


## いいから早くさわらせろ
###コンテナの起動
https://github.com/yuto-miyazawa/Docker-Compose
詳しくはREADMEを参照。
前提としてdocker,docker-composeコマンドは入れておくこと。


1.上記のgitリポジトリをお手元にclone
2.カレントディレクトリを「lamp」移動
3.下記のコマンドでコンテナを起動

```
docker-compose up -d
```


### コンテナの起動確認
1.ブラウザで`http://localhost` に接続 -> hello world!が出ればok
2.ブラウザで`http://localhost:8080` に接続 -> myphpadminの画面に飛べればok
<br>
<br>


## dockerが起動しない場合
### portが重複してる
dockerは使用するportをポートフォワーディングしている。

```dockerfile:docker-compose.yml
    ports:
    - 8080:80  // 8080ポートで外部で受け、コンテナ内の80ポートへ流す
```
この場合、8080ポートがすでに使われている場合、dockerはコンテナを立ち上げることができない。
下記を試すと起動できるようになる可能性がある。

   1. 他のアプリケーションを停止する(Skypeとかは80を使うらしいので怪しい)
   2. 8080の箇所を別の使用されていないポートに書き換える

<br>
<br>
## トラブルシューティング
以下構築時にハマった箇所のメモ

### mysql-clientがapt-getできない

```dockerfile:php/Dockerfile
apt-get install -y zlib1g-dev mysql-client
```
Debianはあるバージョンから「mysql-client」パッケージがなくなり「default-mysql-client」パッケージにかわったため、こちらをapt-getする

```dockerfile:php/Dockerfile
RUN apt-get update \
  && apt-get install -y zlib1g-dev mysql-client \
  && docker-php-ext-install zip pdo_mysql
```
<br>

### composer-setup.phpが古い
phpコンテナを立ち上げる際にこのファイルを読み込むのだが、ハッシュ値を確認しているため最新の値にしてやる必要がある。

```dockerfile:php/Dockerfile
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
```
https://getcomposer.org/download/
↑から最新のファイルを取得する
<br>

###phpからmysqlに接続できない
phpからmysqlに接続しようとすると以下のエラーが出る。

```
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
```
色々調べた結果、どうやらphpからmysqlコンテナを指定する場合、localhostではなくmysqlのコンテナ名を指定してやる必要があった。
今回の場合だとコンテナ名「mysql」を指定する。

```bash
// phpコンテナに入る
$ docker exec -it php /bin/bash

// mysqlに接続
mysql -u root -p -h mysql
```
.phpでmysqlに接続する場合も同様

```php
$dsn = 'mysql:dbname=shop; host=mysql; charset=utf8';
```
Windowsで特定の拡張子のファイルを一括削除しよう

#はじめに
WinMergeを使ってファイルを比較して片方に合わせるようにコピペしていたら、
拡張子が.bakのファイルが増えてしまったので、一括削除できないか調べました。

#使用ツール

- コマンドプロンプト

#手順

1. 一括で削除したい拡張子のファイルがあるディレクトリに移動
2. 削除！

#やってみよう

##1. 一括で削除したい拡張子のファイルがあるディレクトリに移動

```
cd 一括で削除したい拡張子のファイルがあるディレクトリ
```

##2. 削除！

```
del /s *.bak
```

#解説
##1. 一括で削除したい拡張子のファイルがあるディレクトリに移動
これについては略。

##2. 削除！

`del`はファイルを削除するコマンドです。
オプションの`/s`は「指定したファイルを全てのサブディレクトリから削除し、削除したファイル名を表示する」ことを意味します。
サブディレクトリのファイルも対象にしたくない場合は`/s`オプションは外してください。
`*`は0文字以上の任意の文字列です。`*.bak`は拡張子が「.bak」のファイルすべてという意味です。

#参考サイト
[特定の拡張子のファイルを一括削除するには？](https://blog.masahiko.info/entry/2009/09/25/211343)
[ファイルを削除する](https://www.k-tanaka.net/cmd/del.php)
Alfresco CEのトラッキングタグを削除する方法

# やること
Alfresco Community Edition のshareページに設置されるトラッキングタグを除外する。
自身の備忘録として。

# バージョン
Alfresco 6.1.0-RC3
Java 8
Maven 3.6.1

# 手順


 - [Alfresco/shareのリポジトリ](https://github.com/Alfresco/share)をローカル環境にクローン(稼働中のAlfrescoとは別の環境に)
 - share/share/src/main/java/org/alfresco/web/scripts/MessagesWebScript.java内の if isCommunty() {} 部を削除し上書き保存
 - ビルドして、生成されたMessagesWebScript.classを稼働中のAlfresco環境に配置し、再起動
Go言語で文字列内に変数を入れる方法

##やりたい事
PHPで言うところのこれがやりたい。

```php

 $name = '山田太郎';
 $str  = "あなたのお名前は ${name} さんです。";

 echo $str;
 // 結果：あなたのお名前は 山田太郎 さんです。
```

Sprintfを使えば挿入はできるけど、書式子指定したりとか変数自体は引数に持ってこないといけないとか、ちょっとめんどう(2019-11-15:追記)

##結論
**そんなものはなかった**

PHPのように、別で用意した変数を何も考えずにそのまま文字列内に突っ込む方法はないようです。悲しい。

##じゃあどうするか
１）＋で結合する
~~２）Print関数などで出力時に結合する~~　(2019-11-15:例として不適切だったので差替え)
２）Sprintf関数などを使用する

###+で結合する

```Go
name := "山田太郎"
str  := "あなたのお名前は " + name + " さんです。"

fmt.Print(str)
// 結果：あなたのお名前は 山田太郎 さんです。
```
PHPでもよく見る形です。

###Sprintf関数などを使用する

```Go
name := "山田太郎"
str  := fmt.Sprintf("あなたのお名前は %s さんです。", name)

fmt.Print(str)
// 結果：あなたのお名前は 山田太郎 さんです。
```
PHPではあまり見ない形。C言語を思い出します。

(srtkkouさんにコメントをいただいてから、こっちの方法を書かないといけないと気付き、差し替えました。ありがとうございます。)

---
PHPに慣れていたので直接変数の挿入ができないのは、手足をもがれたような気分です。
慣れるまでしばらく頑張ります。

##参考
[Golang の文字列内で変数を展開する方法（各種）](https://qiita.com/KEINOS/items/baef1be88f15515026ec) @ Qiita