OmniAICreator/Qiita-1.07M huggingface dataset:
Laravelで明確配列タイプをする

すみませんが、日本語訳はあとにします。
### The origin code
```php
public function get_user_badge(array $user_ids, array $course_ids, Carbon $from, Carbon $end, $direction = 'desc'){}
```

### Refactoring 1: clarify array type
##### Util Classes
```php
use Illuminate\Support\Collection;

class IntegerCollection extends Collection
{
	public function __construct(int ...$values)
	{
		parent::__construct($values);
	}
}

class UserIds extends IntegerCollection {}
class CourseIds extends IntegerCollection {}
```

##### The code will rewrite as bellow:
```php
public function get_user_badge(UserIds $userIds, CourseIds $courseIds, Carbon $from, Carbon $end, $direction = 'desc'){}

// Usage
$userIds = new UserIds($user_ids);
$courseIds  = new CourseIds($course_ids);
get_user_badge($userIds, $courseIds, ...)
```

### Refactoring 2: Combine $from/$end to InclusiveRange class

##### Util Classes
```php
	abstract class BaseRange
{
	public $begin;
	public $end;

	public function __construct(Carbon $begin, Carbon $end)
	{
		$this->begin = $begin;
		$this->end = $end;
	}

	//...some ultil functions in here
}


class InclusiveRange extends BaseRange{}
```
##### The code will rewrite as bellow:

```php
public function get_user_badge(UserIds $userIds, CourseIds $courseIds, InclusiveRange $range, $direction = 'desc'){}

// Usage
$inclusiveRange = new InclusiveRange($from, $end)
get_user_badge($userIds, $courseIds, $inclusiveRange...)
```
Original post is: https://khoinv.com/post/639390454460432384/clarify-type-in-laravel-code
DjangoでDateTimeFieldの書式を変換する方法 

##Djangoにて取得した日付をフォーマットして表示させたい
Djangoのmodels.pyにて
datetime.now()でなくtimezone.now()を使用する際、

    date = models.DateTimeField('日付',default=timezone.now())

とすると書式は
<b>2020-12-08 21:12:24.333404+00:00</b>
のようになる。

Webアプリケーション上で<b>12/08/20</b>のようにあらわしたいとき

    date = models.DateTimeField(datetime.now().strftime('%m%d%y %H:%M'))

としてしまうと、

    ValidationError [u"'12/08/2020' value has an invalid date format. It must be in YYYY-MM-DD format."]

というエラーが表示される。


###解決方法


htmlで取得した日付を表示する際に、下記のようにしてフォーマットを指定できる。

    <div>{{ item.ans_date|date:"m/d/y H:i" }}</div>

この場合は、<b>"01/01/20 02:41"</b> のように表示される。

その他、12h表記だったり先頭に0を追加しない、年号を4桁表示などしたい場合は以下のページを参考されたし。
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#date

それでは、良いDjangoライフを！
Laravel6以降のbootstrapの導入方法

Laravel6以降はbootstrapを手動で導入する必要がある。

#ターミナルでコマンドを打つ手順

```
composer require laravel/ui 1.*
```

```
php artisan ui bootstrap
```

```
npm install && npm run dev
```

この順にコマンドを打っていく。
[JavaScript] Promise.all() の使いかた

Promise.all()は`Promiseオブジェクトを要素に持つ配列`を引数にとり、すべてのPromiseオブエジェクトが解決するまで処理を待つ。

```JavaScript
Promise.all([promise1, promise2, promise3]).then((value)=> {
  // すべてのpromiseが解決した後に行う処理
  // value = [promise1の結果, promise2の結果, promise3の結果]
});
```

map()メソッドやpush()メソッドと組み合わせて使う例

```JavaScript
// Promiseを要素に持つ配列を作る
const promises = array.map((a) => {
  // Promiseオブジェクトをreturnする
});

// 配列にPromiseを追加する
promises.push(/*他のPromiseオブジェクト*/)

Promise.all(promise).then((value)=> {
  // すべてのPromiseが解決した後に行う処理
});
```
【mongoDB】Mongooseのpopulateメソッドでハマった話


下記の様なDriverモデルがPositionモデルを所有している。

```m_driver.js
"use strict";

const mongoose = require("mongoose");
const Position = require("./m_position.js");
const Schema = mongoose.Schema;

const driverSchema = Schema({
  name: {
    type: String,
  position: { 
    type: Schema.Types.ObjectId, //外部キー
    ref: "Position" //参照モデル
  }
});

module.exports = mongoose.model("Driver", driverSchema);
```

```m_position.js
"use strict";

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const positionSchema = Schema({
  longitude_k_x: Number,
  latitude_i_y: Number,
  driver: {
    type: Schema.Types.ObjectId, //外部キー
    ref: "Driver" //参照モデル
  }
});

module.exports = mongoose.model("Position", positionSchema);
```

今下記のようなデータがあります。

Positionモデルデータ

```js
{
  "_id":"5ff163eb514e011e79ccc284",
  "latitude_i_y":1,
  "longitude_k_x":1,
  "driver":"5ff163eb514e011e79ccc283",
  "__v":0
}
```

Driverモデルのデータ

```js
{
  "_id":"5ff163eb514e011e79ccc283",
  "name":"driverTaro",
  "position":"5ff163eb514e011e79ccc284",
  "__v":0
}
```
お互いに外部キーで結びついている状態です。

この状態で以下のようなpopulateメソッドを実施しました。

```js
position.findOne({ latitude_i_y: 1 })
  .populate("Driver")
    .exec((error, data) => {
       console.log(data);
       console.log(data.driver.name);
})
```
結果

```js
//console.log(data);
{
  _id: 5ff163eb514e011e79ccc284,
  latitude_i_y: 1,
  longitude_k_x: 1,
  driver: 5ff163eb514e011e79ccc283,
  __v: 0
}

//console.log(data.driver.name);
undefined
```
求める結果

```js
//console.log(data);
{
  _id: 5ff163eb514e011e79ccc284,
  latitude_i_y: 1,
  longitude_k_x: 1,
  driver: {
    _id: 5ff163eb514e011e79ccc283,
    name: 'driverTaro',
    position: 5ff163eb514e011e79ccc284,
    __v: 0
  },
  __v: 0
}

//console.log(data.driver.name);
driverTaro
````

ご覧の様に、driverモデルが紐づいて取得できませんでした。

結果として問題があった部分は、

```js
.populate("Driver")
```
populateメソッドの引数が原因でした。
populateメソッドには、**"モデル名"**を指定するものだと思い込んでいました。
しかし、実際は引数に指定するのは、**"外部キーに指定したkey"でした。
よって、今回であれば

```js
.populate("driver")
```
のように、キー名を引数に渡すことにより、求める結果か取得できました。

データーの保存方法に問題があるとばかり思い込んで、そちらを中心に調べたので、時間を要してしまいました。
結果として、公式のサンプルコードを見れば、すぐに解決する問題でした。

ハマった時は、発想を切り替えて、エラーの原因を調査することが大切ですね。

参考:
[mongoose official]
(https://mongoosejs.com/docs/populate.html#saving-refs)
Python BoxがBoxと重なっているかを求める関数

[ ymin,xmin, ymax, xmax ]という box1 と box2 があったとき

```python

def isOverlappingBox(box1,box2):
  ymin1=box1[0]
  xmin1=box1[1]
  ymax1=box1[2]
  xmax1=box1[3]

  ymin2=box2[0]
  xmin2=box2[1]
  ymax2=box2[2]
  xmax2=box2[3]

  if xmax1 >= xmin2 and xmax2 >= xmin1 and ymax1 >= ymin2 and ymax2 >= ymin1:
    return True #重なっている
  else:
    return False #重なっていない
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
うわ、急にローカルホストが動かなくなった時の話

皆さんこんにちは！！

今回はエラー解決備忘録として記事を書いていきます。

同じエラーに直面した人の力になれればなと思います！！！

Vue.jsでサイト制作を行っているところ、急に下記のようなエラーが発生しました。

``TypeError: Cannot read property 'process' of undefined   :index.js``

どうやら、router/index.jsのとあるプロパティが働いていないらしい。。。

```router/index.js
const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition;
    } else {
      return { x: 0, y: 0 };
    }
  },
});
```

こういうエラーって自分で考えても仕方ないから、とりあえずエラーメッセージをコピペして検索。

色んな解決策があるが、どれを試しても上手くいかない。。。

と、そこでとある記事を見つけた。

どうやら``.eslintrc.js``の設定にミスがあるかもしれない。

見てみると、、、

```.eslintrc.js
"env": {
    "browser": true,
    "es6": true
  },
```

この``browser``が原因らしい。

つい最近、Typescriptの勉強を始めたのでESLintの設定をそのままコピペしたせいかエラーが起きてしまった。

色々調べてみたが、これといった理由は分からない。分かる方がいたらぜひコメント欄にてお教え下さい！

この部分を以下のように修正。

```.eslintrc.js
"env": {
    "node": true,
    "es6": true
  },
```

これで動くようになりました！

なにか腑に落ちない感じがする。。。

以上、「うわ、急にローカルホストが動かなくなった時の話」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
bashで終了ステータスとシグナル名をプロンプトの上の行に表示してみた

こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54918/f9a9a495-21ab-7a4c-8df3-ddc1c5a8ca4a.png)

今まではよくある（？）やり方でプロンプトと同じ行に終了ステータスを表示していたのですが、よくよく考えてみるとわざわざ同じ行に表示させる必要ないよなーと気づいたのでプロンプトの上の行に表示させてみました。

```sh
__prompt_command() {
  local xs=$?
  [ "$xs" -eq 0 ] && return 0
  [ "$xs" -gt 127 ] && xs="$xs ($(kill -l "$xs" 2>/dev/null))"
  printf "\033[31mexit status: %s[0m\n" "$xs"
}
PROMPT_COMMAND=__prompt_command
```

プロンプトに表示させる場合は環境変数 `PS1` を設定しますが（それを使っても実現できるのですが）プロンプト表示前に出力させるので代わりに `PROMPT_COMMAND` を使ってプロンプト表示前に実行する関数を指定しています。これを `.bashrc` に追加すればOKです。

終了ステータスが 0 の場合は何も表示せず、終了ステータスが 128 以上の場合はシグナルである可能性が高いのでおまけでシグナル名（上記の例で言えば `INT` = `SIGINT`）も出力しています。表示されるのは上の行なので長くなってもじゃまにならないというメリットがあります。

蛇足ですが `kill -l 終了ステータス` でシグナル名に変換するのは POSIX 準拠の方法です。シグナル番号とシグナル名は環境によって異なることがあるため、このようにしないと正しいシグナル名は取得できません。終了ステータスを与えない `kill -l` でシグナル一覧を表示できるのはよく知られていると思いますが、シグナル番号からシグナル名に変換できることは意外と知られていないような気がします。なお bash では（`kill` は 多くの POSIX シェルでビルトインです。ビルトインでないのは知る限り posh のみです。）逆にシグナル名を与えるとシグナル番号が取得できますが、こちらは POSIX 準拠ではありません。（参考 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/kill.html）
【Unity for Mac】VSCodeでC# Extensionの設定

# UnityのScript EditorでVSCode

- C# Extensionが機能しない
- F12やCommand+クリックで関数の定義へジャンプしない

1. C#のエクステンションをインストールする（エクステンションショートカット：Command+Shift+X）
2. 設定を開く（設定ショートカット：Command+,）
3. Search settingsに「mono」とタイプすると、Extensionsの項目に「C# configuration」がヒットするので開く
4. 「Use Global Mono」の設定を「always」にする
5. 「Mono Path」の設定（Edit in settings.json）を開き、「omnisharp.monoPath」を入力する
6. VSCodeを再起動する

# omnisharp.monoPath の確認方法

ターミナルを開き以下のコマンドで確認する

```
which mono
```

# mono バージョンの確認方法

```
mono -V
```
PoEラズパイタワー　その２〜ネットワーク構築編〜

というわけで、前回準備した機材を使ってネットワーク構築を進めます。


#1. 無線LAN親機：WMR-433W2
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605817/fbb03c7e-21c2-4df3-d0d4-dabccfe5a134.jpeg" width=50%>
中身を取り出すとこんな感じ
ポーチとLANケーブル、USBケーブルが入っています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605817/631819f4-c1e2-a7f9-e75b-e7aa77c09b43.jpeg" width=50%>

電源入れる前に、自宅のWi-Fi環境に合わせて5GHｚ、2.4GHzを選んでおきましょう〜
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605817/014c29d7-ad55-ce2f-ccfc-94392983b5bc.jpeg" width=50%>

#設置・初期設定ガイドにそって設定します。
https://manual.buffalo.jp/buf-doc/35021754-01.pdf
<b>①本製品を設置・配線する</b>
　「無線LAN(ホテルなどの無線LANサービス)に接続する場合」を実施
<b>②インターネットに接続する</b>
　自身のPCに合わせて実施
　このときPCのIPはDHCPから拾うように設定しておくか、
　192.168.13.2〜192.168.13.254にしておきましょう。
　※今回はDHCP想定で書きます
　※192.168.13.1はWMR-433W2のIPで基本的に変更不可です。
<b>③インターネットに接続する（無線LANに接続する場合）を実施</b>
　設定が終わると再起動します。
　起動するまで時間がかかりますが
　<b>「再起動が完了しました」</b>
　が表示されるまでガマン

#動作確認
WMR-433W2の再起動がおわったら動作確認します。
PCのWi-FiがBuffalo-[A|G]-????に接続され、
IPが192.168.13.???(DHCPの場合はおそらく192.168.13.2)になっているのを確認して、
ブラウザ等でwww.yahoo.co.jpとかのページが開ければOKです。

#2. PoE Switch：TP-LINK TL-SG105PE
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605817/e103737d-2bc8-2d5d-1874-3ed3b19ca7cd.jpeg" width=50%>
ACアダプタが恐ろしくでかい。
XBOXのACアダプタをみて愕然したのがよみがえってきたｗ
このSwitch、前のページでも書いた通り、
いろいろな機能を持っており、その設定用に管理画面を持っています。
また、管理画面用IPはDHCPで取得されるため、
このIPがいちいち変動するのもイヤなので
管理画面用IPを固定化(192.168.13.200)します。

##2-1. 結線
　TL-SG105PEの電源を入れる前に、
　WMR-433W2に付属していたLANケーブルで
　起動中のWMR-433W2とTL-SG105PEの5番ポートをつないでおきます。
　これは、TL-SG105PEの管理画面用IPをWMR-433W2からDHCPで取得させるためです。
　はやまってWMR-433W2とTL-SG105PEをつなぐ前に
　TL-SG105PEの電源を入れてしまった場合は
　つないでからTL-SG105PEの電源を入れ直せばOKです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605817/bac4020a-aef7-9fd4-05fa-be7d4fcb89d0.jpeg" width=50%>

##2-2. 設定
　<b>・TL-SG105PEの電源を入れます</b>
　　この状態で
　　　192.168.13.1 WMR-433W2
　　　192.168.13.2 PC
　　　192.168.13.3 TL-SG105PE
　　となっているはずです。
　　PCをDHCPにせず、192.168.13.2以外に設定した場合は
　　TL-SG105PEに192.168.13.2が割り振られるかもしれません。

　<b>・ブラウザで管理画面にアクセスします</b>
　　http://192.168.13.3/ にアクセスするとこんな画面が出るはず。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605817/e81fa5c7-526f-2852-1b17-4b3bb97f45de.png" width=50%>
　　User NameとPasswordの初期値はどちらもadminですが
　　ログインするとパスワード変更を求められます。

　<b>・IP設定</b>
　　パスワード変更が終わったら、
　　左ペインのSystem→IP Settingを選び、
　　DHCP Disableとし、IPを192.168.13.200にします。（スクショ取り忘れたｗ）
　　設定後しばらくすると勝手に192.168.13.200にリダイレクトされます。
　　管理画面トップページに戻り、SystemInfoで
　　　IP Address 192.168.13.200
　　　Default Gateway　192.168.13.1
　　になっていればOKです。
　<b>・その他</b>
　　設定は上記で終了ですが、左ペインから探索して、
　　このスイッチで何ができるのか、一度みてみるのもいいでしょう。
　　また、念のためFirmwareもみてみたのですが、
　　機器のFirmは［20200415 Rel.55282］
　　下のページにあったのが[20200313-rel.38213]でしたので
　　そのままにしておきました。
　　https://www.tp-link.com/us/support/download/tl-sg105pe/

#今回はここまで〜
前の記事：<a href="https://qiita.com/_tanukichi_/items/5eeba82dc63a6961609f">PoEラズパイタワー　その1〜機材準備編〜</a>
次の記事：<a href="https://qiita.com/_tanukichi_/items/3a9c8e7bad665936efa4">PoEラズパイタワー　その3〜ラズパイタワー構築編〜</a>
LaravelでFormRequestを使ってバリデーションする方法

Controllerが肥大化（MVCの宿命）してしまうのを少しでも解決するために、バリデーションはFormRequestを使って処理するのが良さそうだったので、自分用のメモとして使い方をまとめてみた。

# FormRequestとは
バリデーションルールを外部クラス（FormRequestクラス）にまとめることができ、任意の処理で呼び出すことができる
FormRequestを下記のようにDIしてあげると、バリデーションが通った時だけコントローラー内の処理が走るようになります
このようにバリデーションを外部クラスで処理することでControllerでは自分の処理に専念することができる

```php
public function store(StoreRequest $request)
{
  // バリデーションが通ったときにここの処理が走る
}
```

# 使ってみる
`artisan`コマンドで作成できる

```bash
php artisan make:request StoreRequest
```

```php:StoreRequest.php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true; // デフォルトはfalse（アクセス権限を付けない場合はtrueにする）
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            // ここにバリデーションルールを書いていく
        ];
    }
}
```

## バリデーションルール

```php
    public function rules()
    {
        return [
           'title' => 'required|unique:posts|max:255',
           'body' => 'required',
        ];
    }
```
こんな感じで書く
## バリデーションエラー時のレスポンスをjsonに変更
デフォルトではレスポンスがHTMLのためAPI開発などでも扱いやすいようjsonに変更する
バリデーションエラー時に実行される`failedValidation `メソッドをオーバーライドする

```php
    protected function failedValidation(Validator $validator)
    {
        $res = response()->json([
            'status' => 400,
            'errors' => $validator->errors(),
        ],400);
        throw new HttpResponseException($res);
    }
```

## 他にも色々な機能がある
https://qiita.com/OKCH3COOH/items/53db8780027e5e11be82
Bootstrapざっくり入門 - 2

## グリッドシステム

### カラム（column : 列）とガター(gutter : 溝)
Bootstrapではページの幅を12列に分割したグリッドシステムを採用しています。
12列に分割されたグリッドの列をカラムと言い、各カラム間の余白をガターと言います。

### コンテナ(container : 箱)
グリッドシステムを使用してレイアウトする際、最初に使用するのがコンテナです。
コンテナは、コンテンツを入れる箱で、ページの水平中央にコンテンツを配置する役割を持っています。
コンテナには、固定幅コンテナと可変幅コンテナの2種類があります。

- 固定幅コンテナ
    - 画面サイズによってコンテンツの最大幅を切り替えることができます。
    - ウィンドウを拡大/縮小しても幅は固定です。
    - containerクラスを使います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310302/b84589f4-6fb2-6348-71b4-3577f62d7fc5.jpeg" width=100%>

```html
<div class="container">
    <!-- ここにコンテンツを入れる -->
</div>
```

- 可変幅コンテナ
    - 画面サイズ全幅に渡る流動的なコンテンツ幅を持たせることができます。
    - ウィンドウの拡大/縮小に伴い幅が可変（画面幅に対し、常に全幅）
    - container-fuildクラスを使います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310302/8f234520-a80f-99b7-381a-0e4875ff36a7.jpeg" width=100%>

```html
<div class="container-fluid">
    <!-- ここにコンテンツを入れる -->
</div>
```

### rowクラス(行)
コンテナ(箱)の中には、rowクラス(行)を入れます。
rowクラスは、一連のカラムを正しくレイアウトするために使用するクラスで、この中にカラムをまとめます。
複数行にしたいときは、containerの中にrowクラスを指定した要素を追加します。

```html
<div class="container">
    <div class="row"><!-- 1行目 -->
        <!-- ここにカラムを入れる -->
    </div>
    <div class="row"><!-- 2行目 -->
        <!-- ここにカラムを入れる -->
    </div>
</div>
```

### グリッドシステムの使い方
グリッドシステムは、一連のコンテナ(containerクラスまたはcontainer-fluidクラス)、行(rowクラス)、カラム(colクラス)を使用してコンテンツをレイアウトします。
基本構造は、コンテナ(containerクラスまたはcontainer-fluidクラス) > 行(rowクラス) > カラム(colクラス)となっています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310302/5eed226a-590d-ee1f-91dc-aca8b2a52186.png" width=100%>

```html
<div class="container">
    <div class="row"><!-- row : 行 -->
        <div class="col">1列目</div><!-- col : カラム -->
        <div class="col">2列目</div><!-- col : カラム -->
        <div class="col">2列目</div><!-- col : カラム -->
    </div>
</div>
```

## インデックス
<a href="https://qiita.com/mota__do/items/f3823fbc7bcee266f2c7">Bootstrapざっくり入門</a>
<a href="https://qiita.com/white_tiger/items/196ac2dff9dad8d993e8">Bootstrapざっくり入門 - 3</a>

## あとがき
随時更新していきます！
[備忘録] iCloud上のディレクトリをgit管理すると痛い目にあう話

# 絶対にiCloud上でコードを管理するな！！！
iCloud上のディレクトリをgit管理していると，以下のようにバージョンファイルが勝手に作成されてしまうことがある．これは，iCloud上で作業することで発生するので，iCloud上では作業しないようにしよう．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571510/35e3a5b9-4700-6184-9c34-3ced02e4546c.png" width="500">

# この問題の解決方法
もうすでに，バージョンファイルが作成されてしまっていることに気づかずにコミットしてしまった場合は，バージョンファイルをgitの管理対象から外す必要がある．そして，ついでにバージョンファイルも消す．
## 手順
1. iCloudからローカル環境に作業ディレクトリを移す．
2. ローカルに移動した作業ディレクトリでバージョンファイルを管理対象から消し，存在自体も消す．
3. コミットしてプッシュ

## バージョンファイルの削除について
インデックスにキャッシュされている（管理対象となっている）ファイル一覧は以下で取得できる．この中にバージョンファイルが入っていることを確認する．

```
git ls-files
```

上記のコマンドで出力されたファイルを一旦ファイル出力する．例えば以下のように．

```
git ls-files > ls-files.txt
```

出力したファイルの中から，バージョンファイルを抜き出し，バージョンファイルとオリジナルファイルの内容が同じであればバージョンファイルは心置きなく消していいことになる．内容が異なっている場合のみ，中身を確認して消すべきかそうでないかを確認する必要がある．
そのため，消しても良いファイル一覧を取得するプログラムを作成する．例えば以下のように．
（バージョンファイルは間にスペースがあるため少し面倒．ファイル出力するときに，一つのファイルとして表現するためにクォーティングする必要がある．）

```python:grouping.py

import re
from typing import Optional, Tuple
import filecmp

with open("ls-files.txt") as f:
    files = f.readlines()

pattern = r"(^.+)(\s[0-9]+)(.*$)"
pattern = re.compile(pattern)

def split_file_name(filename: str) -> Optional[Tuple[str, str, str]]:
    m = pattern.match(filename)
    if m is None:
        return None
    prefix, version, suffix = m.groups()
    return prefix, version, suffix

splited = [split_file_name(file) for file in files]

versioned = list(filter(lambda s: s is not None, splited))

versioned_dict = {}
for file in versioned:
    key = (file[0],file[2])
    if key not in versioned_dict:
        versioned_dict[key] = []
    versioned_dict[key].append(file)

# rm_files(消しても良いファイル達), save_dict（中身を確認するファイル達）の作成
rm_files = []
save_dict = {}

keys = versioned_dict.keys()
for key in keys:
    ori_file = "".join(key)
    for sp in versioned_dict[key]:
        ver_file = "".join(sp)
        
        # ファイルの比較
        if filecmp.cmp(ori_file, ver_file):
            rm_files.append(ver_file)
        else:
            if key not in save_dict:
                save_dict[key] = []
            save_dict[key].append(ver_file)

# 消しても良いファイル一覧をテキストファイルとして出力
with open("rm.txt", "w") as f:
    for file in rm_files:
        f.write('\"{}\"'.format(file) + " ")
```

上記のようなプログラムで消しても良いファイル一覧が取得できたら，それらのファイルをgit管理対象から外し，存在自体も削除する．以下のように．

```
eval git rm $(cat rm.txt)
```
<!--
~~cat を使うとファイルの中身全てが一つの文字列として認識されてしまうので，evalが必要．~~
-->
shellの解釈の順番の都合によりevalが必要.
CheckBoxFieldクラス

#CheckBoxFieldクラスとは
GridViewコントロールは，フィールドの表示，編集を行います。詳細にカスタマイズするためクラスが用意されており，CheckBoxFieldクラスは，データに基づいチェックボックスを出力します。チェックボックスはチェック状態と非チェック状態の2つの状態だけを表しますので，CheckBoxFieldクラスで表示できるのは，Boolean型(SQL Sever上ではbit型)の値，または，Boolean型に変換できる文字列型のみです。データがTrueであればチェック状態，Falseであれば非チェック状態のチェックボックスを表示します。また，デフォルトでは編集時には変更不可の状態のチェックボックスを表示します。

#例
```html:GridViewSample.aspx
<asp:CheckBoxField DataField="Sex" HeaderText="性別"/>
```

#プロパティ
以下のようなプロパティがあります。

|プロパティ|意味|
|---|---|
|DataField|出力するフィールド名|
|Text|チェックボックスに表示する文字列|
|ReadOnly|編集時に値を編集不可にするかどうか。デフォルトはTrue|

##参考文献
TECHNICAL MASTER はじめてのASP.NET Webフォームアプリ開発 VisualBasic対応 第２版
アドベントカレンダー31日目：SREを読んでみた「オンコール対応」編②

オンコール対応の2回目です。
今日は、オンコール対応は、エンジニアにストレスを与えやすいものですが、それを以下に取り除いていくか、生じさせないようにしていくかを見ていきます。

## 安心感
SREエンジニアがオンコール対応を行うということは、ユーザーの収益に直接関係するシステムのインフラに責任を持つということです。
人は困難に直面した時、直感的かつ反射的に即行動しようとするか、理性的かつ集中を保ち、慎重に行動しようとするかのどちらかの行動をとることが多いです。

複雑なサービス障害を扱う場合には、後者のマインドセットの方が良い結果をもたらしやすいです。
そのため、オンコール対応をするエンジニアが後者のマインドでいられるようにすることが重要です。

サービスの重要度や影響範囲、障害が発生した場合の結果はオンコールエンジニアに非常にストレスを与えます。強いストレスは、認知機能の低下をもたらし、軽率な行動を起こさせやすくします。
また、同じアラートが4回連続発行された時、人は経験則に頼り、それぞれのアラートの原因を自動的に以前の原因と同じものとみなしたくなります。
素早いリアクションは、週間に基づくものなので、考慮が足りずに問題を起こす可能性が増大します。

インシデント管理の理想的な方法は、妥当な判断を下せるだけのデータを揃えたうえで望ましいペースで手順が行われることと並行してその推定を批判的に分析することでバランスをとることです。

また、以下のようなオンコールリソースを確保することでオンコール対応の負担を軽くすることができます。

* 明確なエスカレーションパス
* しっかりと規定されたインシデント管理の手順
* 非難を伴わないポストモーテム文化

## まとめ
* オンコール対応の際には、理性的で慎重なマインドセットであることが重要
* オンコールリソースを確保する

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　134-136
Bootstrapざっくり入門

## Bootstrapとは
レスポンシブWebデザインを採用した HTML, CSS, JavaScript フレームワークです。

### レスポンシブWebデザイン
レスポンシブWebデザインはフルードグリッド、フルードイメージ、メディアクエリなどの技術で構成されています。

- フルードグリッド
    - グリッドシステムによるWebデザインとブラウザ幅の変化に応じて内容の大きさを変えるリキッドレイアウトを組み合わせた手法をフルードグリッドと言います。

- フルードイメージ
    - レイアウト幅に応じて、画像サイズを拡大縮小させるテクニックをフルードイメージと言います。

- メディアクエリ
    - 画面幅、画像解像度、デバイスの向きなどの条件に合わせて、スタイルを切り替えることができるCSS3から導入された技術です。

### Bootstrapの導入
CDN、パッケージマネージャ、ダウンロードなど様々な方法で導入することができます。
詳しくは<a href="https://getbootstrap.jp">Bootstrap公式サイト</a>を参照してください。

#### Bootstrap4の基本テンプレート
```html
<!doctype html>
<html lang="ja">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
  </body>
</html>
```  

## インデックス
<a href="https://qiita.com/mota__do/items/b394eed6c8de47e1661a">Bootstrapざっくり入門 - 2</a>
<a href="https://qiita.com/white_tiger/items/196ac2dff9dad8d993e8">Bootstrapざっくり入門 - 3</a>

## あとがき
Bootstrapについてざっくりとまとめています。
どうか暖かい目で見守ってください。
(*´･ω･`)ﾉ 夜露死苦 ヽ(´･ω･`*)
Amazon S3 Glacier とは

## 勉強前イメージ

s3と似たようなやつ
違うサービスなの？
s3はよく使われるデータ置く感じで、Glacierはほぼ使わないアーカイブの用途のイメージ
ストレージクラスとまた違うのかな？

## 調査

### Amazon S3 Glacier とは

Glacier グレイシアと呼び、
s3とは元々別サービスでAmazon Glacierというものがありましたが、
Glacierのデータがほぼs3のライフサイクルポリシーから移動してきたものであったため、
現在はs3のストレージクラスのひとつです。

> Q: Amazon Glacierはなぜ今はAmazon S3 Glacierと呼ばれているのですか?
> 長い間、バックアップおよびアーカイブストレージサービスである Amazon Glacier は、Amazon S3 のストレージクラスのひとつだと思われてきました。事実、現在 Amazon Glacier に保存されているデータのかなりの部分が、あまり使用しないデータを Amazon Glacier に移動する S3 ライフサイクルポリシーを使用しているお客様から直接送られてきたものです。本日、Amazon Glacier は正式に S3 の一部となり、Amazon S3 Glacier (以下、S3 Glacier) となったことを発表します。すべての既存の Glacier ダイレクト API は今までどおり機能し続けますが、S3 API を使用した S3 Glacier ストレージクラスへのデータの保存はさらに簡単に行えるようになりました。

ですが、Amazon S3 Glacier単体でも使用できます。
Amazon S3 Glacier自体はバックアップやアーカイブのために開発された、セキュアかつ堅牢性の高いストレージです。
データを取り出すのに時間がかかるため、上記で書いたバックアップやアーカイブのようなアクセス頻度の低いデータ保存に向いています。

### Amazon S3 Glacier の特徴

#### 低コスト

Glacierは、従量課金制のストレージサービスです。
初期費用も不要で費用も1GB 約1円/月 と低コストです

#### 高い耐久性

データの耐久性がS3と同様に99.999999999%となっており、リージョン内の複数の拠点へ自動で複製保存されています。

### S3との違い

- 構成要素の違い

Glacierは `Archive` と `Vault` によって構成されています。
Archiveはデータのまとまりで1つのファイルだったり、複数のファイルをtarで固めたファイルをアップロードしたり出来ます
VaultはArchiveをまとめてグループ化することができ、自分で作成しArchiveを移動したり出来ます。
Vault単位でIAMの権限を設定することも出来ます

![glacierUntitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f9b8e63f-a051-f0ea-b7db-36b0923916dd.png)


- ファイルの取り出し

s3ではデータをすぐに取り出すことが出来ますが、Glacierは取り出すのに時間がかかります。
S3 Glacierでは1,2分、S3 Glacier Deep Archiveでは標準で12時間ほどかかります

## 勉強後イメージ

s3と別サービスなのか同じなのかよくわからんかったけど...
`元々別サービスだったけど、s3からのデータがほとんどだからs3に組み込んだよ！別サービスでも使えるよ！` ってことか。
あんまり単体で使うことはないのかな？

## 参考

- [「Amazon S3 Glacierのよくある質問」](https://aws.amazon.com/jp/glacier/faqs/?nc=sn&loc=6)
- [AWS のストレージサービスの違い](https://hacknote.jp/archives/57019/)
- [Amazon S3 ストレージクラス](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/storage-class-intro.html)
- [Amazon S3とAmazon Glacier両者の違いとは？](https://www.acrovision.jp/service/aws/?p=1646)
- [Amazon Glacierを使ってデータの長期間保存を始める](https://dev.classmethod.jp/articles/amazon-glacier-start/)
- [Amazon Glacier編～Glacierとは？～](https://recipe.kc-cloud.jp/archives/1142)
- [Amazon Glacier編～GlacierとAmazon S3との比較～](https://recipe.kc-cloud.jp/archives/1179)
- [AWSのGlacierとは？その読み方と概要について](https://www.acrovision.jp/service/aws/?p=1741)
TerraformでJsonに変数を埋める

関数を使う方法とdata sourceを使う方法があります

まず、Jsonの中では `${hoge}` の形式で指定しておきます
例えば

```json
{
  "region": "${region}"
}
```

# 関数を使う方法

参考: [templatefile function](https://www.terraform.io/docs/configuration/functions/templatefile.html)

```
templatefile(path, vars)
```
Jsonを読み取るときに `file` の代わりに `templatefile` を使用します

```terraform
= templatefile("path/to/foo.json", { hoge = var.fuga })
```

# data source を使う方法

参考: [template_file](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file)

```terraform
data "template_file" "bar" {
  template = file("path/to/foo.json")
  vars = {
    hoge = var.fuga
  }
}
```

その上で、Jsonを指定する箇所で

```terraform
= data.template_file.bar.rendered
```

と指定します

# どっちを使うべき？

>
In Terraform 0.12 and later, the templatefile function offers a built-in mechanism for rendering a template from a file. Use that function instead, unless you are using Terraform 0.11 or earlier.

とあるので、一つ目の関数を使いましょう
PHP学習備忘録 

去年の10月から新人プログラマとして開発に挑戦しています。
以前は運用系の業務だったため、自分で何かを作って動かすのはほぼ未経験です。
今までは、研修でJavaを覚えてきましたが、新たにPHPを覚えることになりそうなので、PHPについて色々調べてみました。
なかなか物覚えはよくない方なので、自身の備忘録としてここに残しておこうと思います。

#PHPについて

PHPとは正式名称は「Hypertext Preprocessor」と呼ばれているとのことです。
ハイパーテキストって書かれている通り、WEB開発で非常に使われている言語になっているようです。
（私はPHP初心者なのでまだ細かいことはわかりませんが…）
簡単にWEBサイトを作成できることでおなじみの「WordPress」もPHPがベースになっています。

#PHPの記述

PHPはHTMLの中に記述できます。拡張子は.phpとなります。
HTML内で記述する際はbodyタグの中に書きます。

HTML文書内に記述する場合、文頭は、<?phpとなり、
?>が締めとなります。
ただ、PHPだけで記述されたphpファイルは?>で締めないことが多いようです。
また、PHPは命令の最後にセミコロンを記述しないと、セミコロンが記述されるまでずっと一つの文として扱ってしまいます。

#PHPの構文

##出力

実際にPHPの構文を使って何か文字を出力します。
どんなプログラミング言語もまず初歩は、「HELLO WORLD」を画面に出力することから始まることが多いですね。
PHPでは出力に「echo」を使います。JavaでいうところのSystem.out,print()、C++でいうところの、coutみたいなものでしょうか。
おなじみのHELLO WORLDを出力したい場合、

```php:test.php
<body>
	<?php
   	echo "HELLO WORLD";
	?>
</body>
```

と記述します。文字の出力は、自分の知っている言語の中で一番シンプルに見えます。

```php:test.php
print "HELLO WORLD";
```

これでも記述できます。「print」はなじみ深い単語ですね。ただ文字列を出力するだけでも別解が色々あるんですね。

文字列の出力ができたら次は、条件文に行くことが多いイメージですが、
PHPの変数の書き方が独特だったので、まず変数について考えていきます。

##変数の扱い

PHPでは$を変数にしたい文字の頭につけます。PHPには型宣言がなんと無いそうな。
変数の命名規則は、文字列は先頭がアンダースコアかアルファベット、その後にアンダースコア、数字、アルファベットとなります
型宣言intだの、Stringだの考えなくていいのは少し楽に思えます。
ただし型宣言が不要なだけで、データ型自体はばっこしあります。(intとかbooleanとかいうアレ)
文字列を出力したい場合は、ダブルクォーテーション（シングルクォーテーションでも可）
で挟まないと文字列として認識されないことは注意が必要です。他の言語でも同様ですね。

```php:test.php
 $変数 = "test";
```
ちなみにデータ型を知りたいときは「var_dump」なるものがあります。

```php:test.php
 $変数 = "test";
 var_dump($変数);
```

こう書くと、$変数のデータ型を教えてくれます。この例で行くとString型になります。

また、値を変えたくない、つまり定数として扱い場合はdefineを使います。

```php:test.php
define("定数",値);
```

となります。不変の定数(円周率π、自然対数の底e、プランク定数?...etc)やいじりたくない数字、文字を扱うのにいいですね。
Javaでいうfinalみたいなイメージでしょうか。
ここまで、変数と定数について調べたので、次は繰り返し処理について調べてみました。

#繰り返し処理

PHPもほかのプログラミング言語と同様に、for文、while文などの繰り返し処理分が一通りあります。
やはり前述の二つはとりわけし開発初心者の私にとってなじみ深いので
ここからPHPの条件式に慣れていきたいです。

##for文
おなじみの繰り返し文ですね。
構文は次のようになります。

```php:test.php
for(初期化文;条件式;更新式){
//ループ処理
}
```

Javaとほぼ同じですね、違うといえば変数を扱う際に、変数の頭に$を付ける必要があることと、PHPなので
<?php
?>
で挟まなきゃいけないくらいでしょうか。
また、このままだと改行がされないので、nl2br("\n")なるものをつけると改行されます。
brは個人的に乱用したくないので、nl2br関数を使っていこうと思います。

```php.test.php
for($i=0; $i<=5; $i++){
	echo $i.nl2br("\n");
}
```

私はこれで改行ができていました。ちなみに繰り返し処理同様によく使われるwhile文
条件式、Javaなどの他のプログラミング言語とほぼ同じでしたので割愛します。

#配列
PHPの非常に簡単なルールがわかったところで、配列について調べてみます。
PHPでもそこまで配列の仕様はほかの言語は変わらないようです。

```php:test.php
$変数 = [値1, 値2, 値3, ...]
echo $変数[n]
```

これもそこまで難しくなさそうですね。やはりシンプルです。PHPが初心者向けってよく言われるのが何となくわかったような気がしないでもないです。
配列の中身の取り出し方も[]の中に取り出したい要素のインデックスナンバーを記述すればよいです。
例によって0から始まるので、配列の最初の要素を取り出すときは$値[0]となることに注意しましょう。

#関数
PHPでも関数は使うことができます。
複雑な処理をまとめて処理したい場合、もしくは単調だけど何度も書かなきゃいけない処理なんかは関数を使うとコードがすっきりして見やすくなりますね。

```php:test.php
function 関数名(){
//関数の処理内容
}
```

となります。これもほかの言語でよく見る形になりますね。
関数を呼び出すときは、関数名()を記述するだけでその処理を呼び出せます。
もちろん、
<?php
?>
内で記述しなきゃダメです。他のプログラミング言語にも言えることですが、何度も記述する必要のある処理は、関数にしてまとめてあげることで、単純に打ち間違いなども減らし、修正する時間を減らすことができるので、単純に生産性が向上すると思っています

#あとがき
Javaの勉強さることながら、新しくPHPも覚えていきゃなきゃならん！となったとき、ものすごく不安になりましたが、ふたを開けてみたら今まで見たきた言語に似ている部分も多く、むしろPHPでは記述がシンプルなもの多いように感じました。
まだまだ、基礎中の基礎しか勉強していないので勉強中の部分もあります。
これからも少しずつ、備忘録も兼ねてPHPの勉強内容を追記し、あとで見返したときに参考にできればと思う次第です。

以下に今回の学習、備忘録をまとめるにあたり、参考にさせていただいたサイトです。
https://www.kagoya.jp/howto/wordpress/php/
putsとprintの違い

Progateでpythonの勉強をし始めたら、「print」というのが出てきた。
python特有の物かと思ったら、Rubyでも普通にあるみたいで。。知らなかった・・！
自分用のメモとして記録しておく。

■主な違い
・改行するかしないか

puts→出力後改行
print→出力後改行しない
S2 Geometry Libraryを利用し、ある地点の緯度経度よりその地点を含むS2セルを求める方法

# S2 Geometry Libraryとは
* 地球を球面と見たときに**S2セル**と呼ばれる領域に分割していき、各セルに**cell ID**と呼ばれる値を割り当てるGoogleが2017年に出したジオメトリ系のライブラリです。[参照](http://s2geometry.io/)

# S2セルとは
* S2セルとは、地球の表面を特定の大きさで均等に分けたものです。
* 緯度経度のような点ではなく、面で位置を表します。
![スクリーンショット 2021-01-04 13.30.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/c9515147-36fb-4f21-1b63-9edfe0489804.png)

# S2セルのレベル
* S2セルにはレベルという概念があります。
* S2セルのレベルとは、レベルが大きいほど１つ１つのセルが細かくなります。
![スクリーンショット 2021-01-04 13.40.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/05724588-d58a-c353-3cbb-7cb0ff66e762.png)

# 実現方法
* 今回は、Go実装版があるので、そちらを利用する上での説明にしようと思います。[参考](https://github.com/golang/geo)
* 使用するfuncは「RegionCoverer」というものです。[参考](https://godoc.org/github.com/golang/geo/s2#NewRegionCoverer)

## RegionCoverer
* RegionCovererは、ある地図上に指定した図形に対して、その図形を確実に埋めるセルのリストを返すものです。
* また、特定の位置の緯度/経度から、上記に記載したある指定した半径の円を図形とし利用することができます。 **=> これがミソです。**

```type.go
type RegionCoverer struct {
    MinLevel  int  // 使用する最小セルレベル。
    MaxLevel  int  // 使用される最大セルレベル。
    LevelMod  int  // 使用するLevelMod。=> 指定しなくていいかもしれません。というより何を指しているのか今一つ分かりませんでした。
    MaxCells  int  // 必要なセルの最大数。
}
```

* ライブラリのドキュメントを見ると、使用例が以下のようになっています。

注目部分が**「r := s2.Region(CapFromCenterArea(center, area))」**
ここで、特定の位置を生成していることがわかります。
今回の場合ですと、初めに載せた記事のやり方と類似するはずなので、**CapFromCenterAngle**というfucを使用します。

```sample.go
rc := &s2.RegionCoverer{MaxLevel: 30, MaxCells: 5}
r := s2.Region(CapFromCenterArea(center, area))
covering := rc.Covering(r)
```

* 下記はRegionCoverを可視化し、わかりやすくしたツールです。[参考](https://s2.sidewalklabs.com/regioncoverer/?center=38.519539%2C-220.907732&zoom=6)

![スクリーンショット 2021-01-05 23.56.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/aec00b19-a9c3-fff2-a7a5-5274709b690d.png)

## 緯度/経度からある半径の円を生成する方法
### LatLngFromDegrees
* S2 Geometryでは、緯度経度をLatLngという1対の角度として表します。
* そのため、**LatLngFromDegrees**というfuncを使用し、緯度/経度の情報を１対の角度に変換します。[参考](https://godoc.org/github.com/golang/geo/s2#LatLngFromDegrees)

```type.go
type LatLng struct {
    Lat, Lng s1.Angle
}
```

### PointFromLatLng
* 後に出てくる、CapFromCenterAngleというfuncの引数に、LatLngではダメで、ポイントと呼ばれる値を引数で渡さないといけない。
* **PointFromLatLng**は、指定されたLatLngのポイントを返します。[参考](https://godoc.org/github.com/golang/geo/s2#PointFromLatLng)


### CapFromCenterAngle
* **CapFromCenterAngle**は、指定されたポイントと角度でキャップを作成します。[参考](https://godoc.org/github.com/golang/geo/s2#CapFromCenterAngle)

```sample.go
func CapFromCenterAngle(center Point, angle s1.Angle) Cap
```

* angleという引数なのですがこれは、キャップの頂点となる球面上の点と、キャップの縁の大円に対する比率です。
* ユースケースとして「渋谷駅を中心に半径4kmの円」を想定した場合には、 地球のサイズの球からの相対的な比率計算をする必要があります。
* ここで、仮に地球の半径を6371.01kmと置くと、半径4kmの円の比率は4/6371.0となります。
* そのため、地球上の円を作成するためには以下のようにする必要があります。

```sample.go
const earthRadius float64 = 6371.01
capOnEarth := s2.CapFromCenterAngle(center, s1.Angle(4/earthRadius))
```

#### キャップとは何か
S2で扱う円は、平面上の円とは違い、球の表面に沿って曲ったキャップのような形状になっています。 
そのため、S2では円はCapという型名です。

# 参考文献
* https://9db.jp/pokemongo/data/5227
* https://pokemongo-get.com/pokego01454/
* http://s2geometry.io/
* https://poketo7878-dev.hatenablog.com/entry/2017/08/02/100000
webpack-dev-server で Chrome DevTools にエラーが出る

webpack-dev-server で ```npm start``` したときに、Chrome DevTools でエラーが出る。

エラーメッセージ

```
DevTools failed to load SourceMap: Could not load content for webpack:///node_modules/sockjs-client/dist/sockjs.js.map: HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME
```

回避方法
webpack.config.js にパラメーターを設定する

```
module.exports = {
  devtool: "eval-source-map",
}

```
[devtoolパラメーターで利用可能な設定値の一覧](https://webpack.js.org/configuration/devtool/)
初めてアプリを作る時に役立つ知識5選

#はじめに
私は約2ヶ月前スクールに入り、Progateからプログラミング学習を始めた、
いわゆる「プログラミング初学者」です。

ですのでこの記事は経験者には当たり前すぎてつまらないかもしれません。。

「せっかくプログラミング勉強進めているし、アプリ作ってみたいな。けど初めて作るの不安だな」
という方がいたら是非読んでくれると嬉しいです。

かく言う私も、先日初めてアプリをリリースする前までは、
どう始めて良いのかわからず、不安でいっぱいでした。

ただ、幸い私は、スクール卒業生や運営の方に恵まれ、
たくさん相談に乗っていただいたおかげでなんとか完成させることが出来ました。

なので、そこで得た貴重なアドバイスや経験をここで共有することで、
少しでも初学者のお役に立てれば幸いです。

※ちなみに以下が私の作った（クソ）アプリなので、
良ければ遊んでください！
https://cryptic-retreat-09777.herokuapp.com/

※初学者なりの誤った記載がありましたら申し訳ありません。
 その際は是非教えて下さい！

#書くこと
・みんなに触ってもらうアプリを作る上での知恵。
・初めてアプリを作る上で役に立つプチ知識。

※書かないこと
・スクールで習うプログラミングの仕組みや書き方
　（私が説明できるはずがありません。。）

#①アプリは炎上させるくらいが良い
これは私が「作ったものがウケなかったらどうしよう。。」とウジウジしていた時に、大先生から頂いた言葉です。笑

考えてみれば、「全員に文句が出ないモノ」って結局は「面白くないもの」だったりしますよね。

周りに迷惑を掛ける類は良くないかもですが、
**「嫌いな人が出るくらいが、関心が持たれてる証拠！」**という考えに凄く共感しました。

万人ウケを想像すると怖くてアイディアが出づらいので、
まずは素直に自分が「面白い！これはウケる！」と思ったものを作るのはどうでしょうか。
（ちなみに私のアプリはお金臭すぎて妻に相当嫌がられました。笑）

#②「rand」メソッド
複雑なスキームを組み込めない初学者ほど是非オススメしたいのが、
###「アプリに運要素を入れる」
ことです。
なぜなら、違う結果が出るかもしれないと、ユーザーがリピートしてくれる可能性があるからです。

また、どんなに面白いゲームでも、よっぽど作り込んでいない限り、「攻略法」が見つかってしまいます。
そして絶対勝てる方法が見つかると人は飽きてしまいます。。

だから、流行るゲームには多少の**運要素**を入れていることが多いです。
（パズドラも最終的には「落ちコン」などの運が要りますよね。）

そんな運要素を初学者でも簡単に実現できるのが「rand」メソッド、
いわゆる**「乱数」**です。

randは指定した範囲の整数をランダムに返してくれるメソッドです。
例えば0から5までの整数をランダムに出したいときは、
```rand(5)
```と書く感じです。

**これがめちゃくちゃ汎用性高い。**

単純に出た数字を使って計算してもいいですし、
if文と組み合わせれば、
「○が出たらこの画面、○が出たらこの画面を表示させる」
などの場合分けが出来ます。

つまり、randを使いこなせば、自分の好きなように運要素をアプリに組み込むことが出来るのです！
（ちなみに私の作った投資ゲームは、各投資対象のボラティリティに合わせて乱数の範囲を設定し、その出た数字を掛け合わせることでアットランダムなグラフを生成しています。）

アプリのアイディアに困ったときは是非「運」に任せてみてはどうでしょうか。

#③CSSの色一覧
恥ずかしい限りですが、数日前の私はCSSで色を変えるだけでも苦労しました。

冷静に「#fff」が白とか覚えるの無茶じゃないですか？

当然のようにネットに色一覧が有りましたので共有しておきます。
もう色のコードを覚える必要はありません！笑
http://www.netyasun.com/home/color.html

ちなみにフォントやデザインも変えたい方は以下ご参考ください。
私の大先輩の記事ですが、正直、神がかってます。
https://qiita.com/aiandrox/items/4196c8f5b564d29fdce7

#④ココナラ
ロゴとかキャラクターを使いたくなった時、
ネットの画像を取ってくるのも怖いし出来れば自分好みのものが欲しいですよね？

私にはデザイナーの友達はいないので、どうやってロゴを作っているんだろうと先輩に聞いたら、
###どうやら「ココナラ」というアプリで作ってもらうらしい。。。

ココナラというのは日本最大級の「オンラインスキルマーケット」で、
サービスを求める発注者と得意分野を商品とする（今回で言うデザイン力）受注者をマッチングしてくれるサービスです。

経験も兼ねて早速キャラのイラストを発注してみましたが、
**正直めちゃくちゃ良かったです！**
私の頼んだ時期は年末年始の一番ダルい（笑）時期にも関わらず、こまめに連絡を下さり、相当な細かい注文をしたのにも関わらず、それを全てクリアした上でなんと**「2日」**で作ってくださりました！！

金額は4,000円（割引使って3,700円）でした。
相場は2,000円前後らしく、少しお高めですが、「年末年始の対応」「仕事の速さ」「レスポンスの速さ」も考えると大満足です！！

ちなみに私が頼んだ方は**「紅梅＠イラスト」**さんです。

##⑤Googleアナリティクス
せっかくアプリ作ったんなら、ユーザーがどのくらい使ったかみたいですよね。
その目的でよく使われるのがこれみたいです。

やり方はサイトを見ればすぐわかるのでここでは省略します。
https://marketingplatform.google.com/intl/ja/about/analytics/

僕程度では本来使うレベルに値しないんですが、
自分の出したアプリが数字として見える形になるのはとても嬉しかったです。
また、**「次はもっとユーザを伸ばすアプリを作る！！」**
というモチベーションにも繋がります。

是非皆さんも試してください。

※Google Analytics を使用する場合は、サイトにプライバシーポリシーを公開する必要があります。公式利用規約 の「7.プライバシー」等をご確認の上ご利用下さい。

#おわりに
他にも書きたいことはたくさんありますが、
全部書くと収集つかないのでこの辺で。。。

私も今回の経験を活かして、
もっと面白いアプリ作れるようがんばります！！
Cloudflare + Vercelでのリダイレクトループエラーの解消メモ


Vercel+Cloudflareでカスタムドメイン設定したWebサイトがリダイレクトエラーが発生しました。

> ![スクリーンショット 2021-01-05 21.21.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/4954a8f0-0e70-85e4-e077-8f8e9894952b.png "スクリーンショット 2021-01-05 21.21.10.png")

クッキー削除などでは解消されず...という感じでした。

先に解決できた方法から紹介してきます。結構手こずりました...

## SSL/TLS暗号化モードをフルに設定することで解消

Cloudflareの公式に書いてありました。

> [リダイレクトループエラーのトラブルシューティング](https://support.cloudflare.com/hc/ja/articles/115000219871-%E3%83%AA%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AB%E3%83%BC%E3%83%97%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AE%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)

Cloudflareでドメインを設定すると、`SSL/TLS 暗号化モード`がデフォルトでフレキシブルになってますが、フルにすることで僕の場合は解消しました。

> SSL/TLS アプリ「概要」タブで、CloudflareSSLオプションを更新します。

SSL/TLSのタブで設定します。

> ![スクリーンショット 2021-01-05 23.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/f25ec562-4719-9fb5-b048-dc11d139a748.png "スクリーンショット 2021-01-05 23.43.44.png")

Vercel側でSSL証明書がある模様でリダイレクトが発生していたのかな。

> 現在Flexibleに設定されている場合、オリジンWebサーバーに設定済みのSSL証明書がある場合、Fullに更新します。

## 補足: HTTPSへのリダイレクト設定は関係なかった

こちらもCloudflareのドキュメントに書いてありましたが、HTTP/HTTPSのリダイレクトに関しては特に設定を変えても関係なかったです。

> 1. (推奨) HTTPSからHTTPへのリダイレクトと、HTTPからHTTPSへのリダイレクトをオリジンWebサーバー設定から削除します。例：

この辺の設定は推奨設定で問題なかったです。

> ![スクリーンショット 2021-01-05 23.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/66e2f144-4b4e-ffd5-505b-ba5d612bae2a.png "スクリーンショット 2021-01-05 23.54.42.png")

## よもやま

細かく言うと今回はお名前.comで取得したドメインをCloudflareで管理しています。

```
お名前.com ----ネームサーバー移管---> Cloudflare ---DNS設定---> Vercel
```

ちなみに、Cloudflare+Netlifyで全く同じ設定をした場合は発生してなく、Cloudflare+Vercelの組み合わせで発生しました。

Netlifyだとcnameでaliasを推奨みたいな表記があるのですが、VercelはAレコードにIPアドレスを設定するやり方を推奨してる模様です。

> ![スクリーンショット 2021-01-05 21.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/f77de49f-3948-6f41-ff03-507b650888c9.png "スクリーンショット 2021-01-05 21.21.19.png")

最初Vercel側の設定なのかと思ったのですがCloudflare側の問題だったということが分かるまでけっこう大変でした.. 

リダイレクトループのチェッカーなどもあるみたいですね

> https://www.redirect-checker.org/index.php
Ruby：クラスメソッドとインスタンスメソッド、クラス変数とインスタンス変数の違い

※2022年から技術系の記事は[個人ブログ](https://yamaday0u.net/category/programmer/)に投稿しております。ぜひこちらもご覧ください→[yamaday0u Blog](https://yamaday0u.net/category/programmer/)

## クラスメソッドとインスタンスメソッドの違い
まずRubyのクラスメソッドとインスタンスメソッドの違いを見ていきます。

### クラスメソッドとは
クラスメソッドを定義したクラス自身が使用できます。クラスで共通の情報を使った処理に使用します。インスタンスがなくても呼び出すことができます。

クラスメソッドを定義する際は、`self.メソッド名`と記述します。以下のようにクラス名`Fruits`から呼ぶことができます。また、インスタンスを生成する`new`メソッドは、代表的なクラスメソッドです。


```fruits.ruby
calss Fruits
  def self.call #selfはクラス自身を指す
    puts "クラスメソッドを呼び出しました"
  end
end

Fruits.new #newメソッドもクラスメソッドの1つ。
Fruits.call
```

ターミナルで上記のrubyファイルを実行すると次のような結果になります。

```:ターミナル
ruby fruits.rb

クラスメソッドを呼び出しました
```
Fruits.callの実行結果が表示されます。
Fruits.newは空のインスタンスが生成されるだけなので実行結果には表示されません。

###インスタンスメソッドとは
インスタンスが使用できるメソッドで、クラス内に定義します。
「インスタンスメソッドを定義したクラス」から生成されるインスタンスが使用できます。

```fruits.ruby
calss Fruits
  def call
     puts "インスタンスメソッドを呼び出しました"
  end
end

fruits = Fruits.new
fruits.call
#.でつなげて下記のように呼び出すこともできます。
Fruits.new.call
```

```:ターミナル
ruby fruits.rb

インスタンスメソッドを呼び出しました
```

#### initializeメソッド
`initialize`メソッドは、`new`メソッドによってインスタンスを生成したと同時に実行される処理を定義できるインスタンスメソッドです。
実は、クラスに記述しなくても`initialize`メソッドは自動で実行されており、この場合は何も処理がされません。

```fruits.rb
class Fruits
  def initialize
    puts "インスタンスが生成されました"
  end
end

Fruits.new
```
ターミナルで上記のrubyファイルを実行すると次のような結果になります。

```:ターミナル
ruby fruits.rb

インスタンスが生成されました
```

`Fruits.new`でインスタンスを生成した後に`initialize`メソッドに定義した処理が実行されたことがわかります。

## クラス変数とインスタンス変数の違い
次にクラス変数とインスタンス変数の違いを見ていきます。

### クラス変数とは
そのクラス内で定義される変数で、`@@変数名`と記述して定義します。クラス変数は、クラスとして共通の変数を定義したいときに使うのに適しています。

```fruits.rb
class Fruits

  @@fruit = "オレンジ" #initializeメソッド内で使用するために、インスタンス生成前に定義

  def initialize
    puts "私は#{@@fruit}が好きです"
  end

end

Fruits.new
```
実行結果

```:ターミナル
ruby fruits.rb

私はオレンジが好きです
```

クラスメソッドの特徴として、一度定義すればクラス内のどこでも使用することができます。

```fruits.rb
class Fruits

  @@price = 0 

  def initialize(fruit, price)
    @fruit = fruit
    @@price += price
  end

  def self.sum
    puts "合計金額は#{@@price}円です" 
  end

end

Fruits.new("オレンジ", 200)
Fruits.new("リンゴ", 300)
Fruits.new("ぶどう", 500)

Fruits.sum
```

```:ターミナル
ruby fruits.rb

合計金額は1000円です
```
オレンジ、リンゴ、ぶどうのインスタンスを生成するたびにクラス変数`@@price `に各フルーツの価格が合算され、`sum `メソッドで合計金額を出力しました。

### インスタンス変数とは
個別のインスタンスに定義できる変数で、`@変数名`と記述して定義します。インスタンス変数は定義したインスタンスメソッドとは別のインスタンスメソッドの中でも使用することができます。

```fruits.rb
class Fruits

  def initialize(fruit)
    @fruit = fruit
    puts "私は#{@fruit}が好きです"
  end

  def dislike
    puts "私は#{@fruit}が苦手です"
  end
end

Fruits.new("オレンジ")
Fruits.new("リンゴ")
fruit = Fruits.new("ぶどう")
fruit.dislike
```

```:ターミナル
ruby fruits.rb

私はオレンジが好きです
私はリンゴが好きです
私はぶどうが好きです
私はぶどうが苦手です
```
`initialize`メソッドで、生成したインスタンスごとにインスタンス変数`@fruit`の値が代入され、putsで出力しています。

また、`initialize`メソッド で定義したインスタンス変数`@fruit` が` dislike `メソッドでも使用できているのが確認できます。

#参考資料
[Rubyのクラス変数の使い方を現役エンジニアが解説【初心者向け】(TechAcademyマガジン)](https://techacademy.jp/magazine/19933)
【メモ】C#で自作クラスのリストから重複を取り除く簡単な方法

# 自作クラスのリストから重複を取り除きたい
C#にはLinqのDistinctメソッドがある。
これはstring型やint型のリストには有効だが、そのままだと自作クラスでは機能しない。
[IEnumerable<T>を実装したクラスまたはIEqualityComparerの実装](https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.distinct?redirectedfrom=MSDN&view=net-5.0)を作りDistinctメソッドで回すことが定石だが、もっと簡単な方法があったのでメモ _φ(･_･

## string型やint型のリストにはDistinctでOK
```C#
var array1 = new string[] { "a", "a", "b", "b" };
foreach (var x in array1.Distinct())
    Console.Write(x);
// ab *OK
```

## 自作クラスのとき
2021/01/06: コメントを受けて修正済み

```C#
var source = new List<M>
{
    new M { P1 = "a", P2 = "a" },
    new M { P1 = "a", P2 = "a" },
    new M { P1 = "b", P2 = "b" },
    new M { P1 = "b", P2 = "c" }
};

var array2 = source.Distinct();
foreach (var x in array2)
    Console.Write($"{{P1: {x.P1}, P2: {x.P2}}}");
// {P1: a, P2: a}{P1: a, P2: a}{P1: b, P2: b}{P1: b, P2: c}
// {P1: a, P2: a} の重複が取り除かれていない

var array3 = source
    .GroupBy(x => new { x.P1, x.P2 })
    .Select(x => x.First());
foreach (var x in array3)
    Console.Write($"{{P1: {x.P1}, P2: {x.P2}}}");
// {P1: a, P2: a}{P1: b, P2: b}{P1: b, P2: c}
// *OK
```

## 追記（2021/01/06）

@albireo さんにもっとシンプルな方法で教えてもらいました。
C#7.3からはタプル同士を `==` `!=` 演算子で比較できるようになったそうです。
サンプルコードは[コメント](https://qiita.com/ishiyama0530/items/8edda3e25bf9348320f6#comment-a62189c01c7610e34192)を参照してください。

[コメント](https://qiita.com/ishiyama0530/items/8edda3e25bf9348320f6#comment-a62189c01c7610e34192)からの抜粋ですが、

> GroupByを使わないと難しいのは、「重複チェックでは対象外のプロパティも重複除外後に参照したい場合」

とのことです :thumbsup:
ハンドメイド商品にNIS１で手軽に価値保証を紐付ける方法

２０２１年１月投稿

ハンドメイド商品にNIS１で手軽に価値保証を紐付ける方法

ここではNIS１の特性を利用しブロックチェーンが消滅しないことを条件として、
主にハンドメイド商品に付加価値をつける提案と仕組みを解説します。


用意するもの
NEMwallet

ウォレットアドレス（物品管理用）１個　test-01
NCOFG7JCSTCX42FAU4JFMOFKFACZVQ4QOZZWL4TG

ウォレットアドレス（物品用）　１個　test-02
NCVYYFLB53G53YCO5UONR75VGIPFGSG2ORYKGW6M

紐付けたい商品　１個



解説
ウォレットアドレス（物品管理用）test-01は販売者専用の販売台帳となります。
ウォレットアドレス（物品用）test-02は商品１個に対して購入者１名、１ウォレットアドレス
というルールで運用します。

販売者はtest-01ウォレットから、test-02のウォレットアドレスに必要に応じて
販売商品名、メッセージ等を0XEM送信します。

送信を受け取ったtest-02のウォレットアドレスを商品と一緒に添付もしくは
後日メールで購入者と共有します。

以上です。

期待される効果・想定

薄利多売の大量生産商品にはできない人と人同士の付加価値をつけることができる。
販売日時が明確になる。
証明はブロックチェーンがなくならない限り続き、販売者、購入者ともに
商品を媒体として紐づいているのでアフターフォローがしやすい。
数年～十数年で壊れるような商品との親和性が良く、通常価格のその商品だけで設定させるが
お互いの保証信頼が明確になるなら、アフターフォローで想定される分を補償費として乗せておいてもよい。
どの程度還元するかはその販売者の倫理による。
また、保証費を商品側のウォレットに入れておくことも想定できる。

デモ
ここでは商品Aを１名に１個販売した場合を想定する。

１．nemwalletを使用しウォレットアドレスを発行する。（シンプルウォレットを選択）

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/a10049c3-04d0-3051-55e9-7ef5710346a3.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546181/fac40bb9-ea4d-64a9-50a7-1c7d1f04b1ea.png)


２．作成したアドレスが
ウォレットアドレス（物品管理用）１個　test-01
NCOFG7JCSTCX42FAU4JFMOFKFACZVQ4QOZZWL4TG
ウォレットアドレス（物品用）　１個　test-02
NCVYYFLB53G53YCO5UONR75VGIPFGSG2ORYKGW6M
です。

３．あらかじめ発行したウォレットアドレスに１XEM程度送金しておきます。

４．任意のメッセージを物品用アドレスに０XEM送信し、送ります。
（手数料がかかります今回は０．４XEMでした）
（絵文字を送信すると文字化けするようですので使わないほうが良いと思います）

http://xembook.net/xemmessage.html?address=NCVYYFLB53G53YCO5UONR75VGIPFGSG2ORYKGW6M

５．物品用ウォレットアドレス（test-02）を商品と一緒に送るか、もしくはメールで後日送ります

考察

現在の１XEMの価格が２０円ですので大体１０円で商品・購入者・販売者を半永久的に紐図けることができます。
また、商品の美術的価値が高くなり複製が出回ったとしても購入者・販売者が明確になる。
譲渡の場合は、販売者の物品管理用アドレスからその旨書き込めばよく、それ以外のアドレスから
書き込まれた内容であればその旨わかるので信頼性が失われません。
課題として、そのアドレスがその商品であるということを明確に表示するものは工夫が必要だと考えます。
例えば、絵画であればマイクロチップを埋め込む、保証書にウォレットアドレスを添付する等
簡単カレンダーを少し装飾してみた

#はじめに
　昨日、導入したsimple_calendarについて、少し装飾を加えたので、紹介します。

[簡単カレンダー
](https://qiita.com/TerToEer_sho/items/561844cecf16cd7013fd)

##表示のされかたを変えたい

```erb

<%= month_calendar do |date| %>
  <%= date.strftime("%d") %>
<% end %>
```

`strftim("%d")`によって表示を変えることができます。ちなみに、この記述で、日にちだけの表示にできます。

##曜日に色をつけたい

```css:calendar.css
.wday-0 {
  color: red;
}
.wday-6 {
  color: blue;
}
```

###変更前
![](https://i.gyazo.com/e644433b996e823cd23b0cf4a403cb66.png)

###変更後
![](https://i.gyazo.com/134dbbb227e978cd66ef9227584dda30.png)

少しはカレンダーっぽくなったかな…
vagrant packageでVBoxManage: error: RTVfsFsStrmAdd failed for 'box.ovf' (VERR_ALREADY_EXISTS) というエラーの解決方法

vagrant packageで `VBoxManage: error: RTVfsFsStrmAdd failed for 'box.ovf' (VERR_ALREADY_EXISTS)` というエラーが発生して若干ハマったため備忘録として残しました。
結論から言うと空き容量がない場合boxファイルを作成できずにこちらのエラーになるようです。

なので、
空き容量を増やすか外付けのストレージにVAGRANT_HOMEを移すことにより対処可能です。
今回は空き容量を増やすことができなかったので後者のやり方を採用して対応しました。

## エラー内容

```
$ vagrant package
==> default: Clearing any previously set forwarded ports...
==> default: Exporting VM...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["export", "49998b3d-dd24-49b2-afab-58653b3d74af", "--output", "/Users/hoge/.vagrant.d/tmp/vagrant-package-20210104-22105-1ry7egv/box.ovf"]

Stderr: 0%...
Progress state: VBOX_E_IPRT_ERROR
VBoxManage: error: Appliance write failed
VBoxManage: error: RTVfsFsStrmAdd failed for 'box.ovf' (VERR_ALREADY_EXISTS)
VBoxManage: error: Details: code VBOX_E_IPRT_ERROR (0x80bb0005), component ApplianceWrap, interface IAppliance
VBoxManage: error: Context: "RTEXITCODE handleExportAppliance(HandlerArg *)" at line 1686 of file VBoxManageAppliance.cpp
```

## 対応方法

空き容量を増やすことができなかったので外付けのSSDにVAGRANT_HOMEを一時的に移しました。

```
$ export VAGRANT_HOME=/Volumes/[SSD]/path/to/.vagrant.d
$ vagrant package
==> default: Exporting VM...
==> default: Compressing package to: /path/to/package.box
```

一時的にVAGRANT_HOMEを移したので元に戻さなければなりません。
もともとVAGRANT_HOMEが未設定であれば

```
$ unset VAGRANT_HOME
```

で削除すればOKですし、別の箇所に設定していたのであれば

```
$ export VAGRANT_HOME=/path/to/.vagrant.d
```

と元の箇所に設定しなおせばOKです。

## 参考

[Resolving Ambiguous Vagrant VirtualBox Driver Errors](https://xentutor.medium.com/resolving-ambiguous-vagrant-virtualbox-driver-errors-7ca4cd2c8c75)
ROS Python - 自作サービスのインポートエラー

## エラー
Pythonノードで自作Serviceのライブラリが読み込めないエラーが発生しました

```python:my_server.py
...

from my_servs.srv import *

...
```


```console:error
Traceback (most recent call last):
  File "/home/hoshina/catkin_ws/src/pca_server/scripts/pca_server.py", line 3, in <module>
    from pca_server_srvs.srv import *
ModuleNotFoundError: No module named 'pca_server_srvs'
```


## serviceのpythonライブラリが生成されているか確認
```bash
ls ~/catkin_ws/devel/lib/python3/dist-packages 

>> my_srvs 
生成されていればオッケー

>> 
何も出なければだめ
```

次のサンプルをビルドしてserviceのライブラリが生成されるか確認
https://github.com/fairlight1337/ros_service_examples

```bash
git clone https://github.com/fairlight1337/ros_service_examples.git

catkin build

ls ~/catkin_ws/devel/lib/python3/dist-packages 

>> ros_service_examples
オッケー,このリポジトリのCMakeLists.txtとpackage.xmlを参考にして、自分のものを修正する
```
## エラーが治らない場合
pythonに以下を追加してライブラリのパスが通っているか確認

```python
import sys
print(sys.path)
```


パスが通っていない場合は

```
source ~/catkin_ws/devel/setup.bash
```

をしたり、ターミナルを再立ち上げしたりする

## C++でincludeできない場合

```
catkin_ws/devel/include/　内にヘッダーファイルが生成されているか確認
```

ない場合

serviceパッケージのCMakeLists.txt内に

```
generate_messages()
```

を入れ忘れている可能性大


http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv


## 環境  
- ubuntu 20.04 
- ros noetic
ggplotで描画したグラフをまとめてpdfに保存する

通常、画像ファイルを保存する場合、ggsave関数を活用する。これを用いて、ファイルの種類を指定すれば.png, .jpg, .pdfなど選択できる。
一方で、複数のファイルをまとめて保存した場合はほかの保存方法が便利。
例えば、以下の事例。pdf関数を活用し、dev.off()で締めくくると、その間に描画したものがすべて1つのpdfに保存される。

```ggplot.R
library(ggplot2)

pdf("graphs.pdf") #ファイル名を指定
ggplot(data1, aes(x = X)) + geom_bar()
ggplot(hof_eras, aes(x = X, y = Y)) +  geom_point()
dev.off() #ここまで保存させる
```

また、余談だが
coord_flip()関数を使うと、描画したグラフのx軸、y軸を反対にする。