OmniAICreator/Qiita-1.07M huggingface dataset:
埋め込みGoogleMapの見た目を調整する

## 埋め込みGoogleMapでどこまでできるのか
案件で、「Map付きのページを見やすくしたい」というものがあった。
GoogleMapAPIは、アカウント登録が必要で、さらに閲覧数が多いと有料である。
そのため、可能な限り、埋め込みGoogleMapで見た目の調整ができないか、ということだった。

## GoogleMapの埋め込み方法（基本）
1. 表示させたい場所を、GoogleMapで検索する。

1. 検索結果が出た状態で、GoogleMapの画面左メニューの「地図を共有または埋め込む」を選択。

1. 「リンクを送信する」と「地図を埋め込む」のタブが出るので、 「地図を埋め込む」を選択。

1. 表示されるiframeタグ（インラインフレームタグ）をHTMLに埋め込む。

### iframeタグの例
` <iframe 
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3241.1169400118947!2d139.76553521603608!
3d35.67412248019593!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x60188be4759ec9d3%
3A0x4aa2ae8a415fa53e!2z44CSMTA0LTAwNjEg5p2x5Lqs6YO95Lit5aSu5Yy66YqA5bqn77yR5LiB55uu77y
X4oiS77yR77yQIOODkuODpeODvOODquODg-OCr-mKgOW6p-ODk-ODqw!5e0!3m2!1sja!2sjp!4v1569389323989
!5m2!1sja!2sjp”width="600" height="450" frameborder="0" style="border:0;" allowfullscreen=""></iframe>`

## 地図が拡大縮小できないとき
地図サイズが、縦横各200pxより小さくなると、地図の拡大・縮小が出来なくなるので注意。
赤枠で囲んだ部分でサイズを調整できる。
または、赤枠部分の記述を削除してCSSでサイズ指定する。
<img width="1316" alt="スクリーンショット 2019-10-10 8.43.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355316/d593157e-a785-b31e-5735-c6c82058fbef.png">

## 地図の縮尺を調整したいとき

GooglpMapの縮尺の初期値は、Mapが自動で調整したものになる。
赤枠部分の数字を変えると、13.1を基準に縮尺を大きく/小さくできる。
（0~180の範囲で）
数値を小さく→ズームアップ
数値を大きく→ズームアウト
<img width="1336" alt="スクリーンショット 2019-10-10 8.47.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355316/a8b827c8-6a9b-5b4d-41ff-c161b6f0c822.png">



## 地図上の赤いピンの位置を変えたいとき

この部分の緯度・経度は、GoogleMapの画面の中央にあたる。
この部分の数字を変えることで、赤いピンの位置を中心からずらすことができるはず…

<img width="1339" alt="スクリーンショット 2019-10-10 8.55.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355316/3ccda7e6-7def-1785-8bd7-4c07c0aef959.png">

なのだが…



この方法では、変化がなかった。
埋め込みGppgleMapでは、ここまでは不可能なのだろうか。

<img width="896" alt="スクリーンショット 2019-10-10 8.57.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355316/f266ff99-636c-9244-ffb1-1525a83ba1d0.png">

しかし、もう１つの別の方法をとると、ピンの移動が可能になった。

### パラメータによる位置指定

iframeタグの中身を画像のような記法で書き換える。

<img width="1349" alt="スクリーンショット 2019-10-10 9.02.24のコピー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355316/499e5799-296b-ee13-fdfa-d6463e7df3b5.png">
iframeタグ内の緯度・経度は、GoogleMapで場所を検索したときに、URLに出てくるので、そこからコピーしてきたものを微調整する。

この記法で書くと、
<img width="880" alt="スクリーンショット 2019-10-10 9.04.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355316/daa48475-f243-f802-1133-42071f367780.png">

ピンの位置が見やすい位置に移動した。


この方法の難しいところは、緯度・経度の小数点以下の細かい数字を、自分の感覚で微調整しなくてはいけないところだ。
また、この方法は、Googleによる公式の方法ではないようだ。
仕事の案件などではなるべく使わない方が良い。
（今回の案件でもこの方法は採用はしなかった。）

## まとめ・補足
- 非公式な方法ではあるが、パラメータで指定する方法を使えば、以下の設定も可能。
 - 表示モード（地図・航空写真・地形図）
 - 言語（日本語・英語・中国語など）

- GoogleMapAPIを利用しなくても、埋め込みGoogleMapで、ある程度の見た目の調整は可能であることがわかった。
- 縮尺の調整をする際などは、「もっと大きく・小さく」のやり取りを繰り返さないためにも、クライアントとの認識合わせが必要。
macOS Catalina にしたらGitコマンドが動かなくなった ( #git # Mac )

# エラー

```
$ git
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

# 解決

```
xcode-select --install
```

[macOS MojaveにしたらGitコマンドが動かなくなった - Qiita](https://qiita.com/n0bisuke/items/1c60084c8c07b690d693)

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2570








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
ThingSpeakでエラー値

気圧計モジュールの[BMP180のデータ](https://qiita.com/yamori813/items/c2cb30fb48b216ab89e9)を13万件ほど送ったところで二件エラーがあり、最高最低気温のフラフがおかしくなりました。

```
2019-10-07 10:57:20 JST,129382,-196.9,476.54,,,,
2019-10-07 13:13:05 JST,129848,-83.5,722.24,,,,
```

気温が-196.9と-83.5になってしまってます。

![スクリーンショット 2019-10-10 9.01.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/91d82200-4f7b-bf4c-f32f-737e0531f3a8.png)

ThingSpeakは部分的にデータを削除することはできないのでMATLABで対処する方法を調べてみました。

とりあえず気温のデータがマイナスの場合NaNにしてデータを無効化してみました。

```MATLAB
% Last week max and min temputure

readChannelID = ;
readAPIKey = "";

day = datetime('now') - 14;
disp(day);

% startdaystr = "Sep 22, 2019 00:00:00";
% enddaystr = "Sep 23, 2019 00:00:00";

for c = 1:14
    
    startdaystr = datestr(day,'mmm dd, yyyy 00:00:00');
    enddaystr = datestr(day + 1,'mmm dd, yyyy 00:00:00');
    [a,b] = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'Fields',1,'DateRange', [datetime(startdaystr),datetime(enddaystr)]);

    a(a < 0) = NaN;
    [m, n] = max(a);
    [x, y] = min(a);

    %disp(m);

    t(c) = day;
    vmax(c) = m - x
    vmin(c) = x
    day = day + 1
end

C = vertcat(vmin, vmax);

H = bar(t, C, 'stacked');

set(H(1),{'FaceColor'},{[1 1 1]});
set(H(1),{'EdgeColor'},{[1 1 1]});
set(H(1),{'LineWidth'},{1});
```

こうなりました。

![スクリーンショット 2019-10-10 9.02.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/0cb5994e-5f48-f5b5-0f96-54ac818a4166.png)

このスクリプトにはマイナスになった時に正しく動かないバグもあるようです。
plunkerでangular

#概要

plunkerでangularやってみた。

#成果物

https://embed.plnkr.co/8OqDUo4G3EDOrOsQXXyZ/

https://embed.plnkr.co/Hj8hUYop0DLHcuUeUlGT/

https://embed.plnkr.co/sLnL8jOMrpuI8RR43XG0/


以上。
ShellScript書く時の小ネタ

すぐ忘れることが多い小ネタをまとめていきます。多分随時更新します。

#### ファイル存在チェック
```bash
if [ -e ${FILE_NAME} ]; then
    # DO SOMETHING
fi
```

##### 存在しない場合は否定

```bash
if [ ! -e ${FILE_NAME} ]; then
    # DO SOMETHING
fi
```

#### ファイルを空にする
```bash
: > ${FILE_NAME}
```

#### 対象ディレクトリ内を一覧する
```bash
for file in `\find ${DIR_NAME}`; do 
    echo $file
done
```

##### 探索の深さ指定

```bash
for file in `\find ${DIR_NAME} -maxdepth 1`; do 
    echo $file
done
```

##### ファイルのみをリストするよう指定（ディレクトリ除外）

```bash
for file in `\find ${DIR_NAME} -type f`; do 
    echo $file
done
```

#### ディレクトリ内のファイルのみ削除する
```bash
find ${DIR} -type f | xargs rm -f
```

#### 2ファイルを比較して差分を抽出
diffだと色々入ってしまってまた加工が大変なので

```bash

awk -v "result_file=${RESULT_FILE}" 'BEGIN {FS = "\n"} NR == FNR {a[$1]=1; next}
{
    if ($1 in a) {
        print "" >> "/dev/null"
    }
    else {
        print $1 >> result_file
    }
}' ${FILE_NAME_1} ${FILE_NAME_2}
```

#### awkに変数を渡す
`-v`オプションを利用する
awkコマンドの-vオプションに続けて`awkで用いる変数=代入する値value(もしくはシェル変数)`を記述

```bash
awk -v hoge=value '{print $0 > hoge}' file
```

### thanks
- https://japanrock-pg.hatenablog.com/entry/20100212/1265972572
- http://trilf2.blogspot.com/2009/11/awk.html
- https://qiita.com/gin_135/items/39baa6426cb342d3370f
- https://blog.bgbgbg.net/archives/2770
Dockerfileの「RUN mkdir /path && cd /path」はWORKDIRで一発

Qiitaの記事やDocker Hubを見てみると、あまりにも以下の様に書いているDockerfileが多い。

```Dockerfile
ENV $APP_PATH = /app
RUN mkdir $APP_PATH && \
    cd $APP_PATH && \
    curl ...
```

これは`WORKDIR`を使えばこう書けます。

```Dockerfile

ENV $APP_PATH = /app
WORKDIR $APP_PATH
RUN curl...
```

`WORKDIR`で指定したディレクトリがない場合は生成されてから作業ディレクトリになります。つまり`mkdir`や`cd`が不要になります。
また`WORKDIR`で指定したディレクトリが`docker container run`を行った時の作業ディレクトリになるのでコンテナに入る時に分かりやすいです。

あと単純に記述量が減るので見やすくなります。

## 参考
Dockerfile リファレンス [WORKDIR]
http://docs.docker.jp/engine/reference/builder.html#workdir
PHPでSQL文(クエリ)の実行

PHPでSQL文を実行する方法です。

SQLの実行方法を検索したところ、実に様々な方法がありました。
例えば、トランザクション処理の有無、PDO属性の設定、バインド変数の設定などです。
ここでは個人的に分かりやすかった方法を記載します。

#パターン1
<pre>
$変数='1';

$dbh = new PDO ('mysql:dbname=データベース名;host=ホスト名またはIPアドレス;charset=utf8;',ユーザ,パスワード,PDO属性)；
$sql = 'SELECT * FROM liked WHERE カラム名 = :バインド変数';
$変数2 = array(':バインド変数' => $変数);

$stmt =  $dbh -> prepare($sql);
$stmt -> execute($変数2);

echo '結果は'.$stmt->rowCount();
</pre>

・ブラウザでPHPファイルを確認すると「結果は１」と表示されます。
１は＄変数で指定した値です。
・「:変数」はSQLステートメント内の変数値のバインド変数(プレースホルダー)です。
このバインド変数の指定にはいくつかの方法があります。
今回は＄変数２でバインド変数の値を格納しています。

以下のような記述でも可能です。
<pre>
$stmt = $dbh -> prepare($sql);
$stmt -> bindvalue(':バインド変数', $変数);
$stmt -> execute();
</pre>

#パターン２
**file1.php**
<pre>
// 関数の呼び出し
require('file２.php');

// データベース接続情報
$dbh = new PDO ('mysql:dbname=データベース名;host=ホスト名またはIPアドレス;charset=utf8;',ユーザ,パスワード,PDO属性)；

// SQL文の作成
$sql = 'SQL文'

$stmt = 関数($dbh, $sql);
$変数 = $smtm -> rowCount();
</pre>

**file2.php**
<pre>
function 関数($dbh, $sql){
$stmt = $dbh -> prepare($sql);
$stmt -> execute();
}
return $stmt;

// returnした¥$stmtをfile1.phpに返します。
// SQL文の実行した結果($stmt)をrowCount()でCountし、$変数に格納します。
</pre>
PowerShellでログファイルを監視してWebhookで通知する

# はじめに
本記事は、WindowsのPowerShellを用いて、アプリケーションが出力するログファイルを監視する方法について記載しています。また、特定のエラーメッセージ検知時にWebhookを使用してチャットアプリに通知します。

監視対象とするログファイルは、Cドライブ配下などに出力するテキストのログファイルを対象とします。

Windoows Serverで監視ソフトウェアを導入することなく、特定のメッセージを検知時に通知したいといった小規模な監視が実現できます。

## Webhook
slackやRocket.Chatなどのチャットアプリは、Webhookとして**curl**を使用する場合がほとんどです。

通知の仕組みを作る考え方として、連携したいチャットアプリがSDK等を公開していて、Pythonなどのライブラリを使用できるのであれば、Pythonで書いた方がスマートな場合もあります。本記事では、WindowsでWebhookを使用するための方法を前提とします。

現在は、WSL（Windows Subsystem for Linux）という便利なものがあるので、WSLが使用できる環境であれば、WSLも一つの案だと思います。なお、Windows Server 2016では、Insider Preview build 16215以降に搭載されています。

要約するとWindows ServerでWebhookを使用するためには、curlが必要です。
curlを使用するために、[curl](https://curl.haxx.se/download.html)から64bitのbinaryをダウンロードします。Providerは、特に理由がなければ「the curl project」でいいでしょう。

## PowerShell
Powershellでログ監視の設定を行います。以下の例は、testフォルダ配下のtest.txtファイルに、ERRORの文字列が出力された場合、curl.batを起動してWebhookと連携します。

- powershell.ps1

```powershell
Get-Content -Path "C:\Users\test\Desktop\test\test.txt" -Wait -Tail 0 | ForEach-Object { If($_ -like "*ERROR*") { Start-Process -FilePath "C:\Users\test\Desktop\test\curl.bat" } }
```

batファイルでは、Webhookを使用するたにcurlの処理（※）を書きます。Windowsでcurlを使う場合のポイントは、文字列を適切にダブルクォーテーションの引用符でくくることです。また、引用符の中で引用符を使用する場合はエスケープを行います。日本語をメッセージとして出力させたい場合は別途、考慮が必要です。以下の場合、チャットアプリにERRORの文字列を通知します。

（※）例としてcurlのあるフォルダに移動して実行しています。

- curl.bat

```text
@echo off
cd C:\Users\test\Desktop\
curl-7.66.0-win64-mingw\bin\curl --request POST --header "Content-Type: application/json" --data "{\"text\":\"ERROR\"}" <WebhookのURL>
```

# おわりに
上記、powershell.ps1とcurl.batファイルを配備し、powershell.ps1を実行すれば監視が始まります。Windoows Serverでちょっとした監視がしたいという場合に便利です。
Arduino用 touch displayのサンプル実行まで

タッチディスプレイを複数使いたかったのでテスト。
使い倒す以前に視野角が狭くて、用を成さなかったので、別の用途を考える。
#環境
Windows 8
Arduino IDE 1.8.4
KEYESTUDIO UNO R3 (Arduino Uno互換品)
Kuman Arduino用ディスプレイ タッチスクリーン 2.8 inch 320*240ピクセル LCD 16bit Arduino Nano Mega2560適用ディスプレイ K60
#準備
添付の8cm CDの
Arduino Demo_UNO&Mega2560\Install libraries
の中の
Adafruit_GFX
Adafruit_TFTLCD
TouchScreen
３フォルダを
C:\Users\??????\Documents\Arduino\libraries
にコピーする。
または、ネットからダウンロードする。
※ダウンロードは、右端の緑のボタンから行う。
https://github.com/adafruit/Adafruit-GFX-Library
https://github.com/adafruit/TFTLCD-Library
https://github.com/adafruit/Adafruit_TouchScreen
※ライブラリを追加後に、arduinoを起動しないと認識しない。

#実行
8cm CDの中のArduino Demo_UNO&Mega2560のサンプルを実行する。


###Example01-Simple test
赤緑青のワイプで塗りつぶされる。
![1686A789-467C-4DEB-90E7-447ECDA9100E.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/31e8c308-3fb9-fef7-0a93-1b1ff81d283d.jpeg)
###Example02-DisplayString
ABC文字と数字がサイズ違いで表示される。![040EB4AD-7511-4AA8-AC04-1CF8D91DB25D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/1d945158-88a5-6136-f9df-7a308f159f75.jpeg)


###Example03-graphicstest
線とか円でグラッフィクが描かれる。
![2D4C20EF-8750-476C-87D9-E4C5C997B13C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/28b422fa-cbf0-dc9b-9fd1-3c67ecb0f6c8.jpeg)

###Example04-Touch
６色のパレットがあり、タッチ（圧力）で色選択とペンでの描画が出来る。
![812D1809-655B-4341-8410-7F7C89A382E7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/565717bb-6aee-cd6f-370f-0e08363fa0da.jpeg)

###Example05-ShowBMP
microSDにBMP画像を入れておき、スライドショー表示が出来る。
PICフォルダに
サンプル画像が４つあり、240x320 24bit 225KBである。
8cm CDの
Tools-Image2Lcd 2.9\Image2Lcd 2.9(Crack version)
に変換ツールっぽいのがあるけど、なんだろう？
![ccc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/6dca5e74-183a-138c-a8b3-e98de9edb29c.png)
![E92802EB-225D-4ABD-BFF6-9A9A66D6CF98.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/11db6bb9-d8fc-fe16-8400-39acf52b120b.jpeg)


###Example06-Phonecal
電話のプッシュボタンみたいな表示が出て入力が出来る。
もちろんこれで電話をかけることはできない。
![89E1EB0B-E60E-4034-80B9-C08ED6B8292C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/2542338a-6f4d-8ecc-20ea-61c88423ce3a.jpeg)
Shifted Stringsをall()を使って解いてみた

# 問題
You are given two strings, A and B. Return whether A can be shifted some number of times to get B.

Eg. A = abcde, B = cdeab should return true because A can be shifted 3 times to the right to get B. A = abc and B= acb should return false.

**つまり**、２つの文字列が渡されて、それがいくつか右にずらすと２つの文字列が一致するのか、そんなことはできないのかを回答する。

#例
A = 'shinbunshi'
B = 'nbunshishi'
--> True　#Aを4つ右にずらすとBになりますよね。

A = 'apple'
B = 'plepa' 
--> False #AをいくつずらそうともBにはなりません。Aは'eappl','leapp','pleap','pplea'にしかなりません。

# 解法1
```python:solution1.py
def is_shifted(a, b):
  # input strings, strings
  # return True or False
  
  if len(a) != len(b):
    return False

  if a == b:
    return True

  # checking all index.

  for index in range(len(a)):

    if a[0] == b[index]:
      left_length = len(a) - index

      if a[:left_length] == b[-left_length:] and a[left_length:] == b[:-left_length]:
        return True

  return False
```

想定している結果を返しますが、もっとスマートな書き方があります。
# 解法2

```python:solution2.py
def is_shifted(a, b):
  # input strings, strings
  # return True or False

  if len(a) != len(b):
     return False
  if len(a) == 0:
     return True

  for s in range(len(a)):
     if all(a[(s+i) % len(a)] == b[i] for i in range(len(a))):
        return True
  return False

```

回答方針は同じですが、スッキリしましたね。
些細なことですが、解法1では文字列が`''`の場合を考慮できていませんでした。解法2ではうまく対処できています。
解法2のallの使い方や、`a[(s+i) % len(a)]`のようにして`IndexError: string index out of range`のエラーを回避しています。
未使用のstyleを排除したcssを生成する


chromeの拡張機能で、cssやjsの利用状況を確認することができ、解析結果をexportすることができます。
https://umaar.com/dev-tips/187-code-coverage-export/

exportしたjsonは下記コードで、未使用箇所を排除したcssを取得することができます。

```php
$json = json_decode(file_get_contents('Coverage-20191010T053906.json'));

//数字2は、何番目のcssを対象とするかを指定
$json = $json[2];
$out = '';
foreach ($json->ranges as $range) {
    $out .= substr($json->text, $range->start, ($range->end - $range->start))." \n";
}
echo '<pre>';
echo $out;
echo '</pre>';
```
Ansible×Python入門用記事

## Ansibleとは　1221更新

Ansibleはシステムのオペレーションの自動化を支える、Python製の構成管理自動化ツール。Ansibleを利用することによって、スクリプトや手動で行なっていた運用オペレーションを自動化し、開発プロセスを効率化することができます。
Ansible以前にも管理ツールは多くあったが、導入コストの高さなどが原因で、導入まで行かなかかったケースが多かったが、現在は大手金融機関や製造業の現場でも採用しているケースも多く、認知度も上がっています。

## Ansibleの特徴

・主に下記が挙げられますが、後で後述します。

・設定ファイルの可読性の高さ（Simple)
・エージェントレスの構成（Agentless)
・マルチレイヤの対応（Powerful)


## Ansibleの環境

Ansibleの管理対象サーバーに、エージェントツールは不要です。必要なのは、Python2.4以降がインストールされていることだけです。最近の主要なLinuxディストリビューションであれば、Pythonは大体インストールされていますので、追加でインストールする必要もありません。

また、Ansibleモジュールによる拡張性の高さAnsibleには、管理対象サーバーやサービスごとに実に様々なモジュールが用意されています。サービスの起動・停止を行うモジュールから、iptablesのファイアウォールを設定するモジュール、AWSやAzure、OpenStackなどのクラウドインフラを制御するAnsibleモジュールも存在します。

参考書　平 初,平原一帆,小野寺大地,安久隼人,坂本諒太,冨永 善視. Ansible徹底活用ガイド (ThinkIT Books) (Japanese Edition) 

## Ansibleのユースケース

・Ansibleではアプリケーションのデプロイメントやミドルウェアのクラスタ構成を一つのファイルとして取り扱い、複雑な依存関係や複数のサーバー間の連携を可能にします

・Hadoopクラスタの構築
・PHP実行環境とWordpressのデプロイメント
・Jenkinsを用いたCI環境の構築

・ブーストラッピングレイヤーにおけるAnsibleの活用事例

・AWSのAPIを利用したEC2インスタンスの立ち上げ
・Dockerを利用したコンテナの管理
・Vagrantを利用した仮装マシンの立ち上げ

このように、Ansibleが包括的にマルチベンダーのAPIを　取り扱うことができる


## Ansibleに取り組むべき理由とメリット

PuppetやChef、そしてAnsibleなどの構成管理ツールを使うべき理由としては、

以下のようなものが挙げられます。

①手動オペレーションによるタイムロスの削減
②メンテナンス時におけるオペレーションミスの発生可能性の低減
③運用後における手順の変更が、作業手順書に反映されていないことによる作業漏れの撲滅

平 初,平原一帆,小野寺大地,安久隼人,坂本諒太,冨永 善視. Ansible徹底活用ガイド (ThinkIT Books) (Japanese Edition) (Kindle の位置No.160-165). Kindle 版. 

## Ansibleのインストール

公式：Git hub
https://github.com/ansible/ansible

##yum(rpm)を利用したインストール　CentOS環境下など

```
$ sudo yum install -y epel-release
$ sudo yum install -y sshpass
$ sudo yum install -y ansible
$ ansible --version
```
##apt(deb)を利用したインストール　Ubuntu16.04LTS環境下など

```
$ sudo apt-get -y install software-properities-common
$ sudo apt-add-repository -y ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get -y install ansible
$ ansible --version
```

### virtualenvやpipを用いたAnsibleのインストール、Virtualenvの仕組み。
virtualenvとは、同一のPythonのバージョンで異なる仮想環境を管理し、用途に応じ、Pythonを切り替えるためのツール。

```
$ virtualenv 【環境名】 #Pyhton環境の作成
$ source 【環境名】/bin/activate　#virtualenvの有効化
$ （環境名）$ python -c "help('modules')" #仮想環境
$ （環境名）$ deactivate
```
## pipを利用したAnsibleのインストール

```
$ curl -kL "https://boostrap.pypa.io/get-pip.py" |sudo python
$ sudo pip install virtualenv
$ cd $HOME/
$ virtualenv venv 
$ souce $HOME/venv/bin/activate
（venv）$ pip install ansible
 (venv)$ ansible --version
```

*Ansibleのインストールを行ったあとはvirtualenvを有効化してから利用する

##ansibleコマンド、「プレイブック」やイベントリの活用法について。

Ansibleを利用して自動化を図るためには、イベントリとプレイブックの定義が基本となっている。特に大規模環境では、グループを使い分けてターゲットのノードを分類します。
プレイブックは、タスクを定義するYAMLファイルです。

＊プレイブックの応用について。１つのプレイブックで多くのタスクを定義すると、
プレイブックの管理が煩雑になるために、それを定義しているのがロール(Role)です
ロールはプレイブックを分割するコンポーネントであり、TaskやVarsセクションを別の
ファイルに分けて管理する仕組みとなっています。

## CI ツールとの連携
継続的インテグレーションは、アプリケーションレイヤーで実装されていた手法ですが、インフラリソースのクラウド化やAPI化によって、インフラ側でも活用されるようになった。

中でも「Jenkins」は幅広いスクリプトジョブの実行やトリガーが多く登録できるため多くの
環境で利用されている。またCIツールがジョブを実行するには、イベントジョブと定期ジョブの２つがあり、定期ジョブではcronなどが時刻取得に活用されている。
GCEにPython使った感情分析環境を構築してみる

リアルタイムで構築中なので進み次第更新

###最終目標
GCEに環境作って、PHPからPython叩いて結果をJSON出力する

###とりあえずGCEにLAMP環境作る
とりあえず適当なLAMP環境をデプロイ
今回使ったのは **LAMP Certified by Bitnami　**

###Pythonインストールしたい
```$ sudo apt-get install python3.7```
するとパッケージ見つからないと出ちゃうので
[この辺](https://linuxize.com/post/how-to-install-python-3-7-on-debian-9/)を参考にビルドインストールを現在進行中
Laravelのwithメソッドへの制約（whereなど）の付け方集


## 基本

### 1つのリレーションのとき

hoge -> fugaというリレーションの場合を考えます。

Hogeクラスにリレーションを追加しておきます。

```php:Hoge.php

//...

public function fuga()
{
    return $this->hasMany('App\Fuga');
}
```

withでfugaに制約を付与しつつ取得するには以下のようにします。

```php
Hoge::with(['fuga' => function ($q) {
    $q->where('id', 2);
}]);
```

### 複数のリレーションのとき

hoge -> fuga
hoge -> fuga1
hoge -> fuga2

hogeがいろんなリレーションを持っていて制約をつけつつ全部取ってきたいときは、単純に連想配列でしていしてあげればOKです。制約がいらないやつは書かなければ大丈夫です。

※hogeクラスに適切なリレーションメソッドを追加しているとします。


```php
Hoge::with([
    'fuga' => function ($q) {$q->where('id', 2);},
    'fuga1' => function ($q) {$q->where('name', 'fugatyan');},
    'fuga2'
]);
```

上記の例だと`fuga`と`fuga1`には制約を付与して、`fuga2`はすべて取ってくるという意味になります。

### ネストしているとき

hoge -> fuga -> piyo

ネストしたリレーションを一気に取ってきたいときはドット記法を使います。

※リレーションメソッドは適切に設定してあるものとします。

```php
Hoge::with(['fuga.piyo' => function ($q) {
    $q->where('id', '>', 5);
}]);
```

さて、上記の例での制約はどのように付与されるでしょうか。

正解は`piyo`にだけ制約が付与され、そのほかには制約は付与されません。最後のリレーションにだけ付与されるのです。

では、`fuga`に制約を付与したいときはどうすればよいでしょう。二通りのパターンを紹介します。

#### いっぱい書く

※`function`書くのが~~めんどくさい~~ので`$closure`に制約を表すクロージャを代入しているとして見てください。

```php
Hoge::with([
    'fuga' => $fugaClosure,
    'fuga.piyo' => $piyoClosure
]);
```

このように書くことで`fuga`と`piyo` に別々の制約を付与することができます。

ただこの書き方だと`fuga`が重複しているしわかりにくいですね。

#### リレーションメソッドを定義する

あらかじめ制約を付与したリレーションメソッドを定義して、それをwithで使ってあげれば個人的に見やすいかなと思います。


```php:Hoge.php
public function fuga()
{
    return $this->hasMany('App\Fuga');
}

public function goodFuga()
{
    return $this->fuga()->where('name',  'good');
}
```

```php:Fuga.php
public function piyo()
{
    return $this->hasMany('App\Piyo');
}

public function badPiyo()
{
    return $this->piyo()->where('name', 'bad');
}
```

```php
Hoge::with('goodFuga.badPiyo')->get():
```
scrapy-selenium

# scrapy-seleniumって何？

Scrapy用のダウンローダーミドルウェア。巷によくある、Scrapy+seleniumと同じ。

Scrapyのドキュメント(Scrapy 1.7 document)に載っているので使ってみた。

本家は https://github.com/clemfromspace/scrapy-selenium

# ウチだけ？

ドキュメントには

SELENIUM_DRIVER_ARGUMENTS=['-headless']  # '--headless' if using chrome instead of firefox

とあるが、firefox(69.0.2)(geckodriver 0.25.0 (bdb64cf16b68 2019-09-10))では上記コメントにも関わらず、SELENIUM_DRIVER_ARGUMENTSを設定する必要があった。

README.mdの訳に訳注追加。

https://gist.github.com/kuma35/37d0c6c80af7d5d0e1d01edce30027f1#file-readme-jp-md
ESLintのglobパターンがマッチしない問題の対処

# ESLintで再帰的なファイルマッチが動かない

以下のように、いくつかの深さを持ったJavaScript、もしくはTypeScriptファイルに対してESLintを再帰的に適用させる場合、globパターン(`**`)を利用してファイルマッチさせるかと思います。

```
src
 |--index.js
 |--app
 |   |--app.js
 |   |--util
 |       |--hoge.js
 |       |--data
 |           |--fuga.js
```

そこで、 `package.json` には以下のように script を定義します。

```package.json
"scripts": {
  "lint": "eslint src/**/*.js"
}
```

しかし、この script を実行しても1つのファイルからしかエラーが検出されません。

```sh
$ yarn lint
yarn run v1.13.0
$ eslint src/**/*.js

eslint-test/src/app/app.js
  1:1  error  Unexpected console statement  no-console

✖ 1 problem (1 error, 0 warnings)
```

# 対処法

実はglobパターンを利用してファイルを再帰的にマッチさせるには、シングルクォーテーションで囲んであげる必要があります。

```package.json
"scripts": {
  "lint": "eslint 'src/**/*.js'"
}
```

こうすると、全てのファイルからエラーが検出されるようになります。

```sh
$ yarn lint
yarn run v1.13.0
warning package.json: No license field
$ eslint 'src/**/*.js'

root/src/app/app.js
  1:1  error  Unexpected console statement  no-console

root/src/app/util/data/fuga.js
  1:1  error  Unexpected console statement  no-console

root/src/app/util/hoge.js
  1:1  error  Unexpected console statement  no-console

root/src/index.js
  1:1  error  Unexpected console statement  no-console

✖ 4 problems (4 errors, 0 warnings)
```

やったね 😊

# 補足
なぜこのように動作するのかコメントで指摘いただいたので、その点を記載します。

`scripts` に記述したコマンドは `bin/sh` によって実行されます。そこでGlobにマッチしたファイルリストを列挙してESLintに渡すことになるのですが、シングルクォートで囲むことによってGlobの解釈自体がESLintで行われるようになります。そのため、意図した通りのファイルがマッチして動作するようになっています。 (私の環境のシェルでは `/**/*.js` をフォルダ構造でマッチさせていたため、意図したファイルリストがESLintに渡されなかった模様)
なお、Windows環境では `scripts` コマンドの実行に `cmd.exe` を使いますが、 `cmd.exe` ではシングルクォートを引数として正しく認識しません。そのため、ダブルクォートを使用する必要があります。

※ この動作/検証は ESLint 6.5.1 で確認しています

# 参考
[ESLint 5.1.0 - No files matching the pattern for several repos](https://github.com/eslint/eslint/issues/10599)
Xcode11にて Module compiled with Swift 5.0.1 cannot be imported by the Swift 5.1 compiler エラーが出た時の対処法

# はじめに
Xcode11にて以下のエラーが出た際の対処法

```
Module compiled with Swift 5.0.1 cannot be imported by the Swift 5.1 compiler
```

## 解決策
Carthage（カーセッジ）を使用してワークスペースの更新を行えばエラーは解消されます。
以下のコマンドのみです。

```bash
$ carthage update
```

Carthageが古ければCarthageの更新を

```bash
$ brew upgrade carthage
```
【Unity】プライバシー ポリシーの設定【Google Play】

Google Playでリリースしようとしたらエラーが出たので、
メモ代わりに解決方法を記載。

■エラー内容
アプリの APK（バージョン コード 1）で権限 
android.permission.READ_PHONE_STATE,android.permission.GET_ACCOUNTS が使用されています。アプリの APK でこの権限を使用するには、プライバシー ポリシーの設定が必要となります。

プライバシーポリシーの設定が必要な模様。


■プライバシーポリシーの記載場所
Google Play Consoleのストア掲載情報にURLの記入欄がある。てかよく見たらプライバシーポリシーの横に「*」がある。必須項目だったのか。。。どうやら2018年あたりからプライバシーポリシーが必須になっている模様。

URLって、アプリ以外も作らないとダメじゃん。アプリ作ってリリースするだけかと思ったのにどうしてこうなった。pdfのドキュメントを作成して公開してる人もいるけど、webサイト作って公開しようか。

プライバシーポリシーって何かと思ったら、個人情報の取り扱いについて記載するのね。フリーのホームページでも作ってプライバシーポリシーのページを設けよう。


■ホームページ作成（無料）
とりあえずWixでさくっと作ろうと思う。昔なんか触ったことあるような気がする。
https://ja.wix.com

無料だったら閉鎖しなければなんでもいいし、自社や自分HPをすでに持っていたらそこにページ追加でもいいかもね。私が前もっていたホームページは閉鎖しちゃってるから、Wixで適当に用意するよ。

■urlの登録
Google Play Consoleのストア掲載情報にURLを入力して問題なければエラーが消えます。エラーが残っている場合は、Googleの指示に従って修正しましょう。

■プライバシーポリシーの例
Google Playに登録してみたプライバシーポリシーはこちら。リリース対象が世界なので、英文になっています。必要があれば都度修正。
https://shimizuworkscompan.wixsite.com/privacypolicy

登録後は緑のチェックが付いたので、何らかのチェック処理が走ってOKになったのだろう。urlだけをチェックしたのかもしれないが。


まだまだ他のエラーが残っていて、全然リリースまでこぎつけない(T_T)
VirtualBox上のvimから抜けられなくなった話

# VirtualBox上のviから抜けられなくなった

## 背景
teratermからssh接続できなかったので、VirtualBox上でsshd_configいじっていたところ。。

## 事象
いつもの感覚で **:q!** しようとしたら

```
E20: Mark not set
```
と出て何やっても抜けられない

## 原因

キーボード配列がUSになってた

USでの **:** = shift + ;

## 再発防止

### Linux上のキーボード+Locale設定

言語設定を日本語にする

```
[root@cent7 xorg.conf.d]# localectl set-locale LANG=ja_JP.utf8
```

キーボードを日本語にする

```
[root@cent7 xorg.conf.d]# localectl set-keymap jp106
[root@cent7 xorg.conf.d]# localectl set-keymap jp-OADG109A
````

### 管理ファイル実体
#### 00-keyboard.conf
```
vi /etc/X11/xorg.conf.d/00-keyboard.conf

# Read and parsed by systemd-localed. It's probably wise not to edit this file
# manually too freely.
Section "InputClass"
        Identifier "system-keyboard"
        MatchIsKeyboard "on"
        Option "XkbLayout" "jp"
        Option "XkbModel" "jp106"
        Option "XkbOptions" "terminate:ctrl_alt_bksp"
EndSection
```

## 参考
[【 localectl 】 システムのロケールやキーボードレイアウトを管理する 【 Linuxコマンドまとめ 】](https://linuxfan.info/localectl)
<meta name="viewport">

```html
<meta name="viewport">
```

このタグはブラウザがページを新しく開いた時に初期 viewport をどう設定するべきか指定する．viewport とはコンテンツをレイアウトするときに使用される想定表示サイズである．

単純に考えると，ブラウザのウィンドウサイズ=viewport サイズであり，実際，歴史的に両者は区別されていなかった．しかし近年はブラウザの実表示サイズとは別の viewport を設定することが可能である．両者にギャップがある時，コンテンツは拡大縮小表示される．

viewport が導入された動機は，デスクトップ用にデザインされたコンテンツを，モバイルの小さな画面に収めるためである．

表示幅 800px 程度を想定したデスクトップ用コンテンツを直接幅 400px 程度のモバイル機で表示するとレイアウトが崩れる．そこでモバイル版ブラウザは画面サイズと独立な viewport サイズを導入し，一旦コンテンツを viewport サイズに対してレンダリングしてから，画面サイズに合わせて拡大縮小するようにした．例えば safari は横幅 980px がビューポートのデフォルトサイズで，特に指定がなければコンテンツは一旦横幅 980 px でレンダリングされ，その後画面サイズに合わせて縮小される．

実際の表示サイズとビューポートサイズが違う，というのは余計な複雑さである．デスクトップ用コンテンツをモバイルの画面に収めるための工夫であり，コンテンツがはじめからモバイル用にデザインされているのであれば viewport サイズをわける必要はない．モバイルデバイス上でブラウザの画面サイズをそのままビューポートにしたければ，明示的にデフォルトの設定を上書きする必要がある．その指定が以下である．

```html
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```

参考
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
https://drafts.csswg.org/css-device-adapt/#viewport-meta
噛み砕くC#(ラムダ式、for文)の考え方

当時Javaのテストでたまに間違えててこれが出来なければプログラミング思考じゃない！
と言われ続けてたのを思い出しC#にしてアウトプット。


#Q,1,2,3に何が出力されるか

```C#
public static void Main(string[] args){
         int[] nums=new int[10];
         for(int i=0;i<nums.Length;i++){
           nums[i]=i/2; 
         }//0,0,1,1,2,2,3,3,4,4
         int sum=0;
         int index=0;
         for(;index<nums.Length;index++){
           sum+=nums[index];
           if(sum > 10){
           break;
           }
         }
         Console.WriteLine(index); //１
        
         int[] data={3,5,8,1,2};
         var result=data.Where(n=>n%2==0).Select(n=>n*n).Sum();
         Console.WriteLine(result); //2
         data.OrderByDescending(n=>n).ToList().ForEach(Console.Write); //3
```
##補足1

Javaとの違い

```C#
public static void Main(string[] args){ //mainでString

nums.Length //length

```
##考え方

１二つ目のfor文で配列numの値をインデックス0から順に足していき、その合計が10を超えたときのインデックス番号を返してます。
２はラムダ式ではありますがクエリ文をヒントに偶数の数値の乗算を合計するだけ。
３はリストに格納してForEachメソッドで降順に出力する。

<details><summary>回答</summary><div>

１は0,0,1,1,2,2,3,3,4,4なので
回答：7
 
2は8*8=64 2*2=4なので 
回答：集合体の合計68

3は85321(カンマなし）
</div></details>

他にもJavaになりますがダイヤを表示せよとかピラミッドを表示させよとか・・
Google AIY Vision Kitを3Dプリンタで作ったケースに入れて携帯できるAIカメラ化する

![IMG_20191010_003713.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354086/8cf892f9-243b-fac9-482d-08b41f50987f.jpeg)




#初めに
[Google AIY Project Vision Kit](https://aiyprojects.withgoogle.com/vision)はディープラーニング推論に特化した専用プロセッサである[Movidius](https://www.movidius.com/)と[Raspberry Pi Zero W](https://www.raspberrypi.org/products/raspberry-pi-zero-w/)が搭載されているキットです。あらかじめパソコンなどで学習したモデルをこのキット上で動かすことができます。ちなみに2019年10月現在、[M5StickV](https://docs.m5stack.com/#/en/core/m5stickv)が最も手軽なAIカメラとなります。しかしRaspberry Piが搭載されているGoogle AIY Project Vision Kitではアプリケーションを組むことも可能です。Google AIY Project Vision Kitのほうが設計柔軟性は高いということができるでしょう。
今回は3Dプリンタでケースを作り、リチウムイオンバッテリーを搭載することにより、出先でもAIカメラの使用をできるようにしました。

#利用する部材
| 種別       |       部材 |    URL    |
|:-----------------|:------------------|:------------------|
| AIカメラ             |　Google AIY Project Vision Kit　| https://raspberry-pi.ksyic.com/main/index/pdp.id/444/pdp.open/444        |
| リチウムイオンバッテリー             |18650　　|        |
| ヒートシンク(RaspberryPiとMovidiusの冷却用)            |　1.5 x 1.5 x 0.8　cmのヒートシンク 　|https://www.amazon.co.jp/gp/product/B00BL8VQDA/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1|
| リチウムイオンバッテリーの充電回路             |　　| https://www.amazon.co.jp/gp/product/B07MW6JJF5/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&psc=1       |
| 3Dプリンタ             |adventurer3　| http://flashforge.co.jp/adventurer3/       |

#作成するにあたっての参考資料
- Raspberry Pi Zero Wへの電源供給は[Raspberry Pi Zero用の小型電源とUSB WiFiモジュール用USBコネクタを自作する](https://karaage.hatenadiary.jp/entry/2016/09/16/073000)を参照。TP（Test Point）のPP1が5V、PP6がGNDです。

#背面画像
![IMG_20191010_003725.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354086/d67f1700-b9ad-41c2-8962-d74de1a9a987.jpeg)
![IMG_20191010_003921.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354086/ba4ed351-dbd8-458e-56f4-c918cdc19b43.jpeg)
.Net Core 2.2 Web APIでCamel式&インデントなしでレスポンスを返したい

.Net Core 2.2 Web APIでCamel式&インデントなしでレスポンスを返したい場合、
Startupで設定を変更すればよい


```csharp
public class Startup
{
    // 省略

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddMvc()
            .AddJsonOptions(options=> {
                options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.None; // インデントなし
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // Camel形式
    });
```
【Rails入門】.inspect を使用したデバック方法

##1.`@reservations`の中身を確認したい！


```ruby:app/controllers/reservations_controller.rb
def edit
	@reservation = Reservation.new
end
```


##2. 答え：`inspect（直訳：調べる）`を使用する
```erb:app/views/reservations/edit.html.erb

<%= @reservation.inspect %>
```

##3. 実際のビューページに出力された情報

```
#<Reservation id: nil, reserved_at: nil, reservation_type: nil, name: "", age: nil, address: "", tel_no: "", email: "", contact: "", deleted_at: nil, created_at: nil, updated_at: nil>
```
nuxt https対応

# nuxt https対応
#### 参考
[https://ja.nuxtjs.org/api/configuration-server/](https://ja.nuxtjs.org/api/configuration-server/)

## nuxt.config.jsを設定
```
import path from 'path'
import fs from 'fs'

export default {
  server: {
    port: 3000,
    host: '0.0.0.0',
    https: {
      key: fs.readFileSync(path.resolve(__dirname, 'server/mysslserver.key')),
      cert: fs.readFileSync(path.resolve(__dirname, 'server/mysslserver.crt'))
    }
  }
}
```

## 鍵の作成
[参考](https://qiita.com/crawd4274/items/19950cf4b96dbe5e1d6c)

```
mkdir server
cd server
penssl genrsa 2048 > mysslserver.key
openssl req -new -key mysslserver.key -subj "/C=JP/ST=Tokyo-to/L=Shibuya/O=Company Name/OU=IT dept./CN=Company Dept CA" > mysslserver.csr
openssl x509 -days 3650 -req -signkey mysslserver.key < mysslserver.csr > mysslserver.crt
openssl pkcs12 -export -inkey mysslserver.key -in mysslserver.crt > mysslserver.pfx
```
[SwiftUI] フィードバックのUIに使うポップアップを作ってみる 

![Untitled.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8358/8a1c2b8d-0961-a76e-a909-f1130701518d.gif)

フィードバックするためのUIであるポップアップはSwiftUIでどのように作るのが良いのでしょうか？
作るだけ作れたので共有します。

## まずは表示するポップアップ自体のコンポーネントを作成

```swift
struct MyPopup: View {
  
  var body: some View {
    Text("Hello!")
      .foregroundColor(.white)
      .padding(16)
      .background(Color.pink)
      .cornerRadius(8)
  }
}
```

## extensionを作る

次にポップアップを表示させたい画面から表示処理を呼び出せるようにView protocolにExtensionを作ります。

```swift
extension View {
  
  func popup<Content: View>(isPresented: Binding<Bool>, content: () -> Content) -> some View {
    
    if isPresented.wrappedValue {
      DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        isPresented.wrappedValue = false
      }
    }
        
    return ZStack {
      self
      
      content()
        .opacity(isPresented.wrappedValue ? 1 : 0)
        .scaleEffect(isPresented.wrappedValue ? 1 : 0)
        .animation(.spring(response: 0.2, dampingFraction: 0.6, blendDuration: 0))
    }
  }
}
```

画面の上に表示したいので、ZStackで包みます。

自動で閉じるようにするために isPresentedがtrueになったらDispatchQueueを使って1秒後にBinding経由でisPresentedをfalseに戻します。


---

## 最後に表示する画面の作成

```swift
struct ContentView: View {
  
  @State var isPresented = false
  
  var body: some View {
    VStack {

      ...

      Button(action: {
        self.isPresented = true
      }) {
        Text("Show")
      }
    }
    .popup(isPresented: $isPresented) {
      MyPopup()
    }
  }
}
```

## 感想

こんな感じでいいんだっけ？という印象
n秒後に閉じるという処理はStateをどうやって制御していくのが良いのでしょうか？

React,Vueの世界ではどうやっているのかがヒントになりそう。
同様にStateなのか、CSSアニメーションで完結してしまっているのか。などなど。
imgurからランダムに画像を取得する with python3 requests

# 目的
機械学習に使うために、ランダムな画像をたくさん集めたかったのが始まりです。

# 概要
imgurの画像、大体圧縮リンクがhttps://i.imgur.com/XXXXX[.jpg | .png]になってるようです。
じゃああとはお分かりですね。5文字のランダムな英数字(大文字・小文字・数字)からなる文字列を作成し、画像を取得すればいいだけです。

数回に1回はremoved.pngにリダイレクトされてしまうので、そうなったらやり直しです。

# 実装
```python
# 再帰による実装
def get_imgur_url(length: int, start: str = None) -> str:
    if length <= 0:  # エラー処理
        return ''

    buffer = random.choice(string.ascii_letters + string.digits)
    buffer = start + buffer if start else buffer
    
    if length <= 1:  # 再帰の末尾
        return 'https://i.imgur.com/' + buffer + random.choice(['.png', '.jpg'])
    
    return get_imgur_url(length-1, buffer)


# これも再帰
def get_imgur_random(count: int):
    if count <= 0:
        # 再帰の末尾
        return

    url = get_imgur_url(5)
    ext = url.split('.')[-1].rstrip('/')  # 拡張子
    resp = requests.get(url)  # 画像の取得

    if resp.history:  # historyが存在すればリダイレクトされてるってこと
        return get_imgur_random(count)

    binary = resp.content
    resp.close()

    with open(f'./imgur_images/{uuid.uuid4()}.{ext}', 'wb') as f:
        f.write(binary)
    
    return get_imgur_random(count - 1)  # 再帰


if __name__ == '__main__':
    get_imgur_random(10)

```
【Rails入門】bundle installとbundle install --path vendor/bundleの違い

違いを忘れそうなので簡単にまとめます。

##1. bundle installとは
`bundle install`は、システム領域にインストールされるため、複数のRailsアプリを同一のマシン上で運用していると問題が発生することがある。

##2. bundle install --path vendor/bundle とは
`bundle install --path vendor/bundle`は、アプリ専用領域のため、他のアプリに影響がない。

####■ bundle install --path vendor/bundle の中の 「vendor」とは
 「vendor」とは、自分が開発しているものではないサードパティーのライブラリを入れるとろ。
ちなみに、「lib」は真逆で、自分が開発した共通のライブラリのようなもの。

##3. なぜ bundle install --path vendor/bundle を使うのか
gemを任意のディレクトリにインストールし、gemをRailsプロジェクト毎に管理するため。

##4. 参考リンク
気になった記事があれば、随時追加します。
 
* [bundle install時に--path vendor/bundleを付ける必要性は本当にあるのか、もう一度よく考えてみよう](https://qiita.com/jnchito/items/99b1dbea1767a5095d85)
* [bundle install --path vendor/bundleと、bundle listとgem listの違いについて](https://qiita.com/okuramasafumi/items/1aea3ed27763315328a3)
【Flutter】Android版のflutter run --releaseが"The Gradle failure may have been because of AndroidX incompatibilities in this Flutter app."で失敗する

# 背景
FlutterのAndroid版アプリを`flutter run --release`で本番ビルドして実行してみたところ、下記のエラーが発生してビルドに失敗しました。

```
*******************************************************************************************
The Gradle failure may have been because of AndroidX incompatibilities in this Flutter app.
See https://goo.gl/CP92wY for more information on the problem and how to fix it.
*******************************************************************************************
Gradle task assembleRelease failed with exit code 1
```

# 対応
Gradleのバージョンを`5.1.1`から`5.4.1`にアップデートし、GradlePluginのバージョンを`3.4.2`から`3.5.1`にアップデーとしたところ、解決することができました。

```gradle-wrapper.properties
# BEFORE
#Sat Aug 10 14:03:52 JST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

# AFTER
#Wed Oct 09 23:43:37 JST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
```

```build.gradle
// BEFORE
dependencies {
  classpath 'com.android.tools.build:gradle:3.4.2'
}

// AFTER
dependencies {
  classpath 'com.android.tools.build:gradle:3.5.1'
}
```

# 備考
エラー内容がAndroidXのマイグレートについて言及していたため最初はAndroidX関連を疑いましたが、すでにマイグレートをしていたため試しに一度Gradleのバージョンを上げてみたところ解決に至りました。
参考になれば幸いです。

# 追記
上記対応を行なったところ、`flutter build appbundle`が`Gradle build failed to produce an Android bundle package.`で失敗するようになりました。
こちらのエラーはFlutterのチャンネルをstableからmasterに変更することで解決しました。

# 参考
https://github.com/flutter/flutter/issues/40445
masterチャンネルに変更することで事象が回避できることが記載されています。
8x8のドットマトリクスで温度/湿度/気圧をスクロール表示する。

#使用した部材

| 種別      |       部材 |    URL   |
|:-----------------|:------------------|:------------------|
|8x8ドットマトリクス            | 赤色ドットマトリクスＬＥＤ　８×８ドット| http://akizukidenshi.com/catalog/g/gI-05163/   |
|Arduino            | ArduinoArduino Uno| http://akizukidenshi.com/catalog/g/gM-07385/  |
|抵抗           | 100Ω×8| http://akizukidenshi.com/catalog/g/gM-07385/  |
|温度/湿度/気圧センサー          | BME280 | http://akizukidenshi.com/catalog/g/gK-09421/　|

#作り方
ドットマトリクスを用いた配線は[Arduinoを使って8X8マトリクスLEDに日本語テキスト文字を表示する](https://bokunimo.net/arduino/matrix_led.html)を参照。
BMEの配線は[マスタリングWireライブラリ　その4　温度/湿度/気圧センサBME280 接続](https://www.denshi.club/cookbook/master/wire/wire4bme280.html)を参照。
BMEはI2CとSPIの通信方式を選べます。扱い方については[Arduino NanoとBME280を使って温度・湿度・気圧を計測する](https://qiita.com/nanase/items/f34e03c29410add9c4d0)を参照。

ソースコードは下記にアップしました。
https://github.com/MypaceEngine/dotmatrix_temp/
【Rails/javascript(jQuery)】非同期での投稿削除機能

前回、編集機能の非同期化について記載させていただきましたが、今回は削除機能の非同期化について記事を書かせていただきます。

それでは、まず動画をご覧ください。
![alt](https://gyazo.com/97b730fd12429634e50d379b3760dc34/raw)

Deleteボタンを押すと、削除するかどうかの確認のアラートが出て、さらにアラートのOKボタンを押すと、きちんと削除処理がされていることが確認できますね。（正確にはこの動画だとちゃんと非同期になっているかわからないと思いますが、、）

削除処理の非同期化については、編集処理の非同期化に比べると、記述量も少なく、HTMLを入れ込む必要もないので楽でしたが、いくつか個人的にポイントだと思った箇所がありましたので記載します。

＜削除機能実装におけるポイント＞
①削除機能の場合、jbilderのファイルやコントローラへのjson.formatの記載は不要
②削除ボタンを押した際のアラートをどのようなビューにするか

①については、当たり前といえば当たり前ですが、これまでの非同期化では、jbuilderとjson.formatをセットで使用していたので、自分は勢いでふたつとも作成してしまいました、、。
ただ、冷静に考えれば、削除処理の場合、動的な情報が入ったHTMLを新たに作成するわけではありませんし、DBから返してもらうデータはないのでいずれも必要ありませんね。
また、削除処理については、基本的に警告表示は必要だと思いますが、アラートをどのようなビューにするのかによってサイトの印象が変わってしまうので、今回は一番簡単なalertメソッドをそのまま使用しましたが、サイトの印象を重視するなら非同期でHTMLを作成するのもありかもしれません。

ということで、以下コードを記載しますので、皆さまの何かのお役に立てば幸いです。

```javascript:blog_destroy.js
$(function() {
  $(document).on("click", ".delete_id", function (e) {
    e.preventDefault();
    var deleteMessage = confirm('削除してよろしいでしょうか？');
    if(deleteMessage == true) {
      var blog_element = $(this).parents('.content');
      var blog_id = blog_element.attr("data-blog-id");
      var url = location.href + "/" + blog_id;
    $.ajax({
      url: url,
      type: "POST",
      data: {'id': blog_id,
      '_method': 'DELETE'} ,
      dataType: 'json'
    })
    .done(function(data) {
      blog_element.remove();
    })

    .fail(function() {
      alert('blog destroy error');
    })
  }
  });
}); 

```

```haml:index.html.haml
= render partial: 'devise/shared/header'
.contents
  -@blogs.each do|blog|
    .content{"data-blog-id": "#{blog.id}"}
      .content__messages
        .content__message
          .content__message__box{"data-edit-id": "#{blog.id}"}
            - if blog.content.present?
              %p.lower-message__content
                = blog.content
          .content__message__info
            %p.message__upper-info__talker
              ユーザ：
              = blog.user.name
            %p.message__upper-info__date
              投稿日時：
              = blog.created_at.strftime("%Y/%m/%d %H:%M")
          
          .content__message__edit-and-delete-btn
            %p.edit_id
              Edit

            %p.delete_id
              Delete

      .pict
        =image_tag blog.image.url, class: 'pict__img' if blog.image.present?

= render partial: 'devise/shared/footer'
```
Ubuntu18.04インストール後にする色々な設定

Ubuntu18.04をインストールした後にやっておく設定。
順次追加していく！

## ブラウザ

chrome
https://www.google.com/intl/ja_jp/chrome/

## ランチャー

MacでいうところのAlfred的なやつを導入

albert

```
sudo apt install curl
curl https://build.opensuse.org/projects/home:manuelschneid3r/public_key | sudo apt-key add -
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/manuelschneid3r/xUbuntu_18.04/ /' > /etc/apt/sources.list.d/home:manuelschneid3r.list"
sudo apt install albert
```

## CapsLockをCtrlにする

```
sudo vi /etc/default/keyboard
XKBOPTIONS="ctrl:nocaps"
```

## 左Altで英字、右Altでひらがな入力できるようにする

```
sudo apt install fcitx-mozc
```

https://kledgeb.blogspot.com/2018/04/ubuntu-unity-1804-13-fcitx-mozc.html
https://qiita.com/ys-0-sy/items/b969c3224f97a0002829

## キーリピートの設定

良い感じに設定

- 設定
    - ユニバーサルアクセス
        - タイピング
            - リピートキー

## ターミナルを整える

Tilix

```
sudo add-apt-repository ppa:webupd8team/terminix
sudo apt-get update
sudo apt-get install tilix
```

https://qiita.com/pagu_o28/items/b6ee642b14f43820748b

## Tweaksを導入

```
sudo apt install gnome-tweaks
```

- フォントを 1.5 倍にする
- emacs入力をONにする

## エディタ

Emacs

```
sudo add-apt-repository ppa:kelleyk/emacs
sudo apt install emacs26
```

Vscode
https://code.visualstudio.com/

## dotfiles

自分のGithubからdotfilesリポジトリをclone
初期設定をする

## 通知管理アプリ

Rambox
https://rambox.pro/#ce

- Slack
- Gmail
- Googleカレンダー

などを設定

## DBのGUIクライアント

- dbeaver
  - https://dbeaver.io/
- table plus(linux版がついに)
  - https://tableplus.com/linux

## Themeを変える

Qogirを入れる
（McMojave なるThemeもあるよ）

### ①themeファイル群とiconファイル群をダウンロード

- theme
    - https://www.gnome-look.org/p/1230631/
    - filesタブからダウンロードする
    - dark系themeはアプリによっては表示がいまいちなのでlight系themeを入れる
- icon
    - https://www.pling.com/p/1296407/
    - filesタブからダウンロードする


### ②theme、iconを置くディレクトリを作る

```
mkdir ~/.themes ~/.icons
```

### ③解凍して作成したディレクトリ配下に置く

※ `index.theme` が入っているディレクトリを置くこと

### ④Tweaksを再起動して外観を設定する

- 拡張機能で `User Themes` をONにする
- 外観で、アプリケーション、アイコン、GNOME_SHELLを `Qogir` に設定する

## 中クリックで貼り付けできないようにする

https://www.virment.com/thinkpad-ubuntu-how-to-disable-middle-button-paste/
PDFBoxを使って既存のPDF文書に線を引く

[PDFBox](https://pdfbox.apache.org/) を使って既存のPDF文書に対して線を書き込みたいというニッチなニーズがあったので、その方法を紹介します。例えば、行政に提出する様式で、申請内容に応じて関係のない部分に取り消し線を引くといったケースを想定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33668/7a460197-8273-c1ef-1e79-e5139e75f90b.png)

### 確認環境

* PDFBox 2.0.15
* AdoptOpenJDK 11.0.3+7
* macOS 10.14.6

### 実現方法

* PDPageContentStream を初期化するときに AppendMode.APPEND を指定してあげるのがポイント
    * デフォルトだと AppendMode.OVERWRITE なので、元の内容がクリアされて真っ白な背景になってしまう
* PDF の座標系はページの左下が (0, 0) で右上に向かって大きくなる
    * 描画位置の特定方法は後述

```java
void line() throws IOException {
    try (InputStream is = getInputStream("sample.pdf");
         PDDocument doc = PDDocument.load(is)) {

        PDPage page = doc.getPage(0);
        PDPageContentStream contents = new PDPageContentStream(doc, page, AppendMode.APPEND, false);

        contents.moveTo(290f, 808f); // 始点座標
        contents.lineTo(365f, 808f); // 終点座標
        contents.setLineWidth(1f);   // 線の太さ
        contents.stroke();           // 描画

        contents.moveTo(290f, 805f); // 始点座標
        contents.lineTo(365f, 805f); // 終点座標
        contents.setLineWidth(1f);   // 線の太さ
        contents.stroke();           // 描画

        contents.close();
        doc.save("/tmp/output.pdf");
    }
}
```

### 描画位置の特定

適切なツールを使うとかもっと賢い方法がありそうですが、分からなかったので泥臭く自分で座標系を描画してあげることにします。

```java
void grid() throws IOException {
    try (InputStream is = getInputStream("sample.pdf");
         PDDocument doc = PDDocument.load(is)) {
        PDPage page = doc.getPage(0);

        // ページ左下から右上に向かって格子線を引く
        PDPageContentStream contents = new PDPageContentStream(doc, page, AppendMode.APPEND, false);
        PDRectangle bbox = page.getBBox();
        for (float x = 0; x < bbox.getWidth(); x += 10) {
            contents.moveTo(bbox.getLowerLeftX() + x, bbox.getLowerLeftY());
            contents.lineTo(bbox.getLowerLeftX() + x, bbox.getUpperRightY());
            contents.setLineWidth((x % 100 == 0) ? 2f : 0.5f);
            contents.stroke();
        }
        for (float y = 0; y < bbox.getHeight(); y += 10) {
            contents.moveTo(bbox.getLowerLeftX(), bbox.getLowerLeftY() + y);
            contents.lineTo(bbox.getUpperRightX(), bbox.getLowerLeftY() + y);
            contents.setLineWidth((y % 100 == 0) ? 2f : 0.5f);
            contents.stroke();
        }
        contents.close();

        doc.save("/tmp/output.pdf");
    }
}
```

あとは左下から目盛りを数えてやれば、描画したい位置の大まかな座標を特定できるというわけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33668/c5dd74e9-5a20-1da3-2684-a1a07a4b7857.png)

もっと良い方法があれば、ぜひ教えて下さい :sweat_smile:
MacOS で Consolas フォントを使う方法

Microsoftに入っているConsolasフォントをMacOSでも使いたい。

# 必要なもの

Homebrew

# 手順

ターミナルを開き、以下のコマンドを順にタイプすればOK

```
brew install cabextract
cd ~/Downloads
mkdir Consolas
cd Consolas
curl -LO https://sourceforge.net/projects/mscorefonts2/files/cabs/PowerPointViewer.exe
cabextract PowerPointViewer.exe
cabextract ppviewer.cab
open CONSOLA*.TTF
```
【ajax】JQueryで共通パーツをページ内に読み込みたい

##開始タグ
今回は趣向を変えて現在の実務で行ったことを書いてみます。
初めて経験したので少しでも詰まっている誰かのためになればと思います。

##使用するきっかけ
普段はphpでのインクルードする場合がメイン。
ですがお客様のサーバーがPHPを使用できず、SSI・DWのライブラリ運用はお互い避けたいということで、Javascriptでの共通パーツ運用を行うことになりました。

##方法
今回は「ajax」を使用してページ内へ読み込みました。

※最初はJQueryの「.load」を使用していましたが、上手くいかなかったので破棄。

１、まず、共通パーツ化したい箇所を、新たに作成したhtmlファイルに記述します。

２、次にJSファイルに以下の記述を行います。（今回はheader.htmlを読み込む場合です。）

```javascript:sample.js
	$.ajaxSetup({
		type: "POST",
		dataType: "html",
		timeout: 11000,
		cache: false
		}
	});

	$.ajax({
		url: "/common/inc/header.html",
		success: function(data) {
			$("#header").html($(data));
		}
	});
```

`$.ajaxSetup`内で、ajaxの初期共通設定を行いますよー、
`#header`に読み込みますよー、てな感じ。

ここで大切なのは`cache: false`。
例えばheaderのハンバーガーメニューなど共通パーツの中でJSを扱う場合、JSが効かない現象が起こるので設定しておくといいです。（IE個性的すぎるよ・・・）

IEのajaxに関する仕様で、一度キャッシュされると次回以降もキャッシュが残った状態で表示されてしまうので、JSが効かなくなるのだとか・・・。

※上記のコードの前は省略形で書くパターンでしたが、IE11だとエラーが出てしまうので正式な書き方がベターです。

##alert("問題発生！");
それでもajaxで読み込んでいる共通パーツ部分のJSが効かない・・・ということであれば、以下を試してください。

```javascript:sample.js
$(window).on("load", function() {
  // 処理内容
});
```
これを使用することで、画像など含めページが完全に表示された状態＝ajaxが実行された後に処理を行うので、JSが効くようになります。

と、これで一件落着かと思いきや、clickイベントの場合は動かない・・・という状況もあるでしょう。（というか自分なりました。）
その場合は以下のように記述してあげてください。
```javascriot:sample.js
$(document).on("click", "要素やid、class名", function() {
});
```
このように記述してあげると、バッチリJSが動くようになります。（自分はなりました！）

##閉じタグ
というわけで、ざっくり言えば「細かく書く」「読み込み順」に気をつけてあげればajaxを使用してページ内へ共通パーツを読み込むのはできちゃいます。
軽微なものではありますが、「やってみる」って大事ですよね。
DebianでNginxをインストールする

本日はNginxというWebサーバーをダウンロードしました！
初めてWeb上に自分のHTMLが表示されたのを見たときは、感動しました( ͡° ͜ʖ ͡°)
見辛いかもしれませんが、工程をまとめたのでシェアします(_ _)

##DebianでNginxをインストールする

sudo apt install nginx

### パッケージの公開鍵をダウンロードしてapt-keyで追加する
wget “http://nginx.org/keys/nginx_signing.key”

sudo apt-key add nginx_signing.key

### nginxのサイトをリポジトリに追加する.
sudo vi /etc/apt/sources.list

### 開いたファイルに以下を追加.
deb http://nginx.org/packages/debian/ squeeze nginx

deb-src http://nginx.org/packages/debian/ squeeze nginx

###後は登録を反映して,
sudo apt-get update

### OSのターミナルから
telnet localhost 80

Escape character is
が表示されたら
GET / HTTP/1.0

これでhtmlのタグ等が表示されたらnginxは起動している。

##自分のhtmlを表示させる
###まず設定ファイルを見る

sudo vi /etc/nginx/nginx.conf
を見ると
include /etc/nginx/sites-enabled/*;
がある

この行で
/etc/nginx/sites-enabled/default
を読んでいるのでそちらを見る

sudo vi /etc/nginx/sites-enabled/default

そちらを見ると

root /var/www/html;
とあるので
ls /var/www/html←ここにhtmlファイルを置けばいいことがわかる。

## HTMLファイルの作り方、移動の仕方
$ vi ファイル名
でファイルを作り

$ mv ファイル名　/var/www/html
でファイルに階層を変える

これでアドレスを検索エンジンで入力すると先ほど追加したファイルが読まれる

### ※一応アンインストールのやり方も載せておきます
sudo apt-get remove nginx
shibboleth 証明書の更新

# shibboleth
用語

学術認証フェデレーション「学認（GakuNin）」 日本のアカデミック関係の統合サインオンの事業。NIIが運営。仕組みとして Shibbolethを用いる。
Shibboleth アカデミックのデファクトSAML。SAMLとはシングルサインオン規格のひとつ。クラウドベース、XMLベース、オープン実装が存在するなどの特徴がある。
IdP（ID Provider）サインオン時の認証サーバ。Shibbolethの場合、１つのアカデミック組織に最低１つ。
SP（Service Provider） Webなどでサービスを提供するサーバ。


以下のような環境で証明書を更新した。

- Shibboleth の秘密鍵と証明書は Web サーバのSSL秘密鍵と証明書を共用
- 旧い Debian サーバに https 上で Webサービスが動作している
- Webサービスは Shibboleth 認証を使用している
- Webサービスは組織内運用のみ、学術認証フェデレーションへのサービス公開は無し。
- 証明書期限切れに伴う更新作業



既に証明書期限切れなので、入れ替えるだけの簡単作業。

# 証明書を作る

鍵長2048bitで秘密鍵を作成

```

$ openssl genrsa -des3 -rand randfile1.txt:randfile2.txt:randfile3.txt 2048 -out > host.key
```
この作業で一旦 pass phrase を入力する。
この key ファイルから、以下のコマンドで組織情報などを入力し、CSR ファイルを作成する。


```

openssl req -new sha256 --key host.key -out host.csr
```

組織情報の入力方法は偉い人に従う。

今回のSPの証明書は UPKI 電子証明書発行サービスを利用することが決まっているので、TSV に添付して申請する

TSV: タブ区切りデータ形式。 CSV: カンマ区切りデータ形式。TSVはCSVのタブ区切り版。

UPKIへの申請は指定書式のTSVデータを用いて行うが、それについてはTSVデータ作成ツールを用いる。 
TSVデータ作成ツール → https://certs.nii.ac.jp/tsv-tool/create/

作成したTSVファイルをサーバ設置機関の登録担当者に提出。証明書が発行されるのを待つ（１日〜数日）。

証明書が発行されたら取得し、該当サーバにserver.crtという名前で設置。



今回、中間CA証明書も更新しないといけないので以下から取得
https://repo1.secomtrust.net/sppca/nii/odca3/index.html
nii-odca3sha2.cerという名前で該当サーバに設置。


# httpsサーバ再起動

必要なファイルが配置できたら以下のようにしてサーバ再起動


```

/etc/init.d/apache2 resatart

```

エラーが出たので下記を参考にして


https://rougeref.hatenablog.com/entry/20180613/1528869737

pass phrase を抜いた CSR ファイルを作る。

```

openssl rsa -in host.key -out host.key
```

もう一度webサーバ再起動

```

/etc/init.d/apache2 resatart
```

ブラウザで見てサーバ証明書エラーが解消できていればOK.

# Shibboleth の更新

WebサーバのSSL証明書を流用して、メタデータを作成する。

http://federation.belnet.be/node/24
を参考に、以下のようにしてmetadata.xmlを作成する

```

shib-metagen -c server.crt -h hoge.hage.fuga-u.ac.jp > metaadata.xml
```

できたメタデータを、IdP管理担当者に送る。IdPメタデータを更新してもらう。


## shibd の設定

新しいIdPメタデータを受領してサーバに設置、

/etc/apache2/mods-avairable/shibbolethを編集して証明書およびIdPメタデータを読み込むように設定します。

今回の機関ではIdPメタデータはWebで参照でき、SP上のshibdがこれを参照するようにする仕組みがありましたがこれを使わず静的にファイルを参照するようにしました。


# 参考資料

ここを読んでおけばいい気がする
https://webclass.jp/documents/system-admin/shibboleth-sp

証明書発行サービスのサイト
https://certs.nii.ac.jp/join/

事前準備 ～ 証明書の申請から取得まで
https://meatwiki.nii.ac.jp/confluence/pages/viewpage.action?pageId=26188809

Apache(mod_ssl)編
https://meatwiki.nii.ac.jp/confluence/pages/viewpage.action?pageId=26192324