OmniAICreator/Qiita-1.07M huggingface dataset:
競技プログラミング練習記 No.30【ABC130練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC130](https://atcoder.jp/contests/abc130)を解きました。
4完です！

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  1min |-| 6ms|
| B |  3min |-| 7ms|
| C |  8min |-| 6ms|
| D | 11min |しゃくとり法|19ms|



## A - Rounding
```c++
	int x, a;
	cin >> x >> a;
	cout << ((x < a) ? 0 : 10);
```
問題文もプログラムもシンプルですね。

## B - Bounding
``` c++
	int n, x, l;
	cin >> n >> x;
	int cnt = 1;
	int pos = 0;
	for(int i = 0; i < n; ++i)
	{
		cin >> l;
		pos = pos + l;
		if (x < pos) break;
		cnt++;
	}
	cout << cnt;
```
入力をもらった時に次の位置がわかりますね。（未来の入力がなくても次の位置を出せます。）
入力を受け取ると同時に位置と回数の更新をして、`X`を超えた時点で出力しました。

## C - Rectangle Cutting
``` c++
	ll w, h, x, y;
	cin >> w >> h >> x >> y;
	printf("%.9f %d", w * h / 2.0, (x*2 == w && y*2 == h) ? 1 : 0);
```
四角形を二分割したときに、大きくない方の面積を最大化する問題ですね。
「小さい方」ではなく「大きくない方」という表現をされていて不思議に思ったのですが、よく考えたら分割後の面積が同じになる切り方がありました。
そして、その切り方は半分になる切り方であって、「四角形の中心」をとおる切り方ですね。

この切り方は「大きくない方の面積」が最大化する切り方でもあります。
つまり、「与えられた入力の座標」と「四角形の中心」の2点をとおる直線で分割すればいいです。

この時の分割された面積は四角形全体の面積の半分ですね。
これは `w * h / 2.0` です。制約よりオーバーフローに注意です。

また、分割の方法が複数あるかも判定します。
切り方は、上に書いた「与えられた入力の座標」と「四角形の中心」の2点をとおる1通りで複数はありません。
...と思ったのですが、「与えられた入力の座標」と「四角形の中心」が一致していた場合は複数通りありますね。
むしろ無限通りあります。
これは`(x*2 == w && y*2 == h)`で判定できます。



## D - Enough Array

``` c++
	ll n, k;
	cin >> n >> k;
	vector<ll> a(n);

	ll ans = 0, sum = 0;
	int le = 0, re = 1;
	for(int i = 0; i < n; ++i)
	{
		cin >> a[i];
		if (sum < k)
		{
			sum += a[i];
			re = i;
		}
	}
	if (sum < k)
	{
		cout << 0;
		return;
	}
	while(re < n)
	{
		ans += n - re;
		sum -= a[le];
		le++;
		while(sum < k)
		{
			re++;
			sum += a[re];
		}
	}
	cout << ans;
```
しゃくとり法です。
総和が`K`以上になる数列の範囲を覚えておいて、範囲をずらしながら答えの個数を数えています。
プログラムでは、範囲は `[le, re]` としています。left-end と right-end という意味です。

入力をもらいながら総和を計算して、`K`を超えた時点で止めています。

`while`文にくるときは、`[0, re]` の和が`K`以上で、`sum`に入っています。

数列の各要素は正なので、`re = [re, n]` のときも総和が`K`以上ですね。
その個数を`ans += n - re;` で加算します。

そのあと、左端をひとつ進めます。つまり範囲を1つ狭めます。
すると総和が減るので、右端を進めてカバーします。
左端を1進めて右端を1進めればカバーできるわけではないことに注意です。

これを繰り返して答えが出せます。

ちなみに、二分探索で解くこともできます。
解いていないので方針を書くだけですが、累積和を使います。
累積和を計算すると連続する部分数列の和を計算できます。
そこで、和が`K`以上になるところとならないところを二分探索でみつける、という方針です。

以上です。ありがとうございました。
PHP で yield のKeyの文字混在を解消したい


### yield の Keyの全角半角混在が気持ち悪い.....。

```php:混在するyieldサンプル
yield 'piyo：全角だぜ' => [['hoge' => Piyo::piyo];
yield 'fuga:半角だぜ' => [['hoge' => '12:34:56']];
yield 'ここにはコロン入らない前提:ガッツだぜ' => [['hoge' => 'awesome']];
yield 'パワフル：魂' => [['hoge' => 'awesome']];
```

* Keyの中の区切り文字を、全角コロンに統一したい！

### yield のKeyの特定文字(半角コロン）を特定文字（全角コロン）に置き換えだ

**奥義！`Ctrl + R` ( in PHPStorm )**
![RK000310.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239314/697b0f81-92c4-0c77-fd2c-bdba5acdb07a.jpeg)


```text:BEFORE
(yield.+?):(.*?=>)
```

```text:AFTER
$1：$2
```

### 結果

```php:サンプルに噛ませた結果（たぶん）
yield 'piyo：全角だぜ' => [['hoge' => Piyo::piyo];
yield 'fuga：半角だぜ' => [['hoge' => '12:34:56']];
yield 'ここにはコロン入らない前提：ガッツだぜ' => [['hoge' => 'awesome']];
yield 'パワフル：魂' => [['hoge' => 'awesome']];
```

#### 補足

* 正規表現分からないので、考慮漏れがあったら教えてほしいです。
* エディタ置換以外のやり方とかも教えてほしいです。( sed とかもっと分からない）
MoneyForwardクラウド勤怠の打刻を自動化【面倒なことはPythonにやらせよう】

## 免責事項
当記事に掲載された内容によって生じた損害等の一切の責任を負いません。この記事は個人の趣味として執筆したもので、私の所属している企業とは関係ありません。また、企業の規則等を破ることを推奨するものではありません。

## MoneyForwardクラウド勤怠の利用規約について
[利用規約](https://biz.moneyforward.com/agreement)を確認しましたが、コンピューターからの自動操作を禁止している記載は発見できませんでした。（お前見落としてるぞというところに気づいた方がいらっしゃれば、教えてください。すぐにやめます）
> (6) 本サービス並びに本サービスを通じてアクセスするコンテンツサイト及び情報提供元のネットワーク又はシステム等に過度な負荷をかける行為

> (13) 当社による本サービスの運営を妨害するおそれのある行為

過度なアクセスをする処理は含まれていないので問題ないと判断しました。

> (16) その他、当社が不適切と判断する行為

お願いMoneyForwardさん、不適切と判断しないで

## 自動化しようと思った経緯
毎朝同じ時刻に出勤打刻を行い、同じ時刻に退勤打刻を行う。これはもう、完全にwhile文なわけですよ。人がやる作業じゃないでしょ。ということで自動化します。(打刻の意味ねーじゃんというツッコミをお待ちしております）

## 使ったコード
Githubでコードを公開しています。
記事内では全てのコードを載せているわけではないので、もっと知りたい方は直接コードをご覧ください。もっとエレガントな方法があると思うので、気軽にIssueやPR投げてください。お願いします。
https://github.com/Haruka0522/AutoMFKintai

## 全体の構成
Seleniumを使ってPythonから打刻のウェブページにアクセス
↓
datetimeとjpholidayを使って休日/平日の判断
↓
事前に設定した出勤/退勤時刻になったらボタンをクリック

シンプルですね！

## ログイン画面の突破
### ソースコード（抜粋）
```python
id_box = self.driver.find_element_by_name("employee_session_form[office_account_name]")
id_box.send_keys(self.company_id)

mail_box = self.driver.find_element_by_name("employee_session_form[account_name_or_email]")
mail_box.send_keys(self.mail)

password_box = self.driver.find_element_by_name("employee_session_form[password]")
password_box.send_keys(self.password)

login_button = self.driver.find_element_by_name("commit")
login_button.click()
```
ログイン画面にアクセス後、要素の名前で入力ボックスを特定し、そこにログイン情報を入力する処理を行います。この要素の名前というのはchromeでアクセスしてF12キーを押すことで開発者モードを使って確認することができます。
困難が予想されたログイン画面の突破ですが、簡単に突破することが可能でした。

### 注意
ソースコード上にパスワード等をハードコーディングして間違ってGithubにアップしてしまうと大変なので、pass.txtというテキストファイルにパスワード等を書き込んでこれを読み込むような方法を取りましょう。.gitignoreでpass.txtをgitの管理から除いておけば間違ってpushしてしまう心配がありません。

## 打刻ボタンのクリック
### ソースコード（抜粋）
```python
actions = ActionChains(self.driver)
actions.move_by_offset(480, 250)
actions.click()
actions.perform()
```
地味に苦戦したのがここです。打刻ボタンの要素を指定してクリックを試みるもうまくいかず、onclick()が書かれていたので直接Javascriptを実行することを試みるも何故かうまくいきませんでした。そこであまりいい方法ではないですが、画面の座標を指定してクリックするという手法を取りました。最初の設定でChromeのウィンドウサイズを固定しているので、おそらく環境が変わっても動くとは思いますが正直エレガントではないので今後改善したいところです。

## 土日祝、平日の判断
土日に間違って打刻してしまうことは避けたいです。私の場合は基本的に平日は働いているので、平日だけ打刻するように設定しました。
### ソースコード
```python
def is_holiday(date):
    return date.weekday() >= 5 or jpholiday.is_holiday(date)
```
datetimeライブラリとjpholidayライブラリを使用し、平日を判断させました。
datetimeの方は単純な土曜日曜を判断させるために、jpholidayは祝日を判断させるために使用しました。

#### 参考記事
https://qiita.com/hid_tanabe/items/3c5e6e85c6c65f7b38be

## メインループ
```python
while True:
    dt_now = datetime.datetime.now()
    if is_holiday(datetime.date.today()):  # 平日判断
        continue
    if dt_now.hour == start_time.hour and dt_now.minute == start_time.minute:
        operator.syukkin()
    elif dt_now.hour == end_time.hour and dt_now.minute == end_time.minute:
        operator.taikin()
    else:
        time.sleep(wait_time)
```

## 最後に
これを24時間動いてるコンピューター(ラズパイが省電力で良さそう)で走らせることで自動で打刻してくれるようになります。Googleカレンダーなどと連携して独自の休日などにも対応できればいいなー、そもそもこんなスクリプトを書かなくてもいいような制度になればいいなーなどと思っております。各方面から怒られそうな予感がしてますが、大丈夫かな…？
Property 'configuration' and 'configLocation' can not specified with together

spring-boot + mybatis環境で作業中、@MapperScanを追加したところで、エラーが発生。

> Property 'configuration' and 'configLocation' can not specified with together

よく読まずにconfigurationが何か足りないのかなと思って時間を浪費してしまいました。よく読めば『「configuration」と「configLocation」は両方設定できませんせんよ』と書いてある通りでした。

設定ファイルに、mybatis.config-locationとmybatis.configurationを混在させていました。

```properties:application.properties
mybatis.config-location=classpath:/mybatis-config.xml
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=30
mybatis.configuration.cache-enabled=false
```


`mybatis.configuration.*`の項目を`mybatis-config.xml`にうつして解決。


# 環境
- spring-boot:2.3.1
- mybatis-spring-boot-starter:2.1.3 (MyBatis3.5.5)
【Railsアプリ、AWS、SendGrid】550 Unauthenticated senders not allowed

RailsアプリをAWSにあげたらSendGridのメールが送れなくて困った。
レイルズチュートリアルの11章の設定を参考にしたままだった模様。

なので、基本設定はこちらを参考にした。
https://sendgrid.kke.co.jp/docs/Integrate/Frameworks/rubyonrails.html

※ユーザーネームとパスワードはenvファイルを使うこと。
こんな感じ。

```
ENV['SENDGRID_USERNAME']
ENV['SENDGRID_PASSWORD']
```

で、修正したのに以下のエラーが消えない

```
550 Unauthenticated senders not allowed
```

なんで？？と悩むこと1週間ほど。結論を書きます。
①インスタンスを再起動
②nginxを再起動
③Unicornを再起動
②と③は以下を参考にした。
https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1#%E7%A2%BA%E8%AA%8D

EC２サーバーとWEBサーバーとアプリケーションサーバーの3つを再起動する必要があった。
初歩的だけど見落としていた。

![https___qiita-image-store.s3.amazonaws.com_0_91664_962e67f6-6c3e-d441-10fb-24c37aaa7dfc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636310/768160df-477c-1651-c7df-5319bce6ecca.png)
【Rails】Bootstrap3を用いた画像スライドショーの実装

# 目標
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579893/99f925e0-0b2f-7adf-3aed-e09a36fd6597.gif)

# 開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

# 前提

下記実装済み。

・[Slim導入](https://qiita.com/matsubishi5/items/b639ffddecc626856039)
・[Bootstrap3導入](https://qiita.com/matsubishi5/items/b117c95f4dd71340cc80)
・[投稿機能実装](https://qiita.com/matsubishi5/items/1a5aeab651b5822d1f2c)
・[画像複数アップロード機能実装](https://qiita.com/matsubishi5/items/a0ff8ab9a830d2cfcc7e)

# 実装

## 1.ビューを編集

```slim:books/show.html.slim
/ 追記
.row
  #sampleCarousel.carousel.slide data-ride='carousel'
    ol.carousel-indicators
      li.active data-target='#sampleCarousel' data-slide-to='0'
      li data-target='#sampleCarousel' data-slide-to='1'
      li data-target='#sampleCarousel' data-slide-to='2'
    .carousel-inner role='listbox'
      - @book.images.each.with_index(1) do |image, index|
        - if index == 1
          .item.active
            = image_tag image.to_s, class: 'img-responsive img-rounded carousel-image'
        - else
          .item
            = image_tag image.to_s, class: 'img-responsive img-rounded carousel-image'
    a.left.carousel-control href='#sampleCarousel' role='button' data-slide='prev'
      span.glyphicon.glyphicon-chevron-left aria-hidden='true'
      span.sr-only
        | 前へ
    a.right.carousel-control href='#sampleCarousel' role='button' data-slide='next'
      span.glyphicon.glyphicon-chevron-right aria-hidden='true'
      span.sr-only
        | 次へ
```

### 【解説】

#### ① 本に登録されている画像一覧を繰り返し処理し、indexを付与する。

```slim
- @book.images.each.with_index(1) do |image, index|
```

#### ② 1枚目に表示する画像を設定する。

今回は、indexが `1` の画像を設定しています。

```slim
- if index == 1
  .item.active
    = image_tag image.to_s, class: 'carousel-image'
```

#### ③ 2枚目以降の画像を設定する。

```slim
- else
  .item
    = image_tag image.to_s, class: 'carousel-image'
```

## 2.`application.scss`を編集

```scss:application.scss
.carousel-image {
  width: 30%; // スライドに対する画像の幅を設定
  margin: 0 auto; // 画像を中央に配置
}
```
初心者によるプログラミング学習ログ 357日目

#100日チャレンジの357日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
357日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">昨日の作業・やったこと⇩<br>●ブログ1記事作成<br>●プログラミング学習357日目　2.0h<br>・架空LP タブレット版作成(<a href="https://twitter.com/ririru_123?ref_src=twsrc%5Etfw">@ririru_123</a><br><br> ) 2.0h<br>・お問い合わせ<br><br>夜だと忘れるからやっぱり朝に戻そう・・・ｗ<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a> <a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@社畜✕投資✕ブロガー (@ppmp65) <a href="https://twitter.com/ppmp65/status/1278062806772838400?ref_src=twsrc%5Etfw">June 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
3分間ネットワーク備忘録 第３回

## 概要

[前回](https://qiita.com/kenmaro/items/cd95be08d43d63947ff7) に引き続き、
３分間ネットワークの振り返りをしていきます。

今回は、
- [第３回](http://www5e.biglobe.ne.jp/aji/3min/03.html)
- [第４回](http://www5e.biglobe.ne.jp/aji/3min/04.html)
- [第５回](http://www5e.biglobe.ne.jp/aji/3min/05.html)
- [第６回](http://www5e.biglobe.ne.jp/aji/3min/06.html)
- [第７回](http://www5e.biglobe.ne.jp/aji/3min/07.html)

を振り返っていきたいと思います。

### 第３回

主に、ネットワーク通信において、なんらかの取り決めに従って通信が行われており、
その取り決めのことを**プロトコル**と呼ぶ。
プロトコルの例として、**TCP/IP**プロトコルがあること。
データの転送速度を、**帯域幅**（英語ではBand width）と呼ぶこと。

などが解説されていました。


### 第４回

博士が絶対に暗記しろと言っていた、
**ISO** が作った**OSI**参照モデルの７層の名前が解説されました。

上から、

- アプリケーション層
- プレゼンテーション層
- セッション層
- トランスポート層
- ネットワーク層
- データリンク層
- 物理層

となっています。ネット君の覚え方は頭文字をとって、「アプセトネデブ」でした。
どのような形でも良いので名前は覚えときましょう。

### 第５回
１〜４層までのOSI参照モデルの、少しだけ解説がされています。

４：トランスポート層：信頼性の高い通信を保証する働きがある
３：ネットワーク層　：データの転送、運ぶルートの決定、宛先の決定を行う
２：データリンク層　：データ伝送制御を行う（ここでの伝送は、ケーブルで繋がれている機器同士）
１：物理層　　　　　：電気、機械的なルールを取り決める層


となっており、この３分間ネットワークの記事の大半がこの４層を解説することにこれから充てられます。
それだけこの１〜４層が重要だということです。

### 第６回
この記事では、各層によってデータに付与されるヘッダー情報などと、それらが付与されたデータの呼称について解説しています。

レイヤ７〜５層の上位レイヤは制御データをデータに付けませんが、
レイヤ４：トランスポート層：制御データを付与し、付与されたデータが**セグメント**と呼ばれる
レイヤ３：ネットワーク層　：制御データを付与し、付与されたデータが**パケット**と呼ばれる
レイヤ２：データリンク層　：制御データを付与し、付与されたデータが**フレーム**と呼ばれる
レイヤ１：物理層　：フレームをビットに直し、電気信号としてケーブルで伝送する

となります。のちの解説で、それぞれの層がどのような制御情報を組み込んでいくかが解説されます。


### 第７回
「LANを構成するために、君だったら何が必要だと思う？」と博士がネット君に質問するところから始まります。
LAN、つまりローカルネットワークを構成するためには、

- ホスト（PCやプリンタ）
- ネットワーキングメディア（ケーブル）
- NIC （ケーブルとパソコンをつなげるものであり、マザーボードのPCIスロットに差し込まれる）
- データの流れを制御するもの（道路で例えるなら信号）

が必要となります。
最後の`データの流れを制御するもの（道路で例えるなら信号）` ですが、
ネットワーク層、データリンク層、物理層でそれぞれ必要となり、それらは

- ルータ（ネットワーク層で必要）
- ブリッジ、スイッチ（データリンク層で必要）
- ハブ、リピータ（物理そうで必要）

と呼ばれます。


###補足
無線LANについて。３分間ネットワークでは、有線接続が前提で記事が書かれているような印象ですが、
現在では多くの家庭で無線LAN (WiFi)を使っていると思います。
もともとはパソコンを直接電話線を差し込むことでネットワークに繋いでいた**ダイヤルアップ接続**が主流でしたが、
のちに有線LAN,その後に無線LANと便利に、高速になっていきました。
セキュリティが懸念されていた無線LANでしたが、

- WEP
- TKIP
- AES
- WPA/WAP2-PSK

などの暗号化技術を用いて（下に行くほど強固なセキュリティ）、安全に使用することが（基本的に）できています。
また、Wifiの通信範囲がルータから数十メートルの範囲に限られていることから、
ネットワークに侵入しようとしているハッカーの立場からも、身元や場所などの足がついてしまう恐れがあり、あまりWifiに侵入されるようなことは少ないということです。



### まとめ

今回は、３分間ネットワークの第３回から第６回までを振り返り、
最後に無線LANの補足を少しだけ行いました。


引き続き続けていきます。

今回はこの辺で。

おわり。
集合から特定個数取り出す全パターンを求める

#概要
5コの集合から3コ取り出した小集合全パターンを書き出すアルゴリズムを求めます
[こちら](http://www.nct9.ne.jp/m_hiroi/linux/clang04.html#ans09)を参考にしました。

(追記)
便利なライブラリがあるので、そちらを使いましょう。教えてくださった方ありがとうございます。

```python
from itertools import combinations
list(combinations([1,2,4,3],3))
>>[(1, 2, 4), (1, 2, 3), (1, 4, 3), (2, 4, 3)]
```


使用言語はpythonです。![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/2191d47d-4b23-7fbf-a15e-c281fea505a3.png)

#アルゴリズム
2コから3コ取り出す全パターン(取り出しても消えない場合)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/940e9331-a734-b748-9e97-053a5fa365d6.png)


"choice”という全体集合から１つ取り出す関数を作ります。
"choice"で１つ取り出したら、depthを１つ増やして、"choice”をまた呼びます。depthが取り出す個数に達したら、帰ってきます。
これで、全パターンが生成できます。

取り出して消える場合は、"choice"を実行したら、次の"choice"には選んだヤツを除いた全体集合を渡せばよいでしょう。

一つ問題なのは、これだと
[赤、緑]　、[緑　、赤]　という同じパターンが混ざってしまう問題があります。
ここは仕方ないので、同じ要素がないか確認し、有った場合片方を削除します。
もっと良い方法があれば教えてください。

#プログラム

```python

import copy

class Allpattern():
    def __init__(self,n,r):
        self.n = n  #ｎ このうち　rこ　取り出す全パターン
        self.r = r
        self.pattern = []
        used = [0] * self.n
        hoge =[]
        for i in range(r):
            hoge.append(used)
            
    def make(self):
        """
        list1 = [1 , ・・・・ , n] という全体集合を作る
        """
        list1=[]
        for i in range(self.n):
            list1.append(i+1)
        
        """
        choice_list ： choiceしたものを入れるリスト
        depth       : choiceっした回数
        """
        choice_list = []
        depth = 0
        self.choice(list1,depth,choice_list)
        
    def choice(self,list1,depth,choice_list):
        for i in list1:
            list2 = copy.deepcopy(list1)
            list2.remove(i)                           #一回選んだものは二度と選ばない
            choice_list2 = copy.deepcopy(choice_list)
            choice_list2.append(i)
            if depth+1 >= self.r:
                self.work(choice_list2)
            else:
                self.choice(list2,depth+1,choice_list2)
            
    def work(self,choice_list):
        """
        rコの選択が終わったとき呼び出される。
        """        
        choice_list.sort()
        if self.pattern.count(choice_list) == 0:
            self.pattern.append(choice_list)
        
    def disp(self):
        for i in self.pattern:
            print(i)
        
if __name__ == '__main__' :
    hoge = Allpattern(5,3)
    hoge.make()
    hoge.disp()
    
    
```
実行結果

```
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 4]
[1, 3, 5]
[1, 4, 5]
[2, 3, 4]
[2, 3, 5]
[2, 4, 5]
[3, 4, 5]
```
pythonでtwitterのツイート検索をする

#任意アカウントのツイートから検索する

```
$ pip install twint
$ pip install nest_asyncio
```

```python:
import twint
import nest_asyncio

nest_asyncio.apply()

c = twint.Config()
c.Username = "{ユーザーID}"
c.Search = "{検索文字}"

twint.run.Search(c)  #検索実行
```

#クラウドプログラム実行環境
Google Colaboratory（グーグル・コラボレイトリー）
https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja
【Windows】gem install sqlite3ができない

# 環境
ターミナル: MSYS2(mintty+bash+pacman)
Ruby 2.6 + DevKit
Windows10 64bit

# SQLiteのバージョンは問わないという人

SQLite 1.3.13をインストールしよう
コンパイル済だからエラー出ることはないはず。

```
gem install sqlite3 --version 1.3.13 --platform ruby
```

# mkmf.logを見て
[①～package configuration for sqlite3 is not found篇～](https://qiita.com/nicokazu/items/944318dc0ef5746e2b9d)
[②～Cannot create temporary file in C:\篇～](https://qiita.com/nicokazu/items/3f6a6bc4b8f31b300648)
模索中...

# 出てくるエラー
```
C:\Users\foobar>gem install sqlite3 --platform ruby
Temporarily enhancing PATH for MSYS/MINGW...
Installing required msys2 packages: mingw-w64-x86_64-sqlite3
警告: mingw-w64-x86_64-sqlite3-x.xx.x-x は最新です -- スキップ
Building native extensions. This could take a while...
ERROR:  Error installing sqlite3:
        ERROR: Failed to build gem native extension.

    current directory: C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/sqlite3-1.4.0/ext/sqlite3
C:/Ruby26-x64/bin/ruby.exe -r ./siteconfyyyymmdd-foooo-baaaaar.rb extconf.rb
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=C:/Ruby25-x64/bin/$(RUBY_BASE_NAME)
        --with-sqlcipher
        --without-sqlcipher
        --with-sqlite3-config
        --without-sqlite3-config
        --with-pkg-config
        --without-pkg-config
C:/Ruby26-x64/lib/ruby/2.6.0/mkmf.rb:467:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.
        from C:/Ruby26-x64/lib/ruby/2.6.0/mkmf.rb:552:in `try_link0'
        from C:/Ruby26-x64/lib/ruby/2.6.0/mkmf.rb:570:in `try_link'
        from C:/Ruby26-x64/lib/ruby/2.6.0/mkmf.rb:672:in `try_ldflags'
        from C:/Ruby26-x64/lib/ruby/2.6.0/mkmf.rb:1832:in `pkg_config'
        from extconf.rb:35:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  C:/Ruby26-x64/lib/ruby/gems/2.6.0/extensions/x64-mingw32/2.6.0/sqlite3-x.x.x/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in C:/Ruby25-x64/lib/ruby/gems/2.5.0/gems/sqlite3-x.x.x for inspection.
Results logged to C:/Ruby26-x64/lib/ruby/gems/2.6.0/extensions/x64-mingw32/2.5.0/sqlite3-x.x.x/gem_make.out
```
【Windows】gem install sqlite3ができない ～package configuration for sqlite3 is not found篇～

# 原因
SQLiteのソースファイルが欠損している

# 解決
MSYS2コンソールで以下のコマンドを実行

```bash
pacman -S libsqlite-devel
```

あとはコマンドプロンプトでも良いのでgem install sqlite3 --platform rubyを実行します。

# エラー内容
```
package configuration for sqlite3 is not found
"x86_64-w64-mingw32-gcc -o conftest.exe -IC:/Ruby26-x64/include/ruby-2.6.0/x64-mingw32 -IC:/Ruby26-x64/include/ruby-2.6.0/ruby/backward -IC:/Ruby26-x64/include/ruby-2.6.0 -I. -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048 -D_WIN32_WINNT=0x0600 -D__MINGW_USE_VC2005_COMPAT -D_FILE_OFFSET_BITS=64  -O3 -fno-fast-math -fstack-protector-strong conftest.c  -L. -LC:/Ruby26-x64/lib -L. -pipe -s -fstack-protector-strong     -lx64-msvcrt-ruby260  -lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi  "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <winsock2.h>
4: #include <windows.h>
5: int main(int argc, char **argv)
6: {
7:   return 0;
8: }
/* end */
```
【Windows】gem install sqlite3ができない ～Cannot create temporary file in C:\篇～

# 原因
Windowsのユーザ名に2バイト文字(日本語)が使われている

# 解決
Tempファイルの位置を移動させる。
コマンドプロンプトで以下を実行

```
mkdir C:\temp
set TEMP=C:\temp
set TMP=C:\temp
```
日本語が使われていなければどのディレクトリでも大丈夫です。
あとはコマンドプロンプトでも良いのでgem install sqlite3 --platform rubyを実行します。

# エラー内容
```
"pkg-config --exists sqlite3"
| pkg-config --libs sqlite3
=> "-LC:/msys64/mingw64/lib lsqlite3\n"
"x86_64-w64-mingw32-gcc -o conftest.exe -IC:/Ruby26-x64/include/ruby-2.6.0/x64-mingw32 -IC:/Ruby26-x64/include/ruby-2.6.0/ruby/backward -IC:/Ruby26-x64/include/ruby-2.6.0 -I. -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048 -D_WIN32_WINNT=0x0600 -D__MINGW_USE_VC2005_COMPAT -D_FILE_OFFSET_BITS=64  -O3 -fno-fast-math -fstack-protector-strong conftest.c  -L. -LC:/Ruby26-x64/lib -L. -pipe -s -fstack-protector-strong     -lx64-msvcrt-ruby260  -lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi  "
Cannot create temporary file in C:\Users\??????\AppData\Local\Temp\: Invalid argument
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <winsock2.h>
4: #include <windows.h>
5: int main(int argc, char **argv)
6: {
7:   return 0;
8: }
/* end */
RPAといままでの自動化の違いについてまとめてみた

RPAを導入する際に、特に技術者から出てくる意見として**「いままでの自動化と何が違うの？？」「それExcelマクロやVBAでもできますよね？」「UWSC、VBS/JScript/PowerShell/Python+Selenium、SikuliXでやったほうが無料だしいいよね？」**といった話があがります。RPAといままでの自動化について、何が違うのか、要点をまとめてみました(^^)/

# ポイント1: プログラミングができない非技術者でも使える
まず、「RPAじゃなくても自動化できちゃうよ」というRPA不要論を唱える人はほとんどが技術者(特にプログラマ/開発者)です。技術者であれば、自分のプログラミング技術を使って様々な言語と無料のツールを使って自動化を行えてしまいます。UIの操作も基本はマウスとキーボードのエミュレーションであり、正しく操作するための要素分解もWindowsやブラウザーのAPIやDOMを使って行っているため、これらを外部から呼び出せば同じことができてしまいます( ﾟДﾟ)

RPAの価値は、これらのことが**「ノーコード/ローコードでできる」「技術者でなくてもできる」**といったところにあります。ただし、いま最も広がっているWinActorやUiPathは、ちょっと高度なことをやろうとするとコーディングが要求されるために、このことが誤解のもとになっているかもしれませんがね...


# ポイント2: 自動化の管理機能やツールが付属
RPA不要論でほとんど語られることがないのが**「作った自動化プログラムの管理はだれがするのか」**という観点です。(運用管理は開発者/プログラマの観点ではなく、インフラ技術者の観点なので、ここで分断が起こっている可能性もありますね...) これも、いま最も広がっているデスクトップ型RPA (Robotic Desktop Automation, RDA)にはこの機能がないので、やはり誤解の元になっている可能性があります。

組織で実際に自動化の運用を行う際は、作った複数の自動化プログラムをスケジューリング実行させる、複数のPCで分散実行させる、実行履歴のログを管理する、など、**数々の管理業務をこなす必要があります**。サーバー型RPAにはこれらが標準機能として搭載されているため、自動化ロジックの構築だけでなく、運用管理まで含まれたソリューションとなっています(^_-)-☆


# ポイント3: 導入する際の総コストと手間
プログラミングができる技術者をプロジェクトに入れる場合、月100万円くらいの費用が最低かかります。**無料のプログラミング言語やツールを使って自動化を行う場合でも、ツールは無料でも技術者の費用がかさみます**。

RPAの場合は、最初の3カ月くらいはスキル移転のために外部の技術者やコンサルを雇ったりしますが、長期的には内製化して、プログラミングができない従業員を主要メンバーとしてRPAプロジェクトを回していくことになります。その際、**きちんと内製化ができ、教育も安価、または無償で受けることができる手段があり、書籍やオンラインドキュメントが充実しているサーバー型のRPAツールを選んでおけば**、技術者を使った従来の自動化手法と比べて、RPAソフトウェア自体に年額100万円くらい払ったとしても全体の総コストは下がっていくでしょう。


# まとめ: RPAでなくても自動化はできるが、RPAは単なる自動化だけを行うのではありません
いかがでしたでしょうか？RPAでなくても同等の自動化業務を行わせることは可能ですが、それをプログラムがかけない人が行えるかどうかが異なってきます。また、自動化の作成だけでなく運用・管理もできるかどうかも異なります。最終的に、人員の運用や教育まで含めたときに総保有コストが異なってきます。RPAは単純に自動化だけを行うのではなく、**「オートメーションの民主化」**により、誰でも手軽に自動化が行えるようにする、というところに、いままでの自動化とは違う価値があるように思われます！



# 参考記事

* [RPAといままでの自動化の違いは?](https://autodojo.hatenablog.com/entry/rpa-vs-normal-automation)
* [officeの杜 - RPA導入に於ける注意点](https://officeforest.org/wp/2019/03/22/rpa%E5%B0%8E%E5%85%A5%E3%81%AB%E6%96%BC%E3%81%91%E3%82%8B%E6%B3%A8%E6%84%8F%E7%82%B9/)
* [SikuliをRPAとして使ったときの注意点とは【理解して使いましょう】](http://marukentokyo.jp/2019/05/13/sikuli%E3%82%92rpa%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E6%B3%A8%E6%84%8F%E7%82%B9%E3%81%A8%E3%81%AF%E3%80%90%E7%90%86%E8%A7%A3%E3%81%97%E3%81%A6%E4%BD%BF/)
* [RPAを支える技術についての解説](https://qiita.com/RPAbot/items/9d87e9292ac2deded338)
OpenAPI Generator で Deno クライアントの生成が可能になりました

[OpenAPI Generator](https://openapi-generator.tech/) で [Deno](https://deno.land/) クライアントの生成が可能になりました。
私が PR を作成し無事？マージされました。
使い方についてご紹介したいと思います。

## openapi-generator-cli のダウンロード

まずは、openapi-generator-cli をダウンロードします。
せっかくなので？ deno コマンドでダウンロードしてみます。

```
$ deno eval 'fetch("https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/5.0.1/openapi-generator-cli-5.0.1.jar").then(r=>r.arrayBuffer()).then(b=>Deno.writeFile("openapi-generator-cli.jar",new Uint8Array(b)))'
```

## コードの生成

openapi-generator-cli は、Java で作成されていますので、JDK がインストールされている必要があります。
次のコマンドでクライアントコードを生成します。
`--additional-properties` の `platform` に `deno` が指定できるようになっています。

```
$ java -jar openapi-generator-cli.jar generate -i https://petstore.swagger.io/v2/swagger.json -g typescript --additional-properties=platform=deno -o generated-src
```

`generated-src` ディレクトリ配下にファイルが生成されます。

## 生成されたコードの利用

次の内容で `test.ts` というファイルを作成します。

```typescript
import * as petstore from "./generated-src/index.ts";

const configuration = petstore.createConfiguration();
const petApi = new petstore.PetApi(configuration);
const pets = await petApi.findPetsByStatus(["available"]); // status が available のデータを取得します
console.log(pets.slice(0, 5)); // レスポンスの最初の5件だけ表示
```

次のコマンドで実行します。
ホスト petstore.swagger.io の API を利用しています。

```
deno run --allow-net=petstore.swagger.io test.ts
```

実行結果は、以下のようになります。

```
[
  Pet {
    id: 1245,
    category: Category { id: 1245, name: "xyz" },
    name: "xyz",
    photoUrls: [ "test" ],
    tags: [],
    status: "available"
  },
  Pet {
    id: 112256,
    category: Category { id: 0, name: "dog" },
    name: "Rex",
    photoUrls: [ "http://example.com/images/rex.png" ],
    tags: [],
    status: "available"
  },
  Pet {
    id: 112258,
    category: Category { id: 0, name: "dog" },
    name: "Rex",
    photoUrls: [ "http://example.com/images/rex.png" ],
    tags: [],
    status: "available"
  },
  Pet {
    id: 12121,
    category: Category { id: 0, name: "string" },
    name: "TestPetName",
    photoUrls: [ "string" ],
    tags: [ Tag { id: 0, name: "string" } ],
    status: "available"
  },
  Pet {
    id: 112270,
    category: Category { id: 0, name: "dog" },
    name: "Rex",
    photoUrls: [ "http://example.com/images/rex.png" ],
    tags: [],
    status: "available"
  }
]
```

## おわりに

生成されたコードは、Deno の fetch API を利用しています。
正直なところ、 fetch API だと機能不足であり、もうちょっと高機能な HTTP クライアントが Deno に標準で入らないかなーと思っているところです。

以上です。
http_proxyの挙動確認

# はじめに

localhostへの通信さえもプロキシサーバを通るように設定できると聞いたので、実験。

# 環境

* Ubuntu18.04
* bash

# 実験

## proxy設定前
```shell
$ curl http://google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
```

## proxy設定後

1行目でproxyの設定をしている。

実際にはプロキシサーバを立ててないので `localhost:9999` に繋げないが、プロキシサーバに繋ごうとしているのが分かる。


```shell
$ export http_proxy=localhost:9999
$ curl http://google.com
curl: (7) Failed to connect to localhost port 9999: Connection refused
```

## proxyを通らないホストを指定

1行目でproxyを通らないホストを指定している。

プロキシサーバを通らずにhttpアクセスできた。

```shell
$ export no_proxy=google.com
$ curl http://google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
```


# おわりに

プロキシの設定について少し賢くなった。
PRML 演習問題 5.17 解答

##問題
>二乗和誤差関数を考える.

```math
\begin{align*}
\mathrm{E=\frac{1}{2}\iint\bigl\{y(x,w)-t\bigr\}^2p(x,t)dxdt}
\tag{5.193}
\end{align*}
```

>ここで$\mathrm{y(x,w)}$はニューラルネットワークのようなパラメトリックな関数である. (1.89)の結果はこの誤差を最小化する関数$\mathrm{y(x,w)}$が$\mathbf{x}$が与えられたときの$\mathbf{t}$の条件付き期待値で与えられていることを示している.

```math
\begin{align*}
\mathrm{y(x)=\frac{{\int}tp(x,t)dt}{p(x)}={\int}tp(t|x)dt=E_t[t|x]}
\tag{1.89}
\end{align*}
```

>この結果を使って, ベクトル$\mathbf{w}$の2つの要素$\mathbf{w_r}$と$\mathbf{w_s}$に関する$\mathbf{E}$の2階微分が

```math
\begin{align*}
\mathrm{\frac{{\partial}^2E}{{\partial}w_r{\partial}w_s}=\int\frac{{\partial}y}{{\partial}w_r}\frac{{\partial}y}{{\partial}w_s}p(x)dx}
\tag{5.194}
\end{align*}
```

>で与えられることを示せ.ここで, $\mathrm{p(x)}$から有限個サンプリングする場合には(5.84)が得られることに注意せよ.

```math
\begin{align*}
\mathrm{H=\nabla\nabla{E}=\sum^N_{n=1}\nabla{y_n}(\nabla{y_n})^T+\sum^N_{n=1}(y_n-t_n)\nabla\nabla{y_n}}
\tag{5.83}\\
\end{align*}
```

(5.83)の第2項以降を無視した式が(5.84)である.

```math
\begin{align*}
\mathrm{H\simeq\sum^N_{n=1}b_nb_n^T}
\tag{5.84}
\end{align*}
```

##方針
まず(5.193)を$\mathbf{w}$の2つの要素$\mathbf{w_r}$と$\mathbf{w_s}$に関する$\mathbf{E}$の2階微分をとり, (5.194)に帰着することを示す.
##解答
・(5.193)から(5.194)の導出

```math
\begin{align*}
\mathrm{E}&=\mathrm{\frac{1}{2}\iint\bigl\{y(x,w)-t\bigr\}^2p(x,t)dxdt}\\
まずは\mathbf{w_r}で微分する.\\
\\
\mathrm{\frac{\partial{E}}{\partial{w_r}}}&=\mathrm{\frac{1}{2}{\iint}\frac{\partial}{\partial{w_r}}\bigl\{(y-t)^2p(x,t)\bigr\}dxdt}\\
&=\mathrm{\frac{1}{2}{\iint}\frac{\partial{y}}{\partial{w_r}}\frac{\partial}{\partial{y}}\bigl\{(y-t)^2p(x,t)\bigr\}dxdt}\\
ここで\mathrm{\frac{\partial}{\partial{y}}}を実行\\
\\
&=\mathrm{\iint\frac{\partial{y}}{\partial{w_r}}(y-t)p(x,t)dxdt}\\
つぎに\mathbf{w_s}で微分する.　式変形は\mathbf{w_r}で微分した時と同じ\\
\\
\mathrm{\frac{\partial{E}}{\partial{w_r}\partial{w_s}}}&=\mathrm{\iint\frac{\partial{y}}{\partial{w_r}}\frac{\partial{y}}{\partial{w_s}}p(x,t)dxdt}\\
\\
ここで\mathrm{t}で積分することで\mathrm{p(x,t)}の\mathrm{x}軸への周辺確率を計算する.\\
\\
\mathrm{\frac{\partial{E}}{\partial{w_r}\partial{w_s}}}&=\mathrm{\int\frac{\partial{y}}{\partial{w_r}}\frac{\partial{y}}{\partial{w_s}}p(x)dx}
\end{align*}
```

以上より(5.193)を$\mathbf{w}$の2つの要素$\mathbf{w_r}$と$\mathbf{w_s}$に関する$\mathbf{E}$の2階微分をとることで(5.194)が得られることが示された.
Cognos Analytics でレポートやダッシュボードを自分の好きなURLで実行する

#レポートやダッシュボードを好きなURLで実行する
これは覚えておくと、いつかどこかで役に立つかも知れません。
こんな感じに、レポートを呼び出すURLを、自分の好きな独自のURLで呼び出す方法です。
<img width="960" alt="003.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/36254c0f-ded7-2333-dca1-3263d73f0cdb.png">

ただし、IHSやIISで実装する、Optional Gatewayの環境じゃないとダメなようです。
つまり、http://CognosHost/ibmcognos みたいな、80番ポートでアクセスする環境ですね。

#実装方法
URL呼び出ししたいレポートやダッシュボードのエントリで、「・・・」から「共有」を開き、下の組み込みコードの方で「コピー」します。
<img width="785" alt="001.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/4046fd1a-5b4a-9ee0-3510-5e723f747a6c.png">

メモ帳等にコピーしたURLを貼り付けて、width、heightを適当に調整して保存。
<img width="495" alt="002.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/b16eb61e-ad5d-20de-bcf0-e6715f2d2cf0.png">

保存したファイルを、Cognosサーバー上の\<CognosInstall>\webcontent配下に好きなディレクトリを作成して保存します。
今回は、webcontentの下にreports01というディレクトリを作成して、その下に「Nebraska」というファイル名で置いてます。※.txt拡張子は外しました

ブラウザで以下のURLを入力すると、レポートが呼び出されます。
http://CognosHost/ibmcognos/reports01/Nebraska
<img width="960" alt="003.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/2dcfc144-9b94-25f6-a472-62ed878b8203.png">

ダッシュボードでも行けました。
<img width="960" alt="004.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/6ecb84ad-e066-ca09-ab6a-a84252b3681a.png">

これちょっと使えるかもですね。

#元ネタ
**How to create custom URL for Cognos Report/Dashboard**
https://community.ibm.com/community/user/businessanalytics/blogs/dinesh-k-dhiman1/2020/06/11/how-to-create-custom-url-for-your-cognos-report?CommunityKey=6b10df83-0b3c-4f92-8b1f-1fd80d0e7e58&tab=recentcommunityblogsdashboard
日本語対応したDeepL APIを使用して、「STT→DeepL→TTS」の同時通訳を試作してみた

##はじめに
DeepL Proが日本語に対応したということで、UnityでDeepL APIを試してみました。
せっかくなので、同時通訳っぽいものを作れたら楽しいなと思い、
**STTで音声をテキスト化
↓
DeepLにテキストを渡し、翻訳されたテキストを返してもらう
↓
翻訳されたテキストをTTSで音声出力**
の流れで組み込みました。

（作業環境…Unity 2019.3.1f）
##STTとTTS
今回、STTとTTSは無料で手軽に試せるIBMのWatsonを使用しました。
2020年7月現在、Unity Asset StoreからWatson SDKは入手できなくなっているので、
https://github.com/watson-developer-cloud/unity-sdk
上記からダウンロードし、Unityプロジェクトにインポートする必要があります。

STT、TTS共にサンプルシーンがあるので、今回はそこで使用されているサンプルコードをほぼそのまま流用しました。
（IBM Cloudにログインして、STTとTTSを作成し、それぞれのAPIキーとURLを利用してください）
ただSTTについては、認識された発話が垂れ流しになるのを防ぐため、
Confidence（確信度）が0.5以上になった時を確定して、DeepLに投げるようにしました。

STTで認識したい言語は下記を、
https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-models&locale=ja
TTSで認識したい言語は下記を参考にしてください。
https://cloud.ibm.com/docs/text-to-speech?topic=text-to-speech-voices&locale=ja

##DeepL API
DeepL API ドキュメント：https://www.deepl.com/docs-api/introduction/

APIの呼び出しにはUnityWebRequestを使用しました。
（参考：https://kan-kikuchi.hatenablog.com/entry/UnityWebRequest ）
APIをPOSTで呼んでいます。

```DeepLReceiver.cs
    [SerializeField]
    string lang;//翻訳したい言語を指定

    private IEnumerator DeepLTranslate(string text)
    {
        
        string base_word = text;
        
        WWWForm form = new WWWForm();
        form.AddField("auth_key", [KEY]);
        form.AddField("text", base_word);
        form.AddField("target_lang", lang);

        UnityWebRequest request = UnityWebRequest.Post("https://api.deepl.com/v2/translate", form);
       
        yield return request.SendWebRequest();
        
        if (request.isHttpError || request.isNetworkError)
        {

            Debug.Log(request.error);
        }
        else
        {
            readJson = request.downloadHandler.text;
            Debug.Log(request.downloadHandler.text);
            JsonRead(readJson);
        }
    }
```


DeepLからは下記のようなJsonが返ってくるので、

```
{
	"translations": [{
		"detected_source_language":"JA",
		"text":"Hallo, How are you?"
	}]
}
```
翻訳されたtextだけを取り出して、TTSに渡せるようにします。

```DeepLReceiver.cs
    [Serializable]
    public class RESPONSEJSON
    {
        public RESPONSE[] translations;
    }
    [Serializable]
    public class RESPONSE
    {
        public string detected_source_language;
        public string text;
    }

    string ttsText;

    private void JsonRead(string json)
    {
        string inputString = json;
        RESPONSEJSON responseJson = JsonUtility.FromJson<RESPONSEJSON>(inputString);
        ttsText = responseJson.translations[0].text;
    }

```



##実際に遊んでみた動画
即席試作といえども、画面に文字だけでは味気ないので、
弊社のオリジナルキャラクター、「ハニカ」に翻訳文を喋らせました。
（Watson TTSの声質が微妙だけど、キャラクターがいるとやっぱり見栄えが可愛い）
↓是非動画でご覧ください。クリックで再生されます。
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/f8cBwGKVoxk/0.jpg)](http://www.youtube.com/watch?v=f8cBwGKVoxk)
**動画内の遊んだ履歴：**
日本語→英語
日本語→スペイン語
中国語→フランス語
英語→日本語
ドイツ語→英語
（楽しかったので日本語以外でも遊んでみました）

文字数にもよりますが、STTからテキストが渡って翻訳→TTSにのって音声出力、までは
体感で2秒かからないくらいですね。
実用する場合には、ここの処理時間なども正確に計測しておきたいところです。
PHP PhalconでAuto Increment付与のMigrationが動かない対応

# はじめに
PhalconにおいてMigrationで新テーブルをCreateする場合は普通に定義すればAuto Incrementは簡単につけられます。
本記事は、既存テーブルのKeyカラムにAuto IncrementをAlterで後から付けたかったが動かなかったので、その対応をしたという話です

# 最初は
普通に列変更でいけると思っていたので最初、`up()`に新、`down()`に旧を`morphTable()`で書けばいいやとしてみました。

```php
public function up()
{
    $this->morphTable('table_name', [
        'columns' => [
            new Column(
                'id',
                [
                    'type' => Column::TYPE_INTEGER,
                    'notNull' => true,
                    'autoIncrement' => true,
                    'size' => 11,
                    'first' => true
                ]
            ),

            /* 省略(その他のカラム情報) */
        ]
    ]);
}


public function down()
{
    $this->morphTable('table_name', [
        'columns' => [
            new Column(
                'id',
                [
                    'type' => Column::TYPE_INTEGER,
                    'notNull' => true,
                    'size' => 11,
                    'first' => true
                ]
            ),

```
ところが、これだとうまく動かない。
Migration自体の結果はsuccessとなるが、この例で言うidカラムのAlterを実行している形跡がないぞ、、と困ってしまいました

# そこで
じゃあ明示的にSQL書いたりとかそういうのできないのかなと思って、ちょっと調べてみると、 `self::$_connection`に、イケそうなMethodがあるではありませんか。
（そう言えばdropTableの時にいつも使っているやつだったな）
ということで

```php
public function up()
{
    self::$connection->modifyColumn('table_name', null, new Column(
        'id',
        [
            'type' => Column::TYPE_INTEGER,
            'notNull' => true,
            'autoIncrement' => true,
            'size' => 11,
            'first' => true
        ]
    ));
}

```
できたやんけー。という感じでした。
加えて`morphTable()`で記述していた時は、カラムが多い時に見づらくてちょっと不満があったのですが、この書き方だと純粋に変更箇所だけの記載になるので、これはこれでいいかもな。とも思ったのでした
wordpress学習(2020//07/01)

###カスタムフィールド
```php:sample.php
$price = get_post_meta(get_the_ID(), '価格', true);

echo $price;
```
get_post_meta();　カスタムフィールドの値を取得する関数　
get_the_ID()　今表示している投稿のid
'価格' カスタムフィールドの価格を選択
true　文字列として単一の結果を返す。カスタムフィールドが一つならtrue。


###Advanced　Custum　Fields (ACF)
プラグイン。カスタムフィールドというメニューが追加される。カスタムフィールドをより細かく設定できる。
インストール後、以下のテンプレートタグが追加される。

```php:sample.php
the_field('価格');

get_field('価格');
```
上は$price = get_post_meta(get_the_ID(), '価格', true);
echo $price;
と同じように表示される。
下は表示せず取得だけ。

###カスタム投稿タイプ
投稿、固定ページだけでなく新しい投稿タイプを追加する。


```php:sample.php
register_post_type('item',[
  'labels' => [
    'name' => '商品',
  ],
  'public' => true,
  'has_archive' => true,
  'hierarchical' => false,
  'supports' => [
    'title',
    'editor',
    'page-attribites'
  ],
  'menu_position' => 5,
  'menu_icon' => '',
  ]
]);
```

function.phpに書いていく。パラメータに投稿タイプ名を指定。
配列で指定する。
itemはurlにも使われる。
labelsの指定はさらに多くある。
publicの部分で表示するように指定する。
has_archiveの部分は一覧ページを持つかどうかを指定。
hierarchical固定ページのようにページの階層があるようにするか投稿のようにするか。
menu_positionは管理画面のメニューのどこに置くかを指定。
menu_iconはメニューアイコンを指定。dashiconというwordpressで提供されているiconを付けることができる。

この場合、wordpressの管理画面のメニューに商品というメニューが追加される。
新規追加でタイトルと本文を入力でき公開をクリックするとURLも変更できる。

ポストタイプを新しく作ったときはパーマリンク設定で変更を保存する。


####「商品」の投稿ページにカスタムフィールドが表示されるよう変更する

ADCプラグインで追加したメニューにあるカスタムフィールドのフィールドグループをクリック。
作ったカスタムフィールドをクリックし、ルールの投稿となっている部分を作成したポストタイプ,商品に変更する。
【Solidity】ストレージとメモリー

Solidityの変数はストレージ、又はメモリーに格納できる。
パソコンのハードディスクとRAMと同じようなイメージでOK。
それぞれの特徴をまとめておく。

# storage
ブロックチェーン上に永久に格納される変数。
状態変数（関数外で宣言された変数）はデフォルトでstorageになる。

storageに保存されるデータはブロックチェーンに格納される = 全てのノードで保存されるということになるため、非常にコスト（gas）が高い。

# memory
コントラクト実行時のみ保持される変数。
そのため、ブロックチェーンに保存されることはない。
ブロックチェーンに保存されないため、コストもかからない。

関数内で宣言された変数はデフォルトでmemoryになる。
関数の実行が完了すれば消えてしまう。（ローカル変数が関数外で使用できないのと同じイメージ）

尚、memoryの配列は必ずサイズを指定して作成する必要がある。

# サンプル
```solidity:
contract GameFactory {
  struct Game {
    string name;
    string status;
  }

  // 状態変数（関数外の変数）はデフォルトでstorageになる
  Game[] games;

  function clearGame(uint _index) public {
    // この場合はコンパイラがstorageかmemoryを指定しろと警告してくれる
    // Game myGame = games[_index];

    // ブロックチェーン内のgames[_index]への参照(ポインタ)が格納される
    Game storage myGame1 = games[_index];
    // そのためブロックチェーンを直接更新できる（games[_index].statusも"clear"になる）
    myGame1.status = "clear";

    // 値をコピーするだけならmemoryを使用する
    Game memory myGame2 = games[_index + 1];
    // 一時的にコピーした値を変更しているだけなので、games[_index + 1].statusは変更されない
    myGame2.status = "clear";

    // memoryの内容をブロックチェーンに反映したい場合
    games[_index + 1] = myGame2;

    // memoryの配列は必ずサイズを指定する
    uint[] memory values = new uint[](3);
    values.push(1); 
  }
}
```
GO言語　複数のマップをマージ する



逆引きGolangには2つのマップをマージするやり方が書いてあったが、
今回は2つ以上のマップをマージする可変長引数関数を作ってみた。
これにより、マップを幾つでもマージしてくれる。


```golang

func merge(m ...map[string]interface{}) map[string]interface{} {
	ans := make(map[string]interface{}, 0)

	for _, c := range m {
		for k, v := range c {
			ans[k] = v
		}
	}
	return ans
}
```


## 参考文献
逆引きGolang　(https://ashitani.jp/golangtips/tips_map.html#map_Merge)
Gitとは？GitHubとは？さらっとイメージを理解するためのまとめ

# Gitとは？
gitとは、ソースコードを始めとするファイルの変更履歴を管理するためのシステム。
変更履歴を記録するシステムのことをバージョン管理システムと言う。

フォルダに日付をつけて管理してったりすると訳わかんなくなったりするので、gitを使って管理してくのが良いみたい。

# なぜGitを使うの？
ファイルの変更履歴を管理するため
何か問題があったときに過去のファイルに戻れるようにしておくため。

# GitHubとは？
- gitの仕組みを利用したwebサービスのこと。
- gitの機能に対してチーム開発に便利な機能と付け加え、gitにおけるリモートリポジトリの役割も担っている。
- github上にチームで共有のプロダクト（ソースコード）を配置し、開発者はgithub上からソースコードをコピーしたり、ソースコードをgithub上のリポジトリに反映させることが出来る

世界中にコードを公開することでいろいろな方からレビューもいただけることもメリット

# GitHub Desktopとは？
github desktopとは、gitを扱うためのGUIツールの一つ
github desktopは、githubが提供しているGUIツール

本来ターミナルで実施するGitの作業をGUIを用いて直感的に操作できる

# リポジトリとは？
リポジトリとは、Gitで変更履歴を管理しておくための入れ物。
このリポジトリにファイルやディレクトリの変更履歴を記録しておく。

# ローカルリポジトリとは？
自分のPC上（ローカル環境）に置くリポジトリのこと。
自分のPC上にあるファイルやディレクトリのバージョン管理を行いたいときに使う。

# リモートリポジトリとは？
外部のサーバーなどのネットワーク上に置くリポジトリのこと。GitHubはこちらのイメージ。


# リモートリポジトリのメリットは？
ネットワーク上に置くことで、複数人で管理下のファイルやディレクトリを共有することが出来る。
ローカル環境下で問題が起こったとしても、またリモートリポジトリからダウンロードを行うことで元に戻すことが出来る

# クローンとは？
リモートリポジトリの内容をまるまる複製して別のマシンのローカルリポジトリを作成すること。

# コミットとは？
ディレクトリやファイルの状態を記録するための操作。
コミットすることで現在の状態が、日時や変更を加えた人の情報を含めて一緒に保存することが出来る。

# インデックスとは？
バージョンを記録するためにファイルを一時的に登録する場所。同じバージョンとして記録したい編集についてはまとめてインデックスに追加し、このタイミングでは記録したくない編集についてはインデックスに追加しない。
インデックスに追加したものをコミットすることで変更が保存される。変更してはコミットして、変更してはコミットしてだと何度もGitの操作が必要となり非効率ということで生まれた考え方。

# コミットメッセージって何故書くの？
コミットする際に添えるメッセージのことをコミットメッセージという。
そのコミットでどのような作業をしたのかということを記録しておくために記述する。

# コミット時に注意すべきこと
なるべく細かく行う。１機能１コミットがベター。ファイルをもとに戻すことになった場合、コミットごとでしか戻せないから。

# プッシュとは？
ローカルリポジトリで加えた変更とリモートリポジトリに同期させること。
ローカルでコミットが終わり、リモートに変更を同期させたい場合には必ずプッシュを行う必要がある。

# ブランチとは？
- リポジトリで管理をしているプロジェクトの履歴の1つ。
- 自分の作業をしている場所のこと。
- ブランチ同士は独立しているため、それぞれのブランチが干渉していない。
- 開発者ごとに担当する機能を明確に分けることが出来る
- 完成途中や問題のあるソースコードをリリースしないで済む。
- 複数人で開発する時にメインのアプリを枝分かれ（複製）させてそれぞれで開発し、終わったらメインへ結合（マージ）する。

# プルとは？
リモートリポジトリの変更履歴をローカルリポジトリに反映させる操作のこと。

#プルリクエスト（プルリク）とは？
作成したブランチをmasterブランチにマージをするときの確認作業のこと。
１つのブランチ作業においてコミュニケーションが取れる掲示板のようなもの
そのコードに問題が無いかどうかを他の開発者や上司に確認を行うためにプルリクエストを見て貰う。

# マージとは？
ブランチとブランチを結合すること。

# LGTMとは？
「コードに問題が無いので、マージをして大丈夫ですよ！」ということ

# デプロイとは？
ソースコードを本番環境に設置し、稼働させること

# コンフリクトとは？
複数の人が同じ箇所を編集してしまい、変更箇所を自動では判断できすにマージできなくなること。


# Github Flowとは？
開発フローのルール的なもの
- masterブランチは常にデプロイ可能である
- 作業用ブランチをmasterから作成する
- 作業用ブランチを定期的にプッシュする
- プルリクエストを活用する
- プルリクエストが承認されたらmasterへマージする
- masterへのマージが完了したら直ちにデプロイを行う
学会のプログラムからWord Cloudを作成

#はじめに
先日参加した人工知能学会(JSAI2020)のトレンドを調べようと思い、プログラムの講演タイトルからWord Cloudを作成しました。
#Word Cloudとは
文章中の単語の出現頻度を調べ、頻度に応じて文字の大きさを変えて図示するものです。ツイートからWord Cloudを作成して、多く呟いている単語を可視化したものなどを見たことがある方もいるのではないでしょうか。
#テキストの用意
[こちら](https://www.ai-gakkai.or.jp/jsai2020/proceedings)からJSAI2020の大会論文集をダウンロードし、index.htmlというファイルを開いてセッション一覧をメモ帳にコピペしました。

プログラムがPDFで公開されている場合は次のようにしてテキストを抽出するといいと思います。

```python

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage

input_path = './Program.pdf'
output_path = 'Program.txt'

manager = PDFResourceManager()

with open(output_path, "wb") as output:
    with open(input_path, 'rb') as input:
        with TextConverter(manager, output, codec='utf-8', laparams=LAParams()) as conv:
            interpreter = PDFPageInterpreter(manager, conv)
            for page in PDFPage.get_pages(input):
                interpreter.process_page(page)
```

#必要ない情報を削除
日付や発表者など、講演タイトル以外の情報をテキストから削除します。発表者は()で囲まれていたので()の中の文字を‍‍‍‍削除しました。()の中の文字や時刻・日付の指定は正規表現を使っています。

```python
import re

with open('Program.txt', mode='rt', encoding='utf-8') as fo:
    Program = fo.read()

#[]を()に変換
Program = Program.replace("[", "(")
Program = ProgramP.replace("]", ")")
#()で囲まれている文字を削除(この時[]だと削除できないため上記のコードが必要)
Program = re.sub(r'\([^)]*\)', '', Program)
#時刻・日付を削除
Program = re.sub(r'((0?|1)[0-9]|2[0-3])[:][0-5][0-9]?', '', Program)
Program = re.sub(r'2020年([0-1]?[0-9])月([0-3]?[0-9])日?', '', Program)
Program = re.sub('時間・会場', '', Program)
Program = re.sub('セッション', '', Program)
Program = re.sub('発表一覧', '', Program)
Program = re.sub('会場', '', Program)

with open('Program_new.txt', 'w') as f:
  print(Program, file=f)
```
#Word Cloudの作成

```python
from matplotlib import pyplot as plt
from wordcloud import WordCloud

with open('Program_new.txt', mode='rt', encoding='utf-8') as fo:
    cloud_text = fo.read()

#font_pathは自分の端末にある日本語フォントを指定
word_cloud = WordCloud(width=640, height=480, font_path="/System/Library/AssetsV2/com_apple_MobileAsset_Font6/c7c8e5cb889b80fff0175bf138a7b66c6f027f21.asset/AssetData/ToppanBunkyuMidashiGothicStdN-ExtraBold.otf").generate(cloud_text)
word_cloud.to_file('wordcloud4.png')

plt.imshow(word_cloud)
plt.axis('off')
plt.show()
```
![wordcloud3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405222/b3e22a3e-dbcf-55ef-2298-68313e69a77c.png)
Rspec　複数のselectタグのテストを実行する時の注意

###テストを実行したい該当のコード
ツアー情報を投稿する際に、ジャンルを選択して保存するようにさせている。
selectタグでvalueが1のoptionを選択してジャンルを保存するテストをやってみたい
<img width="338" alt="スクリーンショット 2020-07-01 15.45.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653956/6acf3f53-1cdc-841b-e589-79d4bf5c893e.png">


とあるページを参考にHTMLに表示される内容（以下だと冒険）を入力してテスト走らせてみた。

```tour_spec.rb
it 'tour投稿に成功する' do
  select '冒険', from: 'tour[genre_id]'
end
```


###ハマったエラー

```ruby:
Failure/Error: select '冒険', from: 'tour[genre_id]'
     Capybara::ElementNotFound:
       Unable to find option "冒険" within #<Capybara::Node::Element tag="select" path="/HTML/BODY[1]/DIV[1]/DIV[1]/DIV[1]/DIV[1]/FORM[1]/DIV[3]/DIV[1]/TABLE[1]/TBODY[1]/TR[1]/TD[2]/SELECT[1]">
```
冒険なんて見つからへんぞってめちゃくちゃ怒られた。
ここで、「やはりvalueを指定してやらないと、できないのではないか？？？」と、疑い始める。



###select '', from: ''　じゃなくても実現できるみたい

```ruby:
find("option[value='<該当するvalueの値>']").select_option
```
修正して実行してみる

```ruby:
Failure/Error: find("option[value='1']").select_option
     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching visible css "option[value='1']"
```
しかし、またキレられた。
なんやら要素が２つあるから特定できひんやんけ！！！！って吠えている

このエラーの原因はもう１つのselectが存在しているからみたいだ。実はジャンル以外にもう１つ、都市を選択するselectタグが存在している
<img width="339" alt="スクリーンショット 2020-07-01 17.53.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653956/6950583e-e625-7636-0b56-d62c51e0f213.png">



###どのselectタグなのか指定してやる
Rspecパイセンがどのselectと立ち向かえばいいか迷わないように、selectタグにあるidを指定してやる。

```tour_spec.rb
find("#tour_genre_id").find("option[value='1']").select_option
find("#tour_city_id").find("option[value='1']").select_option
```


無事にぶっ倒しました。経験値5000ぐらい得た気する



###メモメモ
fill_inやselectは便利やけど、どうやら不安定なことも多いみたい。。。
今回のようにfindで要素を特定して、入力する書き方の方が安全だったり、そうだったり、ラジバンダ、、、。
通っていたテストが時々通らなかったりするのは不安定なことが原因にあるのかよ。知らんかった時はいつもめちゃくちゃ悩んでいたのに
【Swift】保守しやすいコードを書くときに気をつけることSwift版

以前Objective-C向けに公開した記事をSwiftに置き換えたいと思います。

[対象記事はこちら]
https://qiita.com/yu_okb/items/dc7cce9504b43805b065

スクリプトみたいにViewController.swiftにダラダラ記述して後で他メンバーが保守するときに大変な思いをするより、初見でわかりやすい・保守しやすいコードの方が断然良い。そのためにやっている手法があるので、自身の備忘録に残しておく。

おおまかに伝えたいことだけ先に言うと、機能ごとに関数を疎結合にし、ライフサイクルの上に乗せて動かすように意識すると良い。

#やりたいこと
ViewやModel、Controllerなどを最小単位として列挙することで、あとで各処理を見直す際に確認が容易になる。処理を最小単位に書くことで同時に認識しやすくなり、保守が比較的楽になる。Swift版。

ご指摘あればよろしくお願いします。

#ポイント
+ viewDidLoadで余計な初期化をしない
+ 1 機能につき1 関数を定義する（ケースによるが）
+ MARKを正しく記載する
+ 最小単位に処理を分けて関数化することでユニット単位でテストができる

#手順
+ 各処理を最小単位で関数化し記述する
+ MARKを記載する

```ViewController.swift
import UIKit

class ViewController: UIViewController,
    UITableViewDelegate,
    UITableViewDataSource
{
   @IBOutlet var tableView: UITableView!
   var data: NSMutableArray = []

// MARKを書くことでXCode上から定義関数がインデックスされる
   //MARK: Life Cycle
   override func viewDidLoad()
   {
      // 余計な初期化は行わない
      // 目的に応じてラップした関数を呼び出す
      super.viewDidLoad()
      getData()
      setView()
   }

   //MARK: UITableViewDataSource
   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
   {
       // セクション数設定処理
   }

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
   {
      // cell描画処理
   }

   //MARK: Private
   private func getData()
   {
      data = []
              :
      // データ取得処理をここに書く
      // entityクラスを別途定義する
   }

   //MARK: Private View
   func setView()
   {
      // 例えばテーブルビューのみ動作を確認したい場合に"setTableView"以外をコメントアウトすると
      // テーブルビューのみの動作確認ができる
      setNavigationBar()
      setMainView()
      setTableView()
      setToolBar()
   }

   func setNavigationBar()
   {
      // ナビゲーションを実装する
   }

   func setMainView()
   {
      // view関連の実装
   }

   func setTableView()
   {
     // tableViewを実装するために必要な処理を書き出す
     tableView = UITableView(frame: CGRect(x: view.frame.origin.x,
                                                               y: view.frame.origin.y, width: view.frame.size.width, height: view.frame.size.height))
     tableView.dataSource = self
               :
     view.addSubview(tableView)
   } 

   func setToolBar()
   {
     // ツールバーを実装する
   }
}
   :
```

//MARK:
定義する関数の順序は以下の順で書くのが一般的。
それに従って//MARK:を記述する

Editにおける見出しの付け方Objective-Cでは#pragmaだが、Swiftでは「コメントアウトにMARK」を記述するだけ。

Obj-C : #pragma
Swift : //MARK:

MARKに関して、以下が表示されれば成功です。

<img width="334" alt="スクリーンショット 2020-07-01 17.48.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90301/8d88f797-ea73-b88d-cde6-7848ccd2e29f.png">

基本的なカテゴリは以下になると思います。
+ Initialize
+ Life Cycle
+ Delegate
+ Gesture
+ Private

#まとめ
各関数がそれぞれ疎結合になっていると関数同士の因果関係が明確になり、どこでバグが出ているのかを追いやすくなる。
Laravel Logを出力してみる 簡易版

# 目的

- Laravelでのログの出力方法のコントローラ記載部分のみを抜粋して記載する。
- もう少し詳しく知りたい方はこちら→[Laravel Logを出力してみる](https://qiita.com/miriwo/items/8d1c7c3a87cc670f6157)
- Laravelのログに関して少し詳しく調査した内容が知りたい方はこちら→[Laravel5.6以降のログの機能をちょっと調べた](https://qiita.com/miriwo/items/0a44b70f722a3863ff38)

# 実施環境

- MacのローカルにLaravelの環境を構築して実施する。環境構築手順の記事はリンクを後述する。
- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 詳細

1. ログを出力したいコントローラのアクション内に下記の記載を行う。

    ```php
    //use宣言として下記を追記
    use Illuminate\Support\Facades\Log;
 
    //コントローラのアクション内に下記を追記
    Log::debug('test');
    ```
1. ブラウザから追記箇所が実行されるように操作を行う。
1. `アプリ名ディレクトリ/storage/logs/laravel.log`に下記の様な一行が追記される。

    ```アプリ名ディレクトリ/storage/logs/laravel.log
    [YYYY-MM-DD HH:MM:SS] local.DEBUG: test 
    ```