OmniAICreator/Qiita-1.07M huggingface dataset:
Mac（Catalina）にRuby / Railsをインストール 2021-01

※2021-01-04: 2020-04-29の記事を書き直しました。

環境: macOS Catalina, Ruby 2.6.6/2.7.2/3.0.0, Rails 6.1.0

## コマンドライン・デベロッパツールのインストール

次のコマンドを実行します。「"clang"コマンドを実行するには、コマンドライン・デベロッパツールが必要です。ツールを今すぐインストールしますか?」というダイアログが出るので「インストール」を押します。

```
% clang
```

次のコマンドを実行しても同じです。なお、Xcodeのインストールは必要ありません。

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

関連記事: [コマンドライン・デベロッパツールについてメモ](https://qiita.com/kazutosato/items/693000806405a0ebd939)

## Homebrew、rbenvのインストール

[Homebrewのサイト](https://brew.sh/) からコマンドをコピペしてHomebrewをインストールします。

```
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

ruby-buildとrbenvをインストールします。

```
% brew install ruby-build rbenv
```

OpenSSL 1.1 をインストールします。

```
% brew install openssl
```

.zshrcにOpenSSLとrbenvの設定を書きます。これ以外の環境変数は、記述しなくても必要なものはインストールできます。ターミナルを開き直します。

```text:.zshrc
export PATH="$(brew --prefix openssl@1.1)/bin:$PATH"

export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"

eval "$(rbenv init -)"
```

rbenvでRubyをインストールします。

```
% rbenv install 2.7.2
```

Rubyのバージョンを確認します。システムのrubyコマンド(/usr/bin/ruby）のままになっているときは、ターミナルを開き直してください。

```
% ruby -v
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
```

必要であれば、Rubyのその他のバージョンも入れておきます。

```
% rbenv install 3.0.0
```


## Railsのインストール

Bundlerのバージョンを上げておきます。

```
% gem install bundler -N
```

Railsの最新版をインストールします。-N オプションはriドキュメントを省いてインストールを速くするものです。

```
% gem install rails -N
```

バージョンを確認します。システムのrailsコマンド(/usr/bin/rails）のままになっているときは、ターミナルを開き直します。

```
% rails --version
Rails 6.1.0
```

yarn をインストールします。

```
% brew install node yarn
```

新しいアプリケーションを作ってみて成功すればOK。

```
% rails new generic
```

## おまけ: PostgreSQL/MySQLインストール

PostgreSQLのバージョン11をインストールします。

```
% brew install postgresql@11
```

.zshrcでバージョン11のパスを追加します。これだけで、gemのpgはコンパイルできます。

```text:.zshrc
export PATH="$(brew --prefix openssl@1.1)/bin:$PATH"
export PATH="$(brew --prefix postgresql@11)/bin:$PATH"
# 以下略
```

PostgreSQLを起動します。

```
% brew services start postgresql@11
```

MySQL 5.7をインストールします。

```
% brew install mysql@5.7
```

.zshrcでパスを追加します。

```text:.zshrc
export PATH="/opt/homebrew/bin:$PATH"
export PATH="$(brew --prefix openssl@1.1)/bin:$PATH"
export PATH="$(brew --prefix postgresql@11)/bin:$PATH"
export PATH="$(brew --prefix mysql@5.7)/bin:$PATH"
# 以下略
```

MySQLを起動します。

```
% brew services start mysql@5.7
```

bundlerでgemのmysql2をインストールすると、`ld: library not found for -lssl` というエラーが出ます（2021-01-04現在）。先にオプション付きでmysql2をインストールしておきます。

```
% gem install mysql2 -- --with-opt-dir="$(brew --prefix openssl@1.1)"
```

MySQL 5.7はパスワード必須のはずですが、Homebrewでインストールすると、rootのパスワードなしで使えます。パスワード必須にするには、次のコマンドで設定します。

```
% mysql_secure_installation
```
「AWSサーバーレスのウェブアプリケーションを構築する」の体験

いつも忘れないように、コンセプトから。

###コンセプト
・お金かけてまでやりたくないのでほぼ無料でAWSを勉強する
　→ちょっとしたサービスを起動すると結構高額になりやすい。
・高いレベルのセキュリティ確保を目指す
　→アカウントを不正に使われるととんでもない額を請求されるので防ぐ

無料ではないんですが（無料枠がある人はつかますが）、お安い金額でお勉強です。
GWもはじまり、Stay Homeで暇なんで「サーバーレスのウェブアプリケーションを構築する」を体験してみました。
https://aws.amazon.com/jp/getting-started/projects/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/module-5/

学習できるサービスは、

- AWS Lambda
- Amazon APIGateway
- Amazon S3
- Amazon DynamoDB
- Amazon Cognito

です。

###まずは感想から
チュートリアル自体は２時間あれば多少調べながらやっても終わると思います。時間的・金銭的なお手軽さはなかなかいい感じです。ただ、やってみて「で、結局なんだったの？」という内容なので、楽しさは無いです。一応認証を通してログインしてAPI経由で動くので、へーって感じはしますが、それまで。個人的には使ったことのないCognitoに興味がありました。あとはAPIGatewayもほとんど使わないのでやってみたかったのはあります。特に難しくもないのですが、ポイントだけ記載しておきます。

#####モジュール 1:静的ウェブホスティング
ここは簡単です。極端に言えばS3を作成してファイルを配置するだけなので楽勝。しいて言えば、S3の公開設定なんて普段絶対にやらないので、背徳感があるというか、ドキドキするくらいです。まあ、インターネット系の開発をしている人は全然気になるところではないんでしょう。

#####モジュール 2:ユーザー管理
ユーザー認証をCognitoで設定します。設定したらNode.js側の設定ファイルに、Cognitoを使えるように設定します。

> /js/config.js ファイルには、ユーザープール ID、アプリクライアント ID、およびリージョンの設定が含まれています。前のステップで作成したユーザープールとアプリケーションの設定でこのファイルを更新し、ファイルをバケットにアップロードします。

とあるので、指示に従って行えば簡単です。ユーザープールの概念だけ理解しておけばよいと思います。パスワードポリシーとか、MFA有効化とか、簡単にできるんですね。これは非常に便利だと思いました。

#####モジュール 3: サーバーレスサービスバックエンド
ここはDynamoを設定してLambda関数を作成するのですが、AWSで一番の難敵であるIAMはサラッと記載されているので注意が必要です。ポリシー設定もちゃんと登場はするんですが、基本的にチュートリアルではコピペで終わってしまうので、実際に環境構築する場合には難しいところです。動かすだけなら簡単なんですが、セキュアに組むとなると一気にハードルが上がるところです。特に外部公開するようなシステムであれば重要なので、ポリシー作成のあたりはもう少し補足が欲しいなと思いました。別のチュートリアルやればいいんでしょうけど。。。

#####モジュール 4: RESTful API
今回一番難しかったところです。いろいろ設定していくんですが、クライアントからLambdaにどう連携するかがチュートリアルの説明だとわかりにくかったです。出来上がってしまうと以下の画面で連携を確認できるんですが、設定途中だとイメージしにくかったです。慣れていれば問題にはならないでしょうけど、オーソライザーとの関係とかもはじめはよくわかってなかったです。
![apigateway.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480659/99f02dee-7a91-71aa-7768-a49851e30124.png)


###まとめ
仕事ではAPIGatewayを使うことはほぼないですが、簡単に構築できるのは素晴らしいと思います。ただ、使いこなすのにはそれ相応のスキルが必要ですね。どうしてもセキュリティに目が行ってしまいますが、どうやって安全に構築できるかをどうやって確認するかは課題だなと思いました。CISベンチマークに情報が無いかなと思ったんですが、
https://www.cisecurity.org/
「CIS Amazon Web Services Foundations Benchmark v1.2.0」を見てみましたがAPI Gatewayは無かったですね。書かれているのが2018年5月なので情報も少し古いです。現状の対象サービスは以下のようなので、早く追加されるとうれしいなとは思います。

- AWS Identity and Access Management (IAM)
- AWS Config
- AWS CloudTrail
- AWS CloudWatch
- AWS Simple Notification Service (SNS)
- AWS Simple Storage Service (S3)
- AWS VPC

とりあえず今日はここまで。
type 'YourClass' is not a subtype of type 'StatelessWidget'で少しハマった話

# 概要
Udemyを見ながらFlutterの勉強をしているのですが、自分で一から動くものを作っていて掲題のエラーにはまりました。
いくらソースコードを修正してもエラーエラーエラーエラー。。。

# 解決策
アプリのリスタートで解決しました。

# 備考
どうやら、StatelessWidgetからStatefulWidgetに変更する時には
Restartしないとダメらしい。
よくよく考えたらそりゃそうだって話なんだけど初心者は割とつまづくんじゃないかなと思って
備忘録的に。

誰かのお役に立てば。
make installしたファイルたちを手作業で消す（Julius Uninstall）

#経緯
Juliusというオープンソースの音声認識エンジンを試すために「make install」しました。
その後、「ｍake uninstall」できなかったので、ひとつずつ手作業で消した備忘録です。

#手順
```shell:shell
make install -n
```

上記のコマンドで「make install」時にどこになんのファイルを配置したかのコマンドが出力されます（インストール処理自体は走らない）。それを参考に「/local/usr配下」に配置された関連ファイルをひとつずつ消していきました。

いつもパッケージマネージャに頼りがちなので、makeするとどういうコマンドが動いているかを探っていけたので、勉強になりました。

#参考
[コンパイル・インストール手順 (Unix)](https://julius.osdn.jp/index.php?q=doc/install.html)
[make -n installしたらインストールされるファイルの… - 人力検索はてな](https://q.hatena.ne.jp/1143381629)
[JuliusをmakeしたらHomebrewが動かなくなったので、アンインストールした - rohaniのブログ](https://rohani.hatenablog.com/entry/2019/04/23/184921)
P5.js 日本語リファレンス(bezierTangent)


このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/private/91818244dc26c767a0fe) の bezierTangent関数を説明します。

## bezierTangent()

### 説明文

ポイント a、b、c、d の位置 t での bezier への接線を算出します。パラメータ a と d はカーブの最初と最後のポイントで、b と c はコントロールポイントです。最終的なパラメーター t は 0 と 1 の間で変化します。

### 構文

bezierTangent(a, b, c, d, t)

### パラメタ

- a  
Number：曲線上の最初の点の座標

- b  
Number：最初の制御点の座標

- c  
Number：2番目の制御点の座標

- d  
Number：曲線上の2番目の点の座標

- t  
Number：0と1の間の値

### 戻り値

Number：位置tの接線

### 例1

```javascript
function draw(){
  noFill();
  stroke(205, 0, 250); // 紫色を設定
  bezier(85, 20, 10, 10, 90, 90, 15, 80); // bezier 曲線を描画
  
  let steps = 3;
  for (let i = 0; i <= steps; i++) {
    let t = i / steps;
    let x = bezierPoint(85, 10, 90, 15, t); // bezier 曲線上のx座標を取得
    let y = bezierPoint(20, 10, 90, 80, t); // bezier 曲線上のy座標を取得
    let tx = bezierTangent(85, 10, 90, 15, t); // bezier 曲線の接線x座標を取得
    let ty = bezierTangent(20, 10, 90, 80, t); // bezier 曲線の接線y座標を取得
    let a = atan2(ty, tx); // x軸からの角度を取得
    a += PI;
    stroke(255, 0, 0); // 赤色を設定
    line(x, y, cos(a) * 20 + x, sin(a) * 20 + y); // 法線を描画

    stroke(0, 0, 255); // 青色を設定
    line(x, y, cos(a) * -20 + x, sin(a) * -20 + y); // 反対側に法線を描画

    stroke(0);
    ellipse(x, y, 6, 6);
  }
}
```

### 実行結果
![bezierTangent-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43467/ab1e6bff-03cc-9d54-bd03-fb5a9ae22442.png)


### 例2

```javascript
function draw(){
  noFill();

  stroke(255, 0, 0); // 赤色を設定
  bezier(125, 20, 10, 10, 90, 90, 15, 80); // bezier 曲線を描画

  stroke(0, 255, 0); // 緑色を設定
  circle(125, 20, 8); // 始点を描画

  stroke(0, 0, 255); // 青色を設定
  circle(15, 80, 8); // 終点を描画

  stroke(200, 0, 255); // 紫色を設定
  circle(10, 10, 8); // 最初の制御点を描画

  stroke(245, 210, 0); // 黄色を設定
  circle(90, 90, 8); // 2番めの制御点を描画

  let steps = 16;
  stroke(50, 200, 255); // 水色を設定
  for (let i = 0; i <= steps; i++){
    let t = i / steps;
    let x = bezierPoint(125, 10, 90, 15, t); // bezier 曲線上のx座標を取得
    let y = bezierPoint(20, 10, 90, 80, t); // bezier 曲線上のy座標を取得
    let tx = bezierTangent(125, 10, 90, 15, t); // bezier 曲線の接線x座標を取得
    let ty = bezierTangent(20, 10, 90, 80, t); // bezier 曲線の接線y座標を取得
    let a = atan2 (ty, tx); // x軸からの角度を取得
    a = a - HALF_PI;
    line(x, y, cos(a) * 12 + x, sin(a) * 12 + y); // 法線を描画
  }
}
```

### 実行結果
![bezierTangent-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43467/f1f6058e-d671-209b-7a72-cfcc2cc918b6.png)




### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
CakePHP2でsaveAllが遅いからバルクインサート

こちらのサイトから引用させていただきました
http://damepg.hatenablog.com/entry/2012/10/01/001223

saveAllとqueryでのバルクインサートでは50倍の差があるみたいです。


# バルクインサート
どのテーブルでも使えるので、AppModelにでも。

```php
    // バルクインサート
	public function bulkInsert($data) {
		$table_name = $this->usetable;
		$fields = array_keys($data[0]);

		$holder = '(' . implode(',', array_fill(0, count($fields), '?')) . ')';
		$holders = implode(',', array_fill(0, count($data), $holder));

		$params = array();
		foreach ($data as $key => $val) {
			foreach ($fields as $field) {
				if ($field == 'created') {
					$params[] = date('Y-m-d H:i:s');
				} else {
					$params[] = $val[$field];
				}
			}
		}

		$fields = implode(',', $fields);
		$sql = "INSERT INTO ${table_name} (${fields}) VALUES ${holders}";

		$ret = $this->query($sql, $params);
		if ($ret === false) {
			// エラー処理
			return false;
		}
		if ($this->getAffectedRows() != count($data)) {
			// エラー処理
			return false;
		}

		return true;
	}
```

# 使い方

```php
    // Model指定して使う
	$this->User->bulkInsert(
		array(
			array( 'name' => 'taro','job' =>  '社長'),
			array( 'name' => 'jiro','job' =>  '専務'),
			array( 'name' => 'saburo','job' => 'バイト'),
		)
	);
```
Macで特定のWebページを見れなくなった話

#Macで特定のWebページが見れなくなった

* 使用しているMacのスペック 
 * MacBook Pro
 * macOS Catalina version 10.15.4

先日Macを使いSafari上でネットサーフィンをしていると，

**Safari Can't Find the Server**

と表示され，突然特定のページのみ閲覧できなくなった．
翌日になってもこの問題が解決しなかったため，Chromeで同じページを開いたところ，

**DNS_PROBE_FINISHED_NXDOMAIN**

と表示され，やはりそのページを閲覧することができなかった．
どうやらブラウザに依存するようなエラーではないらしい．
このエラーについて調べてみると，DNS関連の設定がうまくいってないらしいとのこと．
結果的にこの問題を解決できたので，その解決法を以下に示す．

まず，アップルメニューからシステム環境設定を開いて，
![mac1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628781/2b5ff429-5019-5055-831e-7d3bd63206b7.png)



ネットワークを選択し，
![mac2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628781/d1ca1e08-d364-34d4-a539-f6b904828480.png)



詳細を選択すると，
![mac3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628781/d0ce6f7f-b02e-dad2-abee-5431c7a8234f.png)



TCP/IPと書かれたタブが見つかるはずなので，そのタブをクリックしてから「DHCPリースを更新」というボタンを押すとok．
![mac4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628781/7218712a-4047-f8dc-03a1-220ef132f686.png)



DHCPを利用する際には「期間限定で使用できるIP」的なものが割り当てられるらしいのだが，期限切れになってもそのIPを使おうとしたのだろうか？
いずれにせよ，この方法で解決できる可能性があるので，同じようなエラーに悩まされてる方はご参考までに．
Asciidoctorインストール手順（Windows10）

Asciidoctorのインストール手順をこの記事では書いていきます。

* 実行環境
    * Windows10
* インストールするもの
    * Ruby v2.7.1
    * asciidoctor 2.0.10


## Asciidoctorとは
軽量マークアップ言語であるAsciiDocをHTMLに変換するためのツールです。
AsciiDocについては、[AsciiDocの良いところ](https://qiita.com/aki-nasu/items/5bf7eeb40687df02945b)を良ければご参照ください。

## インストール手順

### Rubyをインストールする
まず、Rubyをインストールします。今回は`Ruby 2.7.1-1 (x64)`をインストールしました。
※Rubyの詳しいインストール手順は省略します。

* [Ruby-Install](https://rubyinstaller.org/downloads/)

* インストール出来たことを確認

```
ruby -v
```

![](https://i.imgur.com/oADrsdA.png)

### Asciidoctorをインストールする
gemでAsciidoctorをインストールし、インストールできたことを確認します。

```
gem install asciidoctor
gem list --local
```

![](https://i.imgur.com/cJJLNEf.png)

## 実行確認
では、実際にHTMLを出力できることを確認します。
以下の内容をテキストに貼り付けてAsciidoctorのコマンドを実行します。

* sample.adocとして保存

```AsciiDoc
== レベル 1
Text.

=== レベル 2
Text.

==== レベル 3
Text.

===== レベル 4
Text.

.データ形式はCSV, 各カラム幅は表示域の15% (60 ÷ 4 = 15)
[format="csv",width="60%",cols="4"]
[frame="topbot",grid="none"]
|======
1,2,3,4
a,b,c,d
A,B,C,D
|======
```

* AsciidoctorでHTMLを出力する

```
asciidoctor sample.adoc
```

* 出力結果

![](https://i.imgur.com/bjltYzn.png)

## おわりに
単にAsciiDocで文章を書くだけであれば、[AsciiDocの執筆環境を用意する](https://qiita.com/aki-nasu/items/3ae92863b0aaa2aed032)だけでよさそうですが、プレビュー表示では`include`した文を取り込んで表示してくれなかったりします(`AsciidocFX`さんは出来る)。
ですので、作成中はVisual Studio Codeのプレビュー機能で確認し、commitもしくはpushのタイミングでHTMLに出力して最終チェックするという使い方がよいかと考えます。
python3におけるforループの計算速度

## python3におけるforループの計算速度

競技プログラミングをした際に学んだpythonにおけるfor文の計算速度がコード依存性についてのまとめ。

pythonには、配列の記述方法として通常のlistとnumpyのndarrayがある。
行列計算をする場合、numpyを用いるほうが何かと便利なので全てnumpyのndarrayを利用していた。
しかしfor文を書く際、むやみにnp.arange()を用いるとかなり計算速度が遅くなる。

```python:ex_bad.py
for i in np.arange( 5 ):
    print( i )
```

```python:ex_good.py
for i in range( 5 ):
    print( i )
```
【業務系】自動化スクリプト作成のためのリンク集

# 自動化

## [バッチ職人になろう](https://language-and-engineering.hatenablog.jp/entry/20110904/p1)
多種多様ののツールや言語の自動化スクリプトに関するサイト。

## [完全自動化研究所](http://marukentokyo.jp/)
UiPathやSikuliXなどのRPAツールに関するサイト。

## [いつも隣にITのお仕事](https://tonari-it.com/)
業務自動化関連のVBAとGASとPythonスクリプトに関するサイト。

#  ExcelVBA

## [Excelでお仕事](http://www.asahi-net.or.jp/~ef2o-inue/top01.html)
Excel作業のVBAコードを作成するために参考にする。

## [RelaxTools Addin](https://software.opensquare.net/relaxtools/)
オープンソースのExcelアドインでVBAコード作成するために参考になる。

# サクラエディタ

## [カテゴリ別マクロ](http://sakura.qp.land.to/?Macro%2F%A5%AB%A5%C6%A5%B4%A5%EA)
エディタ作業のマクロコードを作成するために参考にする。
[Unity初級]for文の中での変数の扱い

#概要
for文を複数書く時、同じ名前の変数を使うのはよくなさそうだからと違う名前を付けるべきでしょうか？

```cs

    for(int i=0;i<wordMaxLength;i++){
        taiou[i]=-1;
    }
    for(int j=0;j<5;j++){
        x = x + j;
    }
```
#本文
```cs

    for(int i=0;i<wordMaxLength;i++){
        taiou[i]=-1;
    }
    for(int i=0;i<5;i++){
        x = x + i;
    }
```
この時の変数iはfor文{ ‥‥ }の中の閉じた空間限定の変数として扱われるので、同じ変数名を繰り返し使ってもエラーになる事はないです。それぞれの変数の中身も別々のものとして扱われます。
Ruby on Rails チュートリアル 17日目

##17日目
今回は11章の[11.3.2 editアクションで有効化](https://railstutorial.jp/chapters/account_activation?version=5.1#sec-activation_edit_action)まで進んだところでつまずきました。
下のURLを開くと

```
https://505f3862405346e5a7106eb59e6fbcbc.vfs.cloud9.ap-northeast-1.amazonaws.com/account_activations/
```
![スクリーンショット 2020-04-29 12.31.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606053/90a561b1-f1a0-52b6-0204-7b0cc14ee06a.png)

この様になっていました。
routingを確認しても

```/sample_app/config/routes.rb

Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users
  resources :account_activations, only: [:edit]
end

```
これには何の問題もないように思えます。
解決方法を知りたいです。
GCPのApp Engineを使ってGolang製のAPIをデプロイしたら簡単すぎました

## はじめに

普段は業務でAWSをガッツリ触らせていただいていますが、今回は前々から興味のあったGCP(Google Cloud Platform)でアプリケーションをデプロイすることにしました。

ちなみに、GCPでプロジェクト作成後、クレジットカードを登録したら1年間使える3万円分のクレジットもらえました。。

至れり尽くせりすぎる！ありがたく使わせていただきます！

## GCPとAWSの違いとは？

個人的な所感ですが、

AWSはいろんなサービスがあって、インフラエンジニアの方からすると痒いところに手が届くようなサービスが豊富にあるように思えます。

ただ、僕のようにインフラに詳しいわけではなく、ただ自分のアプリを手軽にデプロイしたいような人間からすると、AWSは若干ハードルが高いように感じます。

それに対してGCPは、下記のようなメリットがあります！

- 公式ドキュメントが豊富で読みやすい
- コンソールのUIがAWSに比べてわかりやすい
- サービスの数はAWSほど多くなく、どれを使えば良いか初心者でもわかりやすい
- Firebaseを使う場合、GCP内であれば連携が容易

特に、個人開発でFirebaseをよく使うので、Firebaseとの連携が容易にできる(プロジェクトIDを指定するだけ)のは最高だと思います。

## App Engineとは？

App Engineの公式ドキュメントは[こちらです](https://cloud.google.com/appengine?hl=ja)

一言でいうと、**フルマネージドなサーバーレスコンピューティングサービス**です。

オートスケーリングの機能もあるので、AWSのFargateのようなイメージです(App Engineはコンテナ基盤ではありませんが)。

僕たち開発者は、インフラ周りのことを全てGoogleに丸投げでアプリをデプロイできるわけですね。最高。

## App Engineにアプリケーションをデプロイする

いよいよデプロイしていきましょう。

今回はリクエストがきたらHello Worldと返すだけのシンプルなAPIをデプロイします。

- まずはソースを作成します。マイブームのGolangで書いていきます。

```go:helloworld.go
import (
    "net/http"
	"os"
    
    "github.com/labstack/echo"
)

func main() {
    // サーバーのインスタンス作成
    e := echo.New()
    
    // ルーティング設定
    e.GET("/", helloworld)
    
    // サーバー起動
	e.Logger.Fatal(e.Start(":" + os.Getenv("PORT")))
}

func helloworld(c echo.Context) error {
    return c.String(HttpStatus.OK, "Hello, World")
}
```
- App Engineでアプリを起動するために必要なyamlファイルを作成します。

```yaml:app.yaml
runtime: go112
```

- 作成したソースとyamlファイルをGitHubにプッシュします。

- GCPで新規プロジェクトを作成します。

- GCPコンソール上でターミナルを開きます。

→ ローカルでCLIを使う方法もありますが、今回は手軽に試したいのでGCPが用意してくれている簡易的なターミナルを使用します。

- ソースをGitHubからクローンします。

- ソースのあるディレクトリに移動したら、下記コマンドを叩きます。

```
gcloud app create
```

- 最後にデプロイ用のコマンドを叩きます。

```
gcloud app deploy
```

以上です！！！ターミナルに表示されるURLに実際にリクエストを送ってみると正常に動いているはずです。

## おわりに

こんなに簡単なのは本当に感動しました。

Cloud FunctionsやKubernetes Engineも使ってみたいなあ。
AtCoder Beginner Contest 164 D 数学よく分からないマンが解説を加えてみる

もはや<b>AtCoder Mathematical Content</b>だという声の上がっている表題の問題について、
以下かつっぱさんの解説が華麗すぎてすぐには分からなかったので、数学がよく分からない人でもなんとなくわかった気になれるよう、解説を加えてみます。

[https://www.youtube.com/watch?v=Ra0y0EZ24ZM:embed:cite]

### 考え方

文字列Sが"60574038"だったとします。
このとき、1文字目から4文字目の"6057"が割り切れるかを考えてみます。

Aを右端から"6057"の左端までの値、Bを右端から"6057"の右端手前までの値と考えます。つまり

A = 60574038
B = 4038

です。
このとき、AからBを取り除いたA-B(6057)が2019で割り切れるかどうかは

(A-B) / (10**4) % 2019 = 0

と表現できますが、ここで10**nと2019は互いに素なので、上の式は

(A-B) % 2019 = 0

と等価です。これは

A % 2019 = B % 2019

と等価です。つまり、2019で割った時のAとBの余りが同じなら、A-Bは2019で割り切れます。

このような(A,B)の組み合わせの数を計算すれば良いので、
余りが同じAやBがn個あったとき、その組み合わせのnC2、つまりn*(n-1)/2を計算すれば良いことになります。

従って本問題は、
まず余りの値ごとに、Sの中で余りが同じになる値の数を数え（余りが0の値が何個、余りが1の値が何個、、、）、
次に余りの値ごとに、組み合わせの数を計算し、合計した値が答え、
となります。

#### コード

コードは以下の通り。かつっぱさんのコード丸パクリですが、コメントで説明を加えます。

```python
s = input()[::-1] # 右からn桁の数についてループを回していきたいので、文字列を反転させる

sum_of_digits = 0 # 余りの値
cnts = [0] * 2019 # 余りの値ごとに余りが同じ値の数を格納する変数。2019で割る場合、余りは0~2018までの2019通りあるので、リストの長さは2019
cnts[0] = 1 # ※1
d = 1 # sum_of_digitsの計算に使う10の累乗値

# まず余りの値ごとに余りが同じ値の数を数える
for c in s:
    sum_of_digits += int(c) * d
    sum_of_digits %= 2019
    d *= 10
    d %= 2019 # ※2
    cnts[sum_of_digits] += 1

# 次に余りの値ごとにその組み合わせを計算し、足し合わせる
ans = 0
for cnt in cnts:
    ans += cnt * (cnt - 1) // 2

print(ans)
```

#### ※1

Bとしては0桁の値をとれることに注意します。例えば

A = 4038
B = 
A-B = 4038

というケースです。
for c in sとやるとcは1桁の値から始まります。
そこで0桁の値の余りはfor文の前に計算しておきます。0桁の値を2019で割った余りは0なので、cnts[0]に1を代入します。

#### ※2

`d %= 2019`で計算時間を抑えます。
この処理をしても結果に影響がないのは、直感的には以下で理解できます。

2020 * 10000 % 2019 = 2
2020 * 1924 % 2019 = 2 (10000 % 2019 = 1924)
VSCodeのターミナルでBashのショートカットを使えるようにする

VSCodeのターミナルでWSLのシェルを開くと、Ctrl+p、Ctrl+k等が使えない。
VSCodeでショートカットキーに定義されてるものが使えません。

File > Preferences > Keyboard Shortcuts
を選択してショートカットの設定画面を出す
画面右上にある　
Open Keyboard Shortcuts(JSON)をクリック
次のような記述で、ショートカットを無効にしたいキーを羅列する。

```JSON
[
    {
        "key": "ctrl+p",
        "command": "",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+e",
        "command": "",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+f",
        "command": "",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+k",
        "command": "",
        "when": "terminalFocus"
    },
]
```

Qiitaでも類似した解決策があったんですが、こんなシンプルな記述ではなかったので、書いてみました。
TkinterでQRコードメーカーを作ってみた！

プログラミングの勉強の為に、とにかく何か成果物を作りたい！と思い、pythonのTkinterでQRコードメーカーを作ってみました。


```Python3:qrcode.py
import tkinter
from PIL import Image,ImageTk
import qrcode
 
url = ''
img = imgtk = None
 
def click_btn():
    global url,img
    url = entry.get()
    img = qrcode.make(url)
    draw_code()
 
def draw_code():
    global imgtk #PhotoImage()はグローバル変数に入れないとすぐ消滅し、画像が表示されない
    canvas.delete('QRCODE')
    imgtk = ImageTk.PhotoImage(img) 
    canvas.create_image(
        300,
        300,
        image=imgtk,
        tag='QRCODE'
        )
 

root = tkinter.Tk()
canvas = tkinter.Canvas(width=600,height=500,bg='white')
canvas.pack()
root.title('QRcode maker')
entry = tkinter.Entry(width=60)
entry.place(x=20,y=70)
label = tkinter.Label(root,text='QRコード化したいURLを入力',font=('System',24))
label.place(x=20,y=20)
button = tkinter.Button(root,text='QRコード作成！',font=('Times New Roman',24),command=cli    ck_btn)
button.place(x=20,y=100)
root.mainloop()
```         
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606735/0be434cd-e1c1-eb4b-624b-d0d4d04c3e61.png)

↓実行
   
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606735/02737aee-8d2b-9bc7-26d2-479b60ca04e1.png)

###◎詰まったこと
・エラーメッセージが出ないのに、QRコードがcreate_imageで表示されなかった。
・qrcodeモジュールのimg.saveで保存すると、qrコードは生成されており、保存出来た。
→QRコードが一瞬だけ表示されて、すぐ消えたのかと思い、root.after（）とか使ってみたけど、効果なし。

色々調べた結果、グローバル関数でPhotoImageオブジェクトを保管しないと、オブジェクト？がすぐ消えてしまうようです。
参考url→http://lrcgf.hatenablog.com/entry/2013/06/30/222918

QRコードのイメージを作成したものの、create_imageにきちんとデータを渡せていなかったようです。
勉強になりました。
【Colab】pillow画像取得をURLから直接行う


# まずPillowをColab上にインストール
```python:pytohnコード
!pip install Pillow==7.0.0
```
#画像読み込み
これでとりあえず画像取得できる。

```python:pytohnコード
from PIL import Image
import requests
import io

url = 'https://www.python.org/static/community_logos/python-logo-master-v3-TM.png'
img = Image.open(io.BytesIO(requests.get(url).content))
img
```
# Colab URL
https://colab.research.google.com/notebooks/empty.ipynb#scrollTo=lIYdn1woOS1n
# 参考URL
https://note.nkmk.me/python-pillow-basic/
競プロのライブラリ整理~約数の列挙~

[こちらの記事](https://qiita.com/LorseKudos/items/9eb560494862c8b4eb56)でPythonのコードとして書かれていたものを流用したものおよびそれをC++に書き直したものになります。
また、C++のコードを使用する際は、[テンプレート](https://qiita.com/DaikiSuyama/items/9dba963ba74396b9b7fd)と一緒に使うようにお願いします(一緒に使わないと動きません。)。

```python:enumerate_divisors.py
def make_divisors(n):
    divisors=[]
    for i in range(1,int(n**0.5)+1):
        if n%i==0:
            divisors.append(i)
            if i!=n//i:
                divisors.append(n//i)
    #約数の小さい順にソートしたい場合
    #divisors.sort()
    #約数の大きい順にソートしたい場合
    #divisors.sort(reverse=True)
    return divisors
```

```c++:enumerate_divisors.cc
vector<ll> divisors;//約数を格納する配列

void make_divisors(ll n){
    FOR(i,1,sqrt(n)){
        if(n%i==0){
            divisors.PB(i);
            if(i!=n/i){
                divisors.PB(n/i);
            }
        }
    }
    //約数の小さい順にソートしたい場合
    //sort(ALL(divisors));
    //約数の大きい順にソートしたい場合
    //sort(ALL(divisors),greater<ll>());
}
```
WARNINGS: ***: (fields.W161) Fixed default value provided. ....というワーニングの改善方法

## ワーニングの内容

```
WARNINGS:
***: (***) Fixed default value provided.
        HINT: It seems you set a fixed date / time / datetime value as default 
for this field. 
This may not be what you want. If you want to have the current date as default, 
use `django.utils.timezone.now

```

## 改善方法

```
from django.utils import timezone
...
...

create_date = models.DateTimeField(default=timezone.now())
```
となっていたものを

```
from django.utils import timezone
...
...

create_date = models.DateTimeField(default=timezone.now)
```
に変更することで改善された。

## 参考
- https://www.monotalk.xyz/blog/django-model%E3%81%AEdatetimefield-db%E3%82%AB%E3%83%A9%E3%83%A0%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%80%A4%E3%81%A7warning/
【サクラエディタ】スネーク⇔キャメル変換するマクロ


```javascript:snakeToCamell.js
function converter(match, offset, string){
  var inp = match;
  if(/^[A-Z0-9]+$/.test(inp)){
    return inp.toLowerCase();
  }
  //スネークケースかどうか？アンダースコアがあるか？
  if(/_/.test(inp)){
    //スネーク→キャメル
    //全て小文字に
    inp = inp.toLowerCase();
    //区切り文字の後を大文字に
    inp = inp.replace(/(_|^)(.)/g, snakeToCamelConv);
    //先頭を小文字に
    inp = inp.charAt(0).toLowerCase() + inp.slice(1);
  }else{
    //キャメル→スネーク
    //大文字の前に「アンダースコア」を追加
    inp = inp.replace(/([A-Z])/g, camelToSnakeConv);
    //全て大文字に
    inp = inp.toUpperCase();
  }
  return inp;
}

function snakeToCamelConv(match, p1, p2, offset, string){
  return p2.toUpperCase();
}

function camelToSnakeConv(match, p1, offset, string){
  return '_' + p1;
}

//(INPUT)選択範囲を取得
var str = Editor.GetSelectedString(0);
//(PROCESS)スネークケース⇔キャメルケース
str = str.replace(/(\w+)/g, converter);
//(OUT)編集したテキストを設定
Editor.InsText(str);
```

# 使用例
対象行を選択して、当マクロを実行する。

### 実行前
```
DATA1
SAMPLE_DATA2
SAMPLE_TEST_DATA3
```

### 実行後
```
data1
sampleData2
sampleTestData3
```

### 再実行後
```
DATA1
SAMPLE_DATA2
SAMPLE_TEST_DATA3
```
[備忘録]AdGuardで特定のアプリだけ通信できない場合疑うところ

#はじめに
本投稿はほぼ個人の備忘録です。
・AdGuardを使っている
・なぜか特定のアプリだけ通信ができてない
という場合、
Adguardのアプリの設定をみろ！→最悪一時的にガードはずす
という流れ

#Adguardのアプリの設定をみろ！
こんなふうに設定したくなる
![suku1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219000/e0110d54-4f69-b9e7-1e90-a31ecbb2a6c3.jpeg)
![suku2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219000/5bb5cdd5-73ad-4ba8-488d-2a3212fd3e2b.jpeg)

こんな設定をしたところ、GooglePlayだけオフライン状態になった。
別の端末ではGooglePlay使えるし、他のアプリは普通に使えていた。
さらに「VPNを使用していないすべての接続をブロックする」にチェックを外すとGooglePlayが使えるようになった。

これは新しく買った端末のせい？ともいろいろ疑ったが、AdGuardには「アプリの管理」という項目がある。
なぜかGooglePlayの設定だけAdGuardからの保護が外れていた。

![suku3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219000/d065a828-abe1-2ec4-01a0-aa1bdd183755.jpeg)

これをなおしたら、ともあれオフラインじゃなくなった。

#最悪一時的にガードはずす
オフラインじゃなくなったけど…ダウンロードができない。
いろいろブロックしているのがあるのかと思って、ユーザフィルタを駆使したがダメ。

まぁいっか

ということで、アプリのインストール時だけは
・「VPNを使用していないすべての接続をブロックする」にチェックを外す
と一時的に設定をいじって対応することにした。

だれか対応の仕方、ご存知ないですかね？
他のアプリはこんな問題起きないのに…なんで？
Oppo Reno A + AdGuardPro + GooglePlayがダメ。
もっというとGooglePlayでアプリの更新があったかまでは確認できるが、更新（ダウンロード）ができない。

で、Rakuten Linkとやらが頻繁にアップデートするもんでまぁ面倒。
【Ubuntu18.04 + HHKB US】全角/半角の切替を左右Altに設定する

## はじめに
Ubuntu18.04 + HHKB USで全角/半角の切替を左右Altに設定する方法をメモします。
今までMacのJISキーボードを使っていてスペースバーの横にある切替キーがとても手になじんでいるのでUbuntu + US配列でも同じ操作感を実現したいとおもい設定します。

## 環境

- Ubuntu18.04
- HHKB Professional HYBRID(US配列)

## インストールするもの

- fcitx
- fcitx-mozc


## 手順

1. fcitx, fcitx-mozcインストール
    - `sudo apt-get install -y fcitx fcitx-mozc`
2. 設定1: `Settings` > `Region & Language` > `Manage Installed Languages` > `Keyboard input method system`でfcitxを選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45398/48587a56-5131-2579-5d94-379640e556ca.png)
3. 設定2: `fcitx configuration` > `Input Method`にMozcとEnglishを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45398/871ac026-992f-1bd4-b2ea-5638e0c86bf3.png)
4. 設定3: `fcitx configuration` > `Global Configuration` > `Show Advanced Optionsをチェック` > `Activate/Inactivate Input MethodにLalt/Raltをそれぞれ割当`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45398/85fa8688-31bd-32ce-e6bb-f5210d859300.png)

## 終わりに

以上で左右Altで全角/半角の切替が可能になりました。設定しても動作しない場合は再起動すると動作するかもしれません。
UdonSharp日記～ソースコードの構成～

#概要
UdonSharpでは他オブジェクトのUdonSharp関数にアクセスできない（たぶん）
そのため、複数の機能をワールドに持たせたい場合、1つのClassファイルが大きくなる
傾向にある（と思う。知識不足感が否めませんが。）

1つのクラスに複数の機能を盛り込む場合のソースの設計についてご紹介。

今回は直接的なUdonSharpの話ではありません。
1つのクラスに対し機能を追加していく過程でスパゲッティになってしまうこともあると思います。
そこで一つの解決策をご提示できたら幸いです。

ここら辺のノウハウって「あたりまえだよ～」的な感じであまり共有されていないんじゃないかな？
なんて思ってたりします。
（私もデザインパターンを勉強しないと）


#ソースコードの構成

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627563/3dcee78b-4ccc-487a-cb59-1613a1378829.png)

設計の目的は機能追加がしやすいことです。
具体的には下記の2点を心がけること
1.必要な変数・関数をコピペして定義できる。（切り貼りの範囲が明確である。独立性が高い）
2.実行するためには最小の関数をメイン関数（UdonSharpでははStart()とUpdate()）に登録すればよい。

1.に関しては名前空間を定義して、接頭語としてクラスメンバ変数・クラスメンバ関数につけてあげること
2.に関しては**_init()と**_Update()を呼べば動く状態にすること

といった感じです。

他の人のソース構成も知りたいですね。
RaspberryPiとAWS IoTの簡単接続

# RaspberryPiとAWS IoTの接続設定
基本的な接続方法は[AWS IoTの開発ガイド](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/what-is-aws-iot.html)に従うのが簡単だ。
ただし、２つの方法があり、両方試してみた。ここでは、簡単ではるかに早く設定できた「接続ウィザード」を使った方法を説明する。（準備ができていれば所要時間は約30分）
## 環境
- RaspberryPi 3B:
    - Raspbian GNU/Linux 10 (buster)
    - Python 2.7.16 (default, Oct 10 2019, 22:02:15)
        - ここでは、AWS IoTのPython SDKを利用するため
    - gitが導入されていること 
        - GitHubから、SDK(aws-iot-device-sdk-python)がクーロンされる
    - OpenSSL 1.1.1d  10 Sep 2019
    - インターネットに接続できる環境。(AWSのIoTサービスに接続できる）
- AWSのアカウントがあること
    - AWS IoTサービスを利用する
- 下記は2020年4月時点の手順です。

## 設定手順 
- PCからAWS IoTメニューに入る
    - オンボード選択
        - デバイスをオンボード
            - 開始方法をクリック
                - プラットフォームの選択
                    - Linux/OSXを選択する
                - AWS IoT デバイスSDKの選択
                    - ここでは、Python を選択する
                - 次へをクリック
                - モノの登録。RaspberryPiの名前を登録する。
                - 接続キットのダウンロード
                - connect_device_package.zipがダウンロードされる
![スクリーンショット 2020-04-25 18.41.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225748/bb9c47c7-c4fb-f624-2086-252975f88fa1.png)
- PCにダウンロードしたファイルを解凍する
    - 解凍したディレクトリ名：connect_device_package
    - 以下のファイルがある
        - RaspberryPi_test.cert.pem
        - RaspberryPi_test.private.key
        - RaspberryPi_test.public.key
        - start.sh
    - READMEの記述によると、通信の暗号化はTLSプロトコルでX.509証明書が使用される
- PCにダウンロードしたファイルをRespberryPiへ転送する
    - RaspberryPiに任意のディレクトリを作成する
    - PCからscpコマンドでディレクトリ毎、RaspberryPiへコピーする
        - PCのコマンドターミナルを開く
        - $ scp -r コピー元ディレクトリ名 ユーザー名＠IPアドレス:RaspberryPiのパス
- RaspberryPiのターミナルからコピーしたシェルを実行する
    - $ sudo ./start.sh
        - 筆者の環境では以下のエラーが発生した
            - start.sh: 19: ./start.sh: pushd: not found
        - start.shの１行目に　#!/bin/bashを追加して再度実行する
            - gitからaws-iot-device-sdk-pythonがクーロンされる 
    - クラウドと接続され無事MQTTサンプルアプリケーションが実行され接続の確認ができた！
        - 実行されるサンプルアプリケーションのディレクトリ：aws-iot-device-sdk-python/samples/basicPubSub
            - 実行されるサンプルシェル：basicPubSub.py

## 別の接続方法
- [AWS IoT開発ガイド](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/what-is-aws-iot.html)の「AWS IoT Coreの使用の開始」から一つ一つ進めることも可能だ。
- RaspberryPiとの接続の観点からは、メニューに「RaspberryPiでのAWS IoT Device SDKの使用」があるのがすばらしい。IoTデバイスまたは学習用として、RaspberryPiが普及しているからだろう。ただし、開発ガイドにPython SDKの解説がないのは残念なところか。今のところ、「RaspberryPiでのAWS IoT Device SDKの使用」メニューには、AWS IoT Device SDK for Embedded Cの使用とAWS IoT Device SDK for JavaScriptおよびNodeを利用するのみ。 

以上、接続までの方法でした。２つの方法を試した経験から、「オンボード」メニューから設定する方がはるかに簡単であることがわかった。

## 考慮点
接続方法をいろいろ試していると、接続時にキーと証明書が合わないエラーが出てきた。opensslコマンドで確認する方法が便利だった。[Qiitaリンク](https://qiita.com/ukitazume/items/5c8a51e441eb09769873)
pub/subプログラムによる接続確認は別の[Qiita記事](https://qiita.com/t_kawa1/items/d1916dd8e1bee3bbb2f4)で記述します。

## 参考資料
AWS IoTのPython SDKについては[GitHub](https://github.com/aws/aws-iot-device-sdk-python)にスクリプトの解説がある。
SoXでノイズ入りの音声データを作成

機械学習で音声データのサンプル数がが少なかったので、ノイズデータを入れて音声データを量産しました。
その際の手順を紹介します。

基本的に扱う音声ファイルはwavファイル前提で話を進めていきますので、ご容赦を...

# SoX（Sound eXchange)
これを使うと色々な音声処理できます。
今回はこの中の機能の一部を使ってノイズ入りの音声データを量産してみます。

まずはインストールする。

``` bash
brew install sox --with-lame
```

# 音声データにノイズを混ぜる
早速ですが、ノイズを混ぜてみましょう。
ノイズ用データをフリー素材などから拾ってきましょう。「フリー素材　音声」で調べると生活音などのノイズにできそうなデータが出てくるかと思います。

``` bash
sox -m sound.wav -v 0.1 noise.wav noise_mix.wav trim 0 3
```
上記コマンドでsound.wavとnoise.wavを混ぜて、noise_mix.wavを作成できる。

-m は ２つの音声ファイルを混ぜることを意味します。
-v はノイズ（2つめの音声データ）の音の大きさの調整、1が元の音量。
trim はトリミング、今回だと0秒目から3秒目までをトリミングしている。

# pythonでshellを叩いて量産
実際量産するとなるとfor文など使い実行することになると思います。
pythonではsubprocessモジュールを使うとコマンドを実行できるので、この中でfor文を回してあげると良さそうかなと思いコードを書きました。
ディレクトリ構成などによってコードが変わると思うので、あくまで一例ですが、ざっくり以下のような感じかと。

``` sox.py
import subprocess

for sound_idx in range(1,11):
    for volume in range(1,11):
        for noise_idx in range(1,11):
            s_idx = str(sound_idx)
            noise_volume = str(float(volume) / 10)
            v = str(volume)
            n = str(noise_idx)
            cmd = f'sox -m sound_{s_idx}.wav -v{noise_volume} noise_{n}.wav {s_idx}_{v}_{n}.wav trim 0 3'
            subprocess.check_output(cmd, shell=True)
```

もうちょっと綺麗に書けるはずなので、参考程度に...

### 注意
混ぜるデータ同士、サンプルレート数等が異なるとエラーが発生するので、今回は書きませんがこの辺もSoXなど使って調整の必要が出てくる可能性があるかと思います。

参考: http://webdatareport.hatenablog.com/entry/2016/11/06/161304
Laravel×Reactの環境構築

# この記事を読んで出来ること
バックエンドにPHPのフレームワークであるLaravelを、フロントエンドにJavaScriptのフレームワークであるReactを用いたウェブアプリ開発をするための環境構築。
※今回はmacOSを用いて環境構築を行っています。

## Composerをインストールする
まずはLaravelをインストールために用いるComposerをインストールします。Composerとは、PHP開発で使用するライブラリやパッケージを管理するツールで、macOSではHomebrewでインストールすることが出来ます。インストールが完了してバージョン情報が表示されるか確認しておきましょう。

```
$ brew install composer
$ composer -V
```

## Laravelプロジェクトを作成する
次に、composerを用いてLaravelプロジェクトを作成します。プロジェクトの作成にはcreate-projectを用います。

```
$ composer create-project laravel/laravel "プロジェクト名"
$ cd "プロジェクト名"
```

## Reactを利用できるようにする
フロントエンドのフレームワークをReactに設定します。まずは、Reactを利用するために必要なlaravel/uiパッケージをインストールします。

```
$ composer require laravel/ui
```

そして最後にReactのインストールをします。この際、"--auth"と書くことでログイン機能もインストールしています。インストールが終わると、npmコマンドを実行するようにメッセージが出るのでその通りに実行します。

```
$ php artisan ui react --auth
$ npm install && npm run dev
```

ここまでの作業を終えると、resouce/js/components/Example.jsのコードがReactを用いたものになってることが確認できます。

## Laravelの動作確認
以下のコマンドで開発用のローカルサーバを起動し、[表示されるアドレス](http://127.0.0.1:8000)にアクセスします。

```
$ php artisan serve
```

インストールが正常に行われていたら、「Laravel」と書かれた初期ページが表示されます。ログイン機能もインストールしているため、右上には「LOGIN」「REGISTER」のリンクも表示されているはずです。

## jsファイルの変更を監視する
サーバーは起動したままターミナル上で別のタブを開き、以下のコマンドを実行することでjsファイルが変更されたら自動的にコンパイルが行われます。開発時には "php artisan serve" とこちらのコマンドを実行しておくことでブラウザ上でウェブページを確認することが出来る。

```
$ npm run watch
```
2020-04-29 VMWare Workstation 15 Pro > ゲストOSからインターネット接続できない

```txt:動作環境
Windows 10 Pro (v1909)
VMware(R) Workstation 15 Pro (15.5.2 build-15785246)
```

## 症状

ゲストOSからインターネットに接続できない。

## 気づいた点

ホストOS側で以下のサービスが「停止」になっており、起動もできない。

- VMware DHCP Service
- VMware NAT Service

別途、以下のサービスは「停止」になっており、起動はできた。起動することで、USBメモリがゲストOSに接続できるようになる。

- VMware USB arbitration Service

### 情報

- Networking is broken in my VMware 10.0 VMs after upgrading to Windows 8.1
    - https://superuser.com/questions/643567/networking-is-broken-in-my-vmware-10-0-vms-after-upgrading-to-windows-8-1

「仮想ネットワークエディタ」を管理者権限でデフォルトにする、とのこと。

### 仮想ネットワークエディタ > デフォルトに

1. 仮想ネットワークエディタを開く
2. [設定の変更]で管理者権限にする
3. [デフォルトに戻す]を選択する

実行したところ、以下となった。**処理は5分かかった。**

- ネットワーク関連のドライバの再インストール
- VMnet1, VMnet8の作成
- 下記サービスが再起動後に「実行中」となった
    - VMware DHCP Service
    - VMware NAT Service
    - VMware USB arbitration Service

ゲストOSで「取り外し可能デバイス > ネットワークアダプタ」の設定をしたところ、ゲストOSからインターネット接続できるようになった。
VHDXファイルからWindowsを起動させてみる

#はじめに
VHDXブートとはWindows 7/Server 2008 R2以降で提供されている機能で、VHDX（仮想HDD）から
サーバを起動することができる

#背景
最近は仮想化が進んでいる
　　→物理でも共通のイメージが使えたら良いいかもね！
　　→Windowsだし、VHDXブートで良いよね！


#メリット
・仮想環境と共通イメージを利用できる
・VHDX以外は物理デバイスを直接利用
　　　→各種HW管理ツールが利用可能
・P2P、V2Pが自由自在に
・仮想化と比べ、リソースに無駄がなくオーバーヘッドも低い
・バックアップが簡単
・マルチブートが可能

#デメリット
・構成が複雑になる
・複数OSの同時起動はできない(仮想化ではないので)
・物理構成に比べ、ディスク利用効率及びIOが悪くなる
・ドライバ回りに配慮が必要
・トラブル時の対応は……
・制限事項
　https://docs.microsoft.com/ja-jp/windows-hardware/manufacture/desktop/deploy-windows-on-a-vhd--native-boot

#前提
起動したいOSが入ったVHDXを作成済み

物理ハードディスクの容量が起動したいVHDX以上であること

#OSインストール
まずはWindowsを普通にHDDにインストール　*インストール方法は割愛

ディスク状況は下記な感じでな

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624314/83d099d5-af8a-4689-10f3-c8a834197f91.png)

考慮事項
・VHDXブート後、元々のCドライブは不要となるため、最小でよい
・未割当領域をVHDX格納場所として利用するため、OS分と仮想メモリ分以上の容量を確保する

未割当領域にY等のドライブレターを割り当て、起動したいOSが入ったVHDXを入れる

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624314/da31f957-d9d5-d49b-e81d-bb92333cf162.png)

#BootManagerの編集

コマンドプロンプト上で下記実行

bcdedit /copy {current} /d "メニュー表記"
bcdedit /set <GUID> device vhd=[ドライブレター:]\<ディレクトリ>\<VHDファイル名>
bcdedit /set <GUID> osdevice vhd=[ドライブレター:]\<ディレクトリ>\<VHDファイル名>
bcdedit /set <GUID> detecthal on 

````
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Windows\system32>bcdedit /copy {current} /d "VHD boot"
エントリは {33e534c9-d027-11e8-8371-fe67fa56f32b} に正常にコピーされました。

C:\Windows\system32>bcdedit /set {33e534c9-d027-11e8-8371-fe67fa56f32b} device vhd=[Y:]\検証.vhdx
この操作を正しく終了しました。

C:\Windows\system32>bcdedit /set {33e534c9-d027-11e8-8371-fe67fa56f32b} osdevice vhd=[Y:]\検証.vhdx
この操作を正しく終了しました。

C:\Windows\system32>bcdedit /set {33e534c9-d027-11e8-8371-fe67fa56f32b} detecthal on
この操作を正しく終了しました。

C:\Windows\system32>
````

システムのプロパティ→起動と回復→規定のオペレーションシステム
　VHD bootへと変更
　OSの一覧を表示～のチェックを外し、再起動

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624314/f39493ae-eb29-7931-7133-08a0a58b8f24.png)

#VHDXブート後の確認
VHDXがディスク１として認識され、VHDX内のCドライブから起動している事が分かる

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624314/1e0d32b0-b55d-99ac-5976-9a7adf15e30c.png)

#事後作業
VHDX置き場(今回はF)をYへと変更
仮想メモリのドライブをCからYへと変更（VHDX上では仮想メモリを取れない為）
元々のCドライブ（今回はE）をフォーマット、必要であればその他ドライブとして利用する
　　　→不要であれば、すべてYドライブへと拡張してみても
VHDX上のシステムで予約済み（今回はD）のドライブレターを削除

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624314/e3935cba-c70b-0b42-ae2f981d7bf9c6b1.png)

#その他
C以外のドライブを別VHDXとした場合は起動時に自動的にマウントされなかった

タスクスケジューラにて起動時に下記様を実行させ自動的にマウントさせてみる

　★開始プログラム
　C:\Windows\System32\cmd.exe
　★引数
　/c "(echo SELECT VDISK FILE"Y:\D-Drive.vhdx" && echo ATTACH VDISK && 
　echo SELECT VDISK FILE"Y:\E-Drive.vhdx" && echo ATTACH VDISK) | diskpart“



可変ディスクはトラブルの元　固定にするべき
VHDXドライブサイズが物理サイズを超えると起動できない

#ブート方法の違いによるディスクIO差
検証機：HP PROLIANT DL360 G7
使用ソフト：CrystalDiskMark

てきとーな検証をしたため、物理HDDより良い数値が出てしまったが、物理ブートだろうがVHDXブートだろうが
転送速度に対した差はないと考えられる

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624314/4a6aefcd-9008-0664-746f-9f05245f6183.png)

#富士通による検証
公開してありました
最大でも6％の劣化との事
https://jp.fujitsu.com/platform/server/primergy/software/windows/technical/tips/w2008r2/01-02.html
添字付きファイルの並び替え（ソート）が出来ないときの対処方法

こんにちはしろです


![](https://paper-attachments.dropbox.com/s_7A02063475B1E58340D437464951C3C914E9522DA76E8D548C8FEF0161F495B7_1588126690289_image.png)


こういうファイルをソートしようと思ったときファイル内ではうまく並び替えれるのにPython などで処理をしようと思ったら。

![](https://paper-attachments.dropbox.com/s_7A02063475B1E58340D437464951C3C914E9522DA76E8D548C8FEF0161F495B7_1588126743258_image.png)


このように予想した並びと違う順序になることがあります。。。

これに詰まったので自分用のメモとして書き残しておきます。


##対処法

添字の前に余分に0000をおくことです。これにより問題は解決できます。

しかし、名前すべて手作業で書き換えるのは面倒なのですべてPythonに任せてしまいましょう。


前提として、もとのファイルの添字を足す場合のみを考えます。

```python
ex)img32.png ⇒ img00032.png
```

## 必要となる知識



1. ファイル名の取得（osを使う）
2. 名前から添字の取得（正規表現の使用）
3. ファイルの名前変更（shutilの使用）

です。簡単なので１つずつ終わらして行きましょう。





## 1. ファイル名の取得（os）

ファイル名を取得するにはosというものを使います。

```python
    import os
    file_dl = './File/'
    res = os.listdir(file_dl)
```
これだけでfile でしていたファイル内にあるものの名前がすべて取得出来ました。


## 2. 名前からの添字の取得（正規表現　re）

次は取得したファイル名から添字を取得しましょう。

```python
    import re
    file_index = re.search(r'\d{1,}', 'img012.png').group()
```
ここでは正規表現と言うものをつかって数字だけを文字列から取得しています。

この場合だとimg012.pngから012だけが抜き出されfile_indexに格納されてます。



## 3ファイルの移動（shutil）

最後に名前を変更して保存するのですがそれにはshutil を使います。
やってることは名前を変更して元の場所に移動させているだけです。

```python
    import shutil
    shutil.move(old_path,new_path)
```
こうすることでnew_path にold_pathにあったものが移動させることが出来ました。


## まとめ

以上のことを連結させると

```python
    import os
    import shutil
    import re
    
    file_dl = './File/'
    name = 'img_name'
    #ファイル内のフォルダ名を取得
    res = os.listdir(file_dl)
    
    #for文を用いて１つずつファイルを取り出す。
    for target_name in res:
        #ファイルのパスとファイル名を結合
        target_dl = file_dl + target_name
        #正規表現を用いて添字だけを取り出す
        target_index = int(re.search(r'\d{1,}', target_name).group())
        #新しいファイル名の作成
        target_new_name = name+str("{0:05d}".format(target_index))+'.png'
        #ファイルの名前を変更して保存し直し
        shutil.move(target_dl,file_dl+target_new_name)
```
Segueを使った画面遷移の方法

##任意のタイミングでの画面遷移(基本設定)
### Main.storyboardでの操作
1. 遷移元のViewControllerを選択
2. [control]＋[ドラッグ&ドロップ]で遷移先のViewControllerに繋ぐ
3. present modallyに設定する
4. (presentationをFullScreenにする)※任意
5. [segue]（矢印）のIdentifierを設定する。

### 遷移元のコード
```
----Class内.任意のメソッド内に記述する----
performSegue(withIdentifier: <#String#>, sender: nil)//任意のタイミング
```
遷移したいところに記述しておく
<#String#>はMain.storybordで設定したsugueのIdentifierを書く

###遷移先のコード
```
----Class内.任意のメソッド内に記述する----
dismiss(animated: true, completion: nil)//任意のタイミング
```
FullScreenの設定では画面をスワイプして遷移元の画面に戻ることができないので上記のコードを書いておく。

##値を渡しながら画面遷移する
**上記の設定、コードは必須**

###遷移元のコード
```
----Class内に記述する----
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.withIdentifier == <#String#>{
        let <#name#> = segue.destination as! <#UIViewController#>
        <#name#>.受け取る変数 = 渡す値
    }
}
```

画面遷移時に自動で呼ばれる
1. <#String#>にはsegueのIdentifierを書く。
2. <#UIViewController#>には遷移先のClass名
3. <#name#>には任意の定数名。
例)NextViewControllerClassであればNextVC等

###遷移先のコード
```
----Class内に記述する----
var 受け取る変数名　= 任意のデータ型()
```
受け取る変数を定義しておく

##遷移先から画面を戻す時に処理を行う場合
[先述した基本設定]の設定、コードは必須
加え、下記のコードを書く
###遷移元のコード
```
<#protocolName#>//後述のプロトコルをClassに適合する

------以下、変数名等に関しては先に説明したものと同じように書く------

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == <#String#>{
        let <#name#> = segue.destination as! <#UIViewController#>
        <#name#>.delegate = self
    }
}
```
下記のコードを記載したあとProtocolでエラーが出る。
プロトコルメソッドが記載されていないためである。
エラーで補完されたプロトコルメソッドに行いたい処理を書く
###遷移先のコード
```
----Class外に記述する----
protocol <#protocolName#>{
    func <#functionName#>()
}

----Class内に記述する----
var delegate:<#protocolName#>?

----Class内.任意のメソッド内に記術する----
delegate?.<#functionName#>()
dismiss(animated: true, completion: nil)//任意のタイミング
```
非Active Record（Active Model）のデータをFactoryBotで生成する

最近書いたテストが、ActiveModel（非アクティブレコード）に基づいていました。ちょっと工夫も必要だったので、備忘も兼ねて記事を残そうと思います。
今回テストを書いたモデルはこんな感じです。

### Recordsモデル（非Active Record）
| column | type |
|--------|------|
|id|integer|
|title|string|
|information|text|

### テスト用のモデルを作る
`spec/support/models/record.rb` に以下のように記載し、テストに使えるモデルを作成します。

```ruby:spec/support/models/record.rb
class Record
  attr_accessor :id, :title, :information
end
```

### ファクトリを生成する
`spec/factories/record.rb` にファクトリを生成します。
class名を省略せずに入れるところがポイントです。

```ruby:spec/factories/record.rb

FactoryBot.define do
  factory :record, class: :record do
    id { 1 }
    name { 'タイトルです' }
    information { 'テストデータです' }
  end
end
```

### テストで使う
テストで使うときはこんな感じです。`FactoryBot.create` ではなく、`FactoryBot.build` を使うのがポイントです。（DBにテーブルがあるわけではないので、createでsaveまで走らせようとするとエラーになります）

```ruby:
 describe 'something', type: :something do
   redord = FactoryBot.build(:record)
   expect(record.title).to eq "タイトルです"
 end
```

結局、作成したテストではActiveModelのFactoryを使わなかったのですが、役に立ちそうだったので記録として残しておきます。

参考サイト：
[Tips for Using FactoryGirl Without an ORM](https://thoughtbot.com/blog/tips-for-using-factory-girl-without-an-orm)
[非ActiveRecordなテスト用データをFactoryGirlで生成する](https://qiita.com/foloinfo/items/1534a77eca7de4c57edc)
Delphi10 まだアセンブラが使えるか試してみた

#はじめに
Delphi10でもまだアセンブラが使えるか試してみました。
複雑なものを書く元気が無いので、学生時代に初めて習ったアルゴリズムである
バブルソートでごまかしてみました。
ソート対象データは  data : array [0..DATACOUNT] of integer　にセット済みの前提です。
DATACOUNTは定数(const)です。

#普通にPascalで記述
```Pascal
// バブルソート
procedure TForm1.bubble;
var i,j,v : integer;
    exchange : boolean;
begin
  for i := DATACOUNT downto 1 do
  begin
    exchange := false;
    for j := 0 to i-1 do
    begin
      if data[j] > data[j+1] then
      begin
        exchange := True;
        v := data[j];
        data[j] := data[j+1];
        data[j+1] := v;
      end;
    end;
    if not exchange then
      break;
  end;
end;
```

#アセンブラ（かなり怪しい）で記述
```Pascal
// バブルソート(アセンブラ)
procedure TForm1.bubble_asm;
begin
  asm
    push edi                   // 変更不可レジスタ退避
    push esi                   // 変更不可レジスタ退避
    push ebx                   // 変更不可レジスタ退避
    lea edi,[eax].TForm1.data  // data[0]のアドレス
    mov edx,DATACOUNT          // for i := DATACOUNT
@for1:                         // 外側ループ処理開始
    cmp edx,1                  // 外側ループ終了判定
    jb @ret                    // 外側ループ終了判定
    mov esi,1                  // exchange := false
    mov ecx,0                  // for j := 0
    push edi                   // data[0]のアドレス保存
@for2:                         // 内側ループ処理開始
    mov eax,[edi]              // data[j]
    mov ebx,[edi+4]            // data[j+1] integer=4byte
    cmp eax,ebx                // if data[j] > data[j+1]
    jbe @noexchange            // data[j] <= data[j+1]ならthen以下を実行しない
    mov esi,0                  // exhcnage = true
    mov [edi],ebx              // data[j] := data[j+1]
    mov [edi+4],eax            // data[j+1] := data[j]
@noexchange:                   // 交換終了(無し)
    inc ecx                    // to i-1
    cmp ecx,edx                // 内側ループ終了判定
    je @for2end                // 内側ループ終了判定
    add edi,4                  // dataへのポインタを1つ進める
    jmp @for2                  // 内側ループ繰り返し
@for2end:                      // 内側ループ終了
    pop edi                    // data[0]へ戻す
    dec edx                    // i := i-1
    cmp esi,1                  // if not exchange then
    je @ret                    // break
    jmp @for1                  // 外側ループ繰り返し
@ret:                          // 処理終了
    pop ebx                    // 変更不可レジスタ回復
    pop esi                    // 変更不可レジスタ回復
    pop edi                    // 変更不可レジスタ回復
  end;
end;
```

#結果
何とか動きました(汗)
処理時間を測定したところデータ件数10万件で
　普通にPascal　= 32.7秒
　アセンブラ = 18.6秒
ということである程度の高速化にはなっています。
※マシンスペックは別記事を参照してください。
まあ実際に使うことは無いと思いますが…
Excelで重複するデータを刈り取る機能「重複の削除」

Excelでデータ管理をしていると、ついつい同じデータが登録されていたりして、台帳がカオスになっていたりすることがあります。
結構、複数人で作業したりしているとおきますよね。
そんなときのための重複行を裁く方法を紹介します。

## 重複行を抽出する
COUNTIF関数を使ってフラグ列を作り、オートフィルタ機能を使ってそれらを抽出します。
新しい列に以下のような塩梅の数式をいれます。（COUNTIFの検索対象範囲は絶対参照に、検索値は相対参照にするのがコツです）
=IF(COUNTIF($B$2:$B$65535,B2)>1,”重複”,””)
一行入力したら、そのセルをコピーして、同じ列の全行に貼り付けます。
その後、オートフィルタを実行し、フラグ列から空白セルを除外します。
これで重複行のみが表示されるようになります。

## 「重複の削除」機能を使い自動的に処理する
［重複の削除］機能を使用して自動的に重複データのうち1件を残して2件目以降を削除することができます。

重複行を処理したい範囲をぐりっとドラッグして選択し、「データ」＞「重複の削除」を押します。
![名称未設定-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628561/6eca2aa3-9db4-070a-d4bc-4e015572a11d.jpeg)

なにやらダイアログが出てきます。
重複行とみなす基準を指定するためのダイアログで、チェックを入れた列のデータが同じものが重複行とみなされます。
OKを押すと処理が走ります。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628561/0f8aeda5-832a-b5c3-f788-68167570795b.jpeg)

結果がダイアログで表示されます。
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628561/29d55e51-3c71-b62c-0d4f-6e640cb8067c.jpeg)

重複行が削れてユニークなものだけになりました。
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628561/b1a0a3bb-0b56-387f-01e0-fa41b4a4f169.jpeg)
jestでFirestoreテストしようとして TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type object

jestを使って「ローカルでない」Firestoreに関連するテストをしようとしたところ以下のエラーが発生しました。

```
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type object
```

`process.env.GOOGLE_APPLICATION_CREDENTIALS` には正しい認証ファイルのパスが設定されており以下のコードでエラーが発生。

```
const Firestore = require('@google-cloud/firestore');
const firestore = new Firestore();
```

jest.config.jsに以下を追記することで解決しました。

```
testEnvironment: 'node'
```

参考
https://github.com/firebase/firebase-admin-node/issues/793#issuecomment-592867589
【Objective-C】NSUserDefaultsについて

#NSUserDefaults
NSUserDefaults簡単に言うとキーバリュー型のDB(データベース)にアクセスするために用いるもので、これを用いることで、アプリの起動時にキーと値のペアを永続的に保存することができます。その他の特徴を下記に記しておきます。

**・< Key, Value >形式の辞書型でアクセス可能。**
**・各iOSアプリは、1端末に対して1つのNSUserDefaultsを保持している。**
**・アプリを削除するとNSUserDefaultsも消えるため、同じアプリを再インストールしてもNSUserDefaultsはリセットされる。**


NSUserDefaultsは以上のような特徴を持っていて、主な使用目的としてはユーザーの設定情報（Preferences）を永続的に保存することが目的として挙げられます。

#生成方法
NSUserDefaultsを生成する為には、以下のコードで生成します。

```objective_c
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
```

#サンプルコード
##値を登録（保存）
下記のコードではNSUserDefaultsを取得した後、NSMutableDictionaryを取得し、key-value形式で配列に値を入れて行っています。その後配列をregisterDefaultsで登録することによって、NSUserDefaultsへの値の保存が完了します。

```objective_c
NSUserDefaults *test = [NSUserDefaults standardUserDefaults];  // 取得
NSMutableDictionary *defaults = [NSMutableDictionary dictionary];
[defaults setObject:@"99" forKey:@"KEY_I"];  
[defaults setObject:@"99.99" forKey:@"KEY_F"]; 
[defaults setObject:@"88.88" forKey:@"KEY_D"];  
[defaults setObject:@"YES" forKey:@"KEY_B"];  
[defaults setObject:@"hoge" forKey:@"KEY_S"];
//registerDefaultsで登録
[ud registerDefaults:defaults];
```

##値の更新
下記のコードでは、NSUserDefaultsに対して値の更新処理を行っています。
値を更新するときは、そのKEYの型に合わせて整数ならsetInteger、flost型ならsetFloatなどで値を更新していきます。
そして最後にsynchronizeを叩くことで、NSUserDefaultsに更新した値を即座に反映させることができます。

```objective_c
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];  // 取得
[ud setInteger:100 forKey:@"KEY_I"];  
[ud setFloat:1.23 forKey:@"KEY_F"];  
[ud setDouble:1.23 forKey:@"KEY_D"];  
[ud setBool:YES forKey:@"KEY_B"];  
[ud setObject:@"あいう" forKey:@"KEY_S"]; 
//現在は不要
//[ud synchronize];  NSUserDefaultsに即時反映させる（即時で無くてもよい場合は不要)
```

##値の取得
値の取得は下記コードのように**[NSUserDefaults 型名forKey:@"キー名"**でvalueを取得し、それを変数などに代入してあげることで取得が可能です。

```objective_c
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];  // 取得
int i = [ud integerForKey:@"KEY_I"];  // KEY_Iの内容をint型として取得
float f = [ud floatForKey:@"KEY_F"];  // KEY_Fの内容をfloat型として取得
double d = [ud doubleForKey:@"KEY_D"];  // KEY_Dの内容をdouble型として取得
BOOL b = [ud boolForKey:@"KEY_B"];  // KEY_Bの内容をBOOL型として取得
NSString s = [ud stringForKey:@"KEY_S"];  // KEY_Sの内容をNSString型として取得
```

##値の削除
値の削除は**[NSUserDefaults removeObjectForKey:@"キー名"];**でキーを削除することによって、削除が完了します。

```objective_c
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];  // 取得
[ud removeObjectForKey:@"KEY_I"];  // KEY_Iを削除する
```

#参考
https://developer.apple.com/documentation/foundation/nsuserdefaults/1414005-synchronize?language=objc