OmniAICreator/Qiita-1.07M huggingface dataset:
Webアプリケーションについて

# 3層アーキテクチャ
Webアプリケーションは基本的に、

1. プレゼンテーション層・・・ Webブラウザ + Webサーバー 
2. アプリケーション層・・・・ APサーバー
3. データ層・・・・・・・・・ DBサーバー

の`3層構造`と呼ばれる階層的なデータ構造となっている。



# MVCモデル
Webアプリケーションの構造はそのほかにも`MVCモデル`があります。それぞれ

M（Model）・・・データベースの管理・操作
V（View）・・・・HTMLファイルの出力
C（Controller）・・ModelとViewを繋ぐ

の頭文字を取っています。

①WebブラウザからURLにアクセス
②ルーティングで定められている特定のコントローラ内の特定のアクションにアクセスする
③コントローラは、データベースから必要なデータを取得するようにモデルに依頼
④モデルはデータベースからデータを取得し、コントローラに結果を返却
⑤コントローラは所得した結果をビューに渡し、必要なHTMLファイルの作成を依頼
⑥ビューはHTMLファイルを作成し、Webブラウザに表示する


# 3層アーキテクチャとMVCモデルの違い

3層アーキテクチャは階層構造であるので最上層のアプリケーション層とデータ層がやり取りすることはない。
これに対して、　MVCモデルは各要素がやり取りを行う。


# フレームワークとは

各Webアプリケーションの設計において。処理の流れには共通した部分がある。そこで、共通した部分はひな形として準備しておき、各アプリケーションにおいて独自の部分を開発者が自由に設計できるようにしたものを`フレームワーク`と呼ぶ。
Rubyでは`Ruby on Rails`、
PHPでは`Cake PHP`、
Javaでは`Java EE`など。


# 参考
[イラスト図解式 この一冊で全部わかるWeb技術の基本](https://www.amazon.co.jp/%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88%E5%9B%B3%E8%A7%A3%E5%BC%8F-%E3%81%93%E3%81%AE%E4%B8%80%E5%86%8A%E3%81%A7%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8BWeb%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%B0%8F%E6%9E%97-%E6%81%AD%E5%B9%B3/dp/4797388811)
ログイン機能

#ログイン機能について
※とある未熟者エンジニアの備忘録です。

Laravelでは簡単にログイン機能を実装する事ができます。
仮のルート設定し説明していきます。

php artisan route:list
上記コマンドにてログイン機能のルートが確認できます。
App\Http\Controllers\Auth\LoginController.phpのshowLoginFormアクションメソッドを使うという設定を行い、そしてloginという名前付きとします。

次にviewを書く作業の説明です。
resources\views
ここにauthフォルダを作成、
その中に簡潔なlogin.blade.phpを作る事にします。

```
<h1>ログイン画面</h1>
<form action="{{ route('login') }}" method="post">
  @csrf
  <label>email</label>
  <input type="email" name="email">
  <label>password</label>
  <input type="password" name="password">
  <input type="submit" value="ログイン">
</form>
```

これでログイン機能は完了です。


これだけ？という疑問が生まれると思いますので、
どこでログインの処理がされているのか見ていきましょう。

実は冒頭で説明したLoginController.phpの中にshowLoginFormアクションメソッドは書かれていません。
showLoginFormアクションメソッドの代わりに
use AuthenticatesUsers;
が途中で書かれています。
一番上にはuse Illuminate\Foundation\Auth\AuthenticatesUsersと記載がありますので、
このAuthenticatesUsersの場所は
vendor\laravel\framework\src\illuminate\Foundation\Auth\AuthenticatesUser.php
ここに書かれています。

このAuthenticatesUser.phpの中を見てみると
showLoginFormアクションメソッドが書かれています。
YoutubeをMP3にダウンロード

Youtube So MP3をダウンロード–音楽を聴くのは好きですか？次に、YouTubeプラットフォームを介して最新の音楽を頻繁に更新または更新しますか？もしそうなら、確かにあなたは音楽を聴くためにあなたのインターネットの割り当てを毎日あきらめなければなりませんよね？

しかし今では、携帯電話をオフラインで使用するだけで、YouTubeの最新の曲を聴くことができます。なぜなら今、youtubeをmp3にダウンロードする方法はたくさんあるからです！一方、現在、YouTubeプラットフォームにアップロードされているミュージックビデオクリップはたくさんあります。

特に今では、私たちが一般的にアクセスできるさまざまな種類の曲のダウンロードサイトと比較すると、YouTubeはより最新のものになっています。 YouTubeプラットフォームを介して、曲のビデオクリップへのリンクをコピーしてダウンロードするだけです。

しかし、次の議論に進む前に、以下で最初にオフラインで曲を聴くことのさまざまな利点を読んだ方がよいでしょう。

オフラインで曲を聴くときに間違いなく得られることの1つは、割り当てを節約することです。これは、Webサイトにダウンロードするだけで、電話デバイスに自動的に保存されるためです。その後、曲を再生する必要があります。

しかし、ストリーミングとも呼ばれるオンラインで聴く必要がある場合は異なります。その場合、必然的に、曲のビデオクリップを再生するために多くの割り当てを使用する必要があります。

チャンネルの曲のビデオクリップをYouTubeアプリケーションでダウンロードできないことが判明した場合は言うまでもありません。したがって、曲を楽しむことができるように、mp3にyoutubeをダウンロードする必要があります。

それに加えて、mp3としてyoutubeをダウンロードするときに得られる次の利点は、インターネットネットワーク接続の影響を受ける必要がないことです。つまり、オフラインで聴いたり、クォータを使用しなかったりしても、後で突然音質が低下しても心配する必要はありません。

YoutubeをMP3にダウンロードするためのヒント
また、ダウンロードした曲を自分の着信音として作成することもできます。面白いですね。そのため、詳細については、以下のmp3にYouTubeビデオをダウンロードする方法を参照してください。

最初に行う必要のある最初のステップは、YouTubeアプリケーションを開くか、公式Webサイト自体を介して開くことです。その後、あなたがしなければならないのはあなたがmp3にダウンロードしたい曲のビデオクリップを探すことだけです。

公式サイトをご利用の場合は、ご覧の曲のビデオクリップ右上にある3点アイコンをクリックしてください。その後、共有または共有を選択します。曲のビデオクリップリンクをコピーした場合。

ただし、スマートフォンやタブレットを使用している場合は、再生している曲のビデオクリップの下部にある共有メニューをクリックするだけです。その後、ダウンロードしたい曲のビデオクリップへのリンクをコピーします。

PCまたはタブレットでブラウザを開きます。その場合は、URL列でytmp3WebサイトアドレスまたはWebサイトを開きます。 ytmp3 Webサイトのページが表示されたら、後で、前にコピーしたビデオクリップのURLをコピーする必要があります。

[変換]をクリックした場合は、しばらく待ちます。後であなたが望むファイルフォーマットがあるでしょう。携帯電話の音楽プレーヤーで直接曲を再生できるようにするには、mp3ファイル形式を選択します。 [ダウンロード]をクリックして、ダウンロードプロセスが完了するまで待ちます。

YouTubeの詳細については、https://ytube.id/ でのみYouTubeのヒントにアクセスしてください。

Source :

<a href="http://blog.ub.ac.id/akreditasi/">Blog Mahasiswa</a>
<a href="https://bit.ly/3H9fnz6">Buku Rekening</a>
<a href="https://bit.ly/3Ji45ua">Tips YouTube</a>
<a href="https://in-baidu.com/ikuti-tips-download-youtube-jadi-mp3-untuk-dengarkan-musik-tanpa-kuota/">Tips YouTube</a>
<a href="https://petercstenson.com/bagaimana-cara-menyimpan-video-dari-youtube-ke-galeri-simak-penjelasannya/">Tips YouTube</a>
<a href="https://almunasabat.com/pengen-nonton-youtube-dapat-uang-berikut-ini-ulasannya/">Tips YouTube</a>
<a href="https://wedchallenge.org/berapa-gaji-youtuber-1000-subscriber-simak-ulasan-di-bawah-ini/">Tips YouTube</a>
<a href="https://natudelia.com/bingung-kenapa-youtube-tidak-bisa-memutar-video-simak-ulasan-di-bawah-ini/">Tips YouTube</a>
<a href="https://artoflights.org/jangan-bingung-ini-rekomendasi-aplikasi-edit-video-youtuber/">Tips YouTube</a>
<a href="https://starwarsgaming.net/cara-mengatur-ukuran-header-youtube-dengan-mudah-bagi-pemula/">Tips YouTube</a>
<a href="https://lennonandwolfe.com/jangan-bingung-ini-cara-mengubah-mp4-ke-mp3/">Tips YouTube</a>
<a href="https://student.blog.dinus.ac.id/fatiya/simak-berbagai-macam-aplikasi-subtitle-youtube/">Tips YouTube</a>
<a href="https://allenbridgeis.com/ini-beberapa-macam-konten-youtube-luar-negeri-yang-belum-ada-di-indonesia/">Tips YouTube</a>
githubのプロフィール画像をコマンドラインから取得する

githubのプロフィール画像をコマンドラインから取得するには以下のようにすればOK

`${USER_NAME}`は対象ユーザのgithubアカウント名にする

```shell:
curl https://avatars.githubusercontent.com/${USER_NAME} --output output.png
```

必要に応じて画像サイズは変換して使うとよい

> [コマンドラインで画像を縮小する：ImageMagick convert mogrify](https://weblinuxmemo.hatenadiary.org/entry/20090929/p1)

以下のwarningが出力される場合は`--output`オプションをつける事で解決する

```shell:
$ curl https://avatars.githubusercontent.com/${USER_NAME}
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
```

# 参考

https://qiita.com/seigot/items/f3ce961407b9f9617ad2
football-data.orgのAPIでサッカーのデータを取得する

サッカーチームや試合のデータをAPIで取得できないか？と思ったので探した結果よさそうなAPIサービスがあったのでデータ取得までまとめます。

## API概要
https://www.football-data.org/

今回使ってみるAPI。アカウント登録すれば無料枠で12のコンペティション（５大リーグやCLなど）のデータを取得できる。[詳細は公式ページ](https://www.football-data.org/)にて


## アカウント登録

[登録画面](https://www.football-data.org/client/register)から名前、メールアドレス、言語を選んで登録。利用規約はしっかり読むこと！

@football-data.orgのメールアドレスからAPIトークンが送られてくる。

## データ取得

[公式ドキュメント](https://www.football-data.org/documentation/api)を参考に。今回はGO言語でサッカー史上最もクールなクラブチームを取得するように実装しました。

```golang
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
)

func main() {
	// 取得したいデータのURL作成
	url, _ := url.Parse("https://api.football-data.org/v2/")
	url.Path = path.Join(url.Path, "teams", "108")

	req, _ := http.NewRequest("GET", url.String(), nil)
	req.Header.Add("X-Auth-Token", "Your API token") // アカウント登録時に送られてきたAPIトークンをリクエストヘッダーに追加
	client := new(http.Client)
	resp, _ := client.Do(req)
	defer resp.Body.Close()

	byteArray, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(byteArray))
}

```

## 取得データ

```json
{
	"id": 108,
	"area": {
		"id": 2114,
		"name": "Italy"
	},
	"activeCompetitions": [
		{
			"id": 2001,
			"area": {
				"id": 2077,
				"name": "Europe"
			},
			"name": "UEFA Champions League",
			"code": "CL",
			"plan": "TIER_ONE",
			"lastUpdated": "2021-06-26T13:37:26Z"
		},
		{
			"id": 2019,
			"area": {
				"id": 2114,
				"name": "Italy"
			},
			"name": "Serie A",
			"code": "SA",
			"plan": "TIER_ONE",
			"lastUpdated": "2021-04-17T07:19:44Z"
		}
	],
	"name": "FC Internazionale Milano",
	"shortName": "Inter",
	"tla": "INT",
	"crestUrl": "https://crests.football-data.org/108.png",
	"address": "Corso Vittorio Emanuele II 9 Milano 20122",
	"phone": "+39 (02) 77151",
	"website": "http://www.inter.it",
	"email": "segreteriaccic@inter.it",
	"founded": 1908,
	"clubColors": "Blue / Black",
	"venue": "Stadio Giuseppe Meazza",
	"squad": [
		{
			"id": 77,
			"name": "Joaquín Correa",
			"position": "Attacker",
			"dateOfBirth": "1994-08-13T00:00:00Z",
			"countryOfBirth": "Argentina",
			"nationality": "Argentina",
			"shirtNumber": null,
			"role": "PLAYER"
		},
		...
	],
	"lastUpdated": "2021-11-24T14:55:58Z"
}
```

## まとめ

試合結果や成績を取得するだけであれば十分で比較的容易に実装することができました。選手の個人スタッツ等まで深堀するにはこのAPIでは取れないので他を検討する必要がありそうです。
goroutineに制限時間を加える

間に合わなかった場合

```go

package main

import (
	"context"
	"fmt"
	"time"
)

func task(ctx context.Context, channel_kun chan string) {
	fmt.Println("start")
	time.Sleep(5 * time.Second)
	fmt.Println("finish")
	channel_kun <- "良くできました"
}

func main() {
	channel_kun := make(chan string)
	ctx := context.Background()
	time_limit := 3 * time.Second
	fmt.Println("制限時間は", time_limit, "ね～")

	ctx, cancel := context.WithTimeout(ctx, time_limit)
	defer cancel()
	go task(ctx, channel_kun)

loop_label:
	for {
		select {
		case <-ctx.Done():
			fmt.Println("時間切れ～")
			fmt.Println(ctx.Err())
			break loop_label
		// タスクが間に合った時。
		case message := <-channel_kun:
			fmt.Println("間に合いました")
			fmt.Println(message)
			break loop_label
		}
	}
	fmt.Println("for文を終了します。")
}


```

実行結果

```

制限時間は 3s ね～
start
時間切れ～
context deadline exceeded
for文を終了します。

```

間に合った場合

```go

package main

import (
	"context"
	"fmt"
	"time"
)

func task(ctx context.Context, channel_kun chan string) {
	fmt.Println("start")
	time.Sleep(2 * time.Second)
	fmt.Println("finish")
	channel_kun <- "良くできました"
}

func main() {
	channel_kun := make(chan string)
	ctx := context.Background()
	time_limit := 5 * time.Second
	fmt.Println("制限時間は", time_limit, "ね～")

	ctx, cancel := context.WithTimeout(ctx, time_limit)
	defer cancel()
	go task(ctx, channel_kun)

loop_label:
	for {
		select {
		case <-ctx.Done():
			fmt.Println("時間切れ～")
			fmt.Println(ctx.Err())
			break loop_label
		// タスクが間に合った時。
		case message := <-channel_kun:
			fmt.Println("間に合いました")
			fmt.Println(message)
			break loop_label
		}
	}
	fmt.Println("for文を終了します。")
}



```

実行結果

```

制限時間は 5s ね～
start
finish
間に合いました
良くできました
for文を終了します。

```
Forms: Power BI のコネクターが出てくるまでは FormsAPI を使ってみては？

# 背景

会社にて Forms の分析に困ってる人がいたので、FormsAPI使ってみたら？という提案用に

# 普通のやり方

結果の表示にある、Excel から分析するのが定番かな、と思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/525268ed-4aa8-c1af-2463-b56bdf71e2ad.png)

昔はこのファイルの生成を事前にやっておかないといけなかったりと面倒だったんですが、今は不要になってる気も・・

# Forms API を利用する方法

今回の肝は以下。Forms API を使ってデータ取得をする。
そのうち Power BI でForms コネクターが提供されるとは思うので、それまでの繋ぎに。


https://qiita.com/baku2san/items/419aba7a5b1cc19ccbf5

>
1. Tenant ID は、[list-my-environments](https://docs.microsoft.com/ja-jp/connectors/flowmanagement/#list-my-environments) で Default Environment から取得
1. User ID は、[office365users](https://docs.microsoft.com/ja-jp/connectors/office365users/#get-my-profile-(v2)) などで取得
1. Form ID は、Forms の [Trigger](https://docs.microsoft.com/ja-jp/connectors/microsoftforms/#when-a-new-response-is-submitted) か、APIで取得とか
1. Responses API で回答取得


1. 上記で書いた方法で、Response API URL を用意
1. Web コネクターで上記URLからデータ取得<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/434b51a0-0af8-dd67-23b7-9c1108fd3e5a.png)
1. JSON 分解すれば・・こんな感じで最新データが即座に利用出来ますよ。<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/805c5595-95ba-f22f-8048-3ad4cbcdac90.png)

# ID 取得方法別解
- TenantID の取得方法は、以下でも
    - Power Automate の Default 環境で、URL から取得<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e06e889e-92f1-7108-f6af-b76ba50789b6.png)

:::note warn
"Default-" は削除必要
:::

- User ID の取得方法は、以下でも
    - Office プロファイルで Delve のURLから取得<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/fe71be52-ae22-c4fc-21d8-55412db37de9.png)

- Forms ID の取得方法は以下でも
    - 取得したい Form を開き、URLから取得<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/2b669c6a-94f4-396f-9a80-40d03a7cc113.png)

# keyword

How to analyze Forms with Forms API in Power BI
Dataportalで都道府県別の塗り分けマップを利用する方法

# はじめに

こんにちは。@yyyimaiです。
この記事は私自身がつまずいた Google が提供する無料の BI ツールである Dataportal の[塗り分けマップ](https://support.google.com/datastudio/answer/7065037#zippy=%2C%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E5%86%85%E5%AE%B9)を利用する方法です。
多くの方はつまずかないと思いますが私は公式のドキュメントを読んでもあまり理解できなかったので、備忘録としてこちらを残します。

結論から申し上げますと、簡単な方法と面倒だけどデータベース的に管理する方法の2パターンがあります。

1. 簡単な方法は、都道府県のデータの入っているカラムの種類を地域コードに変更するという方法。
2. 面倒な方法は、[ISO 3166-2:JP](https://ja.wikipedia.org/wiki/ISO_3166-2:JP)の一覧データを別のシートやテーブルとして管理し、スプレッドシートなら VLOOKUP 関数を利用してシート内でデータの結合、 DWH ならカスタムクエリの利用によりテーブルを結合して利用する方法があります。

## 1. 簡単な方法

簡単な方法の例として以下のようなユーザー一覧のデータが1万件あるとします。
![テストデータ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/ca46ca7d-2034-cbdf-5ff8-1b02d69c43b2.png)
このデータを Dataportal にデータソースとして連携すると以下のように表示されるはずです。
![テストデータの連携画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/249fe201-d0a2-48d5-8fd5-7edbb1b72fe5.png)
この時に都道府県のカラムをテキストではなく地域の中にある地方行政区画（第１レベル）に変更します。
この変更により都道府県のデータを地域データとして扱うことができます。
そして以下のように塗り分けマップを作成することができます。
![テストデータの塗り分けマップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/e79c6718-5e04-d4c8-e98c-4d5b8ccec3df.png)

ただし私はこの方法はスプレッドシートのデータを Dataportal に連携している時のみに利用することを推奨します。
なんとなくデータのあるべき姿を歪めているように感じるからです。
なので、 DWH を利用しているようなユーザーは地域データのテーブルを別持ちにして管理する2番目の方法を選択してもらいたいと考えています。

## 2. 面倒な方法

Dataportal において都道府県の地域データを上記で書いたように ISO 3166-2:JP として表すことができます。
例えば、北海道は JP-01 、大阪府は JP-27 、東京都は JP-13 となります。
Dataportal はこれらの文字列を自動的に判別し地域データとして扱います。
今回はスプレッドシートの場合を考えます。
以下のような 47 都道府県分のデータを入れたシートを別に作成します。
![都道府県_ISO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/ceecd0dc-e361-169b-0887-93083ebf0fef.png)
そしてこの ISO コードをテストデータの H 列に出すように VLOOKUP 関数を作成します。
![テストデータ_ISO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/bd3ae26e-e355-bbf7-2ad5-fa2720c0bc88.png)
Dataportal のデータソースにて接続を編集し H 列も認識するようにしてから再接続をすると以下のようになります。
![テストデータの連携画面_ISO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/cba660b9-a3a5-6ebd-e772-6dc6ec5ef558.png)
ISO コードがディメンションの中に増え、そして自動的に地方行政区画（第１レベル）として扱われています。
このデータを使って1の簡単な方法で作成した塗り分けマップと同等のマップを以下のように作成します。
![テストデータの塗り分けマップ_ISO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2324252/010f929a-04ec-dfa7-55ca-3bc7b22811de.png)
この1の簡単な方法で作成した塗り分けマップとの違いは、位置の部分が都道府県から ISO コードに変わっており、ツールチップが空になっていたものが都道府県になっています。

# 終わりに

1と2の方法は管理の面を考えると2の方が勝っていると考えますが、手軽にグラフを作成できる Dataportal ではあまり考えずに1の方法を利用してもいいようにも感じます。
人それぞれの利用法を取っていただければと思います。
私のように地域データとは何ぞやとか悩んでる暇があったらかっこいいダッシュボードを早く作ることに時間を使った方が有意義だと思います。
よい BI ライフを送ってください！ありがとうございました。
Nerves Livebook with ngrok can be accessed from outside network.

https://qiita.com/advent-calendar/2021/raspberrypi

12/04, 2021

# Introduction

Enjoy [Elixir](https://elixir-lang.org/):bangbang::bangbang::bangbang:
Enjoy [Nerves](https://www.nerves-project.org/):bangbang::bangbang::bangbang:

Yesterday, I posted an article.

https://qiita.com/torifukukaiou/items/8393fb3deb2448163b07

I think that [Nerves Livebook](https://github.com/livebook-dev/nerves_livebook) with [ngrok](https://ngrok.com/) can be accessed from outside network.

I try it.
Of course, I can do it!!!

# [Nerves Livebook](https://github.com/livebook-dev/nerves_livebook) Setup

Would you please refer the article?

https://qiita.com/torifukukaiou/items/27abc5b84f6f55f85d71#nerves-livebook-setup

# Diagram

![スクリーンショット 2021-12-26 22.52.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/1e380ccd-f43e-c9d1-5f28-f5a26a8bf486.png)


I use Raspberry Pi 4.
[Nerves Livebook](https://github.com/livebook-dev/nerves_livebook) runs on Raspberry Pi 4.

We can access [Nerves Livebook](https://github.com/livebook-dev/nerves_livebook) from outside network with [ngrok](https://ngrok.com/).
Yes we can.
Success!!! L-chika :tada::tada::tada:

# Note

:::note alert
Chrome browser on outside network PC shows alert.
:::


![スクリーンショット 2021-12-26 22.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/c1a71798-d5df-9d9c-1091-58296b211f42.png)

Click **詳細を表示**

![スクリーンショット 2021-12-26 22.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/3e8b49f0-3667-1568-65ad-aef7144c5f9e.png)

Click **安全でないこのサイトにアクセス**



# Wrapping up :lgtm::lgtm::lgtm::lgtm::lgtm:

We can access [Nerves Livebook](https://github.com/livebook-dev/nerves_livebook) from outside network with [ngrok](https://ngrok.com/).

Enjoy [Elixir](https://elixir-lang.org/):bangbang::bangbang::bangbang:
Enjoy [Nerves](https://www.nerves-project.org/):bangbang::bangbang::bangbang:

---

I organize [autoracex](https://autoracex.connpass.com/).
And I belong to [NervesJP](https://nerves-jp.connpass.com/).
I hope someday you'll join us.

[We Are The Alchemists, my friends!](https://www.youtube.com/watch?v=04854XqcfCY)

![https___qiita-user-contents.imgix.net_https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F240349%2F5ef22bb9-f357-778c-1bff-b018cce54948.png_ixlib=rb-1.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/447253f9-3060-8bb7-7132-7754ef4aead5.png)
github上に新しいリポジトリを作成した後、古いリポジトリのgit履歴を新しいリポジトリへpushする

github上に新しいリポジトリを作成した後、古いリポジトリのgit履歴を新しいリポジトリへpushする際のメモ

１．新しいリポジトリを作成する
２．古いリポジトリのgit履歴を新しいリポジトリへpushする

## １．新しいリポジトリを作成する

githubの`repository-->new`から新しい空のリポジトリを作成する

`sample`という名前の空リポジトリを作成する例

![スクリーンショット 2021-12-26 21.53.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/c7b9919f-3a8a-f2e1-f1cc-de06d2fc4632.png)


## ２．古いリポジトリのgit履歴を新しいリポジトリへpushする

`old_sample`という古いリポジトリから、新しいリポジトリ`sample`へpushするコマンド例
URLは適宜変更すればOK

```
git clone http://github.com/seigot/old_sample
cd old_sample
git push --mirror http://github.com/seigot/sample
```

新しいリポジトリに期待通りpushできている事を確認した後、古いリポジトリは不要であれば削除すればOK

# 参考

https://tsujitaku50.hatenablog.com/entry/2017/01/08/200155
DockerのPostgres環境でDB接続エラー（could not find driver）

## エラー内容
Dockerで立ち上げたPHP+Postgresの環境で、PDOを利用してDB接続を行なったときに下記が発生

```
could not find driver
```

## 原因
DockerのphpコンテナにPDOドライバーがインストールされていないことが原因

## 対策
Dockerfileを使ってPDO（pdo_pgsql）をインストールして解決する
phpのDockerfileに下記を追加

```
RUN apt-get update && apt-get -y install libpq-dev
RUN docker-php-ext-install pdo_pgsql
```

注意点として、単にpdo_pgsqlをインストールしようとするとエラーが発生してしまうため、先にlibpq-devをインストールするのがポイント
WebRTC Momo送信 → Sora Laboシグナリング → Unity受信

構成はタイトルのまんまです。
正しいやり方かどうかは分かりませんが、動かすことが出来たのでメモしておきます。2021/12/26現在の情報です。

## Sora Laboの設定

ユーザー登録をして、シグナリングURLとシグナリングキーを確認しておく。(このあと使う)

## 送信側 momoの起動

[momo](https://github.com/shiguredo/momo)を起動しWebカメラの映像を送出する。
momoを実行するPCにはWebカメラが接続されていることが前提。

### Momoの起動オプション
```
./momo sora --signaling-url wss://node-01.sora-labo.shiguredo.jp/signaling --channel-id USERNAME@CHANNEL-ID --metadata '{"signaling_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}' --role sendonly
```

ここで、`--signaling-url` や `--metadata '{"signaling_key": "xxxxxxxxxxxxxxxxxxxxxx"}'`の`xxxxxxxxxxxxxxxxxxxxxx`の部分は[Sora Labo](https://sora-labo.shiguredo.jp/)のページに表示された値を使う。
`channel-id`はSora Laboに登録したGitHubのユーザー名と`@`と任意の文字列の組み合わせ。
例えば```comoc@sora-test-channel```。

## 受信側 Unityの設定とプレイ

### SoraSample.csスクリプトの修正

2021/12/26時点のGitHubのmasterブランチの`SoraSample.cs`スクリプトでは、`DataChannelMessaging`と記述すべき部分が `DataChannel` になっているので、`DataChannelMessaging`に置換する。また`config.DataChannels`も`config.DataChannelMessaging`に置換する。

### recvonlyシーンを開く
[Sora Unity SDK Samples](https://github.com/shiguredo/sora-unity-sdk-samples)プロジェクトを開き、`recvonly`シーンを読み込む。

### Scriptの設定
Hierarchyから`Script`を選択し、Inspectorから`Signaling Url`、`Channel Id`、`Signaling Key`の3か所に、momoで指定したものと同じ値を入力する。

### 実行
エディタのPlayボタンを押した後、「開始」ボタンを押す。
うまく行けば、このスクショのように、送出側のカメラ映像が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39561/ba0f4acd-0456-5420-bb6b-991c46db3b99.png)

### Linuxで ffmpeg で任意の映像ソースを仮想ビデオデバイス /dev/videoN にして momo から送出

手元にビデオデバイスがない(動画ファイルならある)ときに使える技。

#### ffmpegを使って再生

例. `VIDEOFILE.mp4`を `/dev/video2` のソースにする。

```
ffmpeg -re -stream_loop -1 -i VIDEOFILE.mp4 -map 0:v -f v4l2 /dev/video2
```
オプションの意味
* `-re`はフレームレートを維持
* `-stream_loop -1` は無限ループ
* `-map 0:v` はビデオだけ抽出
* `-f v4l2` v4l2のフォーマットを強制

#### momo で /dev/videoN をビデオデバイスとする。解像度は4Kにしてみる

```
momo --video-device="/dev/video2" --resolution 4K sora --signaling-url wss://node-01.sora-labo.shiguredo.jp/signaling --channel-id USERNAME@CHANNEL-ID --metadata '{"signaling_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}' --role sendonly
```

`-video-device="/dev/video2"` ビデオデバイスを指定。(このオプションを指定する順番をいろいろ試してみたところ`momo`の直後ならば動くようだ)
`--resolution 4K` 解像度を4Kにする。

Unity側のRawImageに設定されているテクスチャの解像度が640x480に固定されていたので、`SoraSample.cs`を改造して3840,2160にしないとぬるい画になってしまう。

以上。
PHP FPM の設定

## 前提
次の手順の続きで進める。

https://qiita.com/silverskyvicto/items/c302133a2bfafe1ba511

## 手順

1. 実行用ユーザーを作成する

    ```CentOS
    # useradd php-fpm
    ```

    ```Ubuntu
    $ sudo adduser --no-create-home php-fpm
    ```

2. 使用するディレクトリを作成する

    ```
    $ sudo mkdir /var/run/php-fpm /var/log/php-fpm
    $ sudo chown php-fpm:php-fpm /var/run/php-fpm /var/log/php-fpm
    ```

3. 必要なファイルをコピーする

    ```
    # cp /usr/local/etc/php-fpm.conf.default /usr/local/etc/php-fpm.conf
    # cp /usr/local/etc/php-fpm.d/www.conf.default /usr/local/etc/php-fpm.d/www.conf
    # cp sapi/fpm/php-fpm /usr/local/bin/
    ```

4. `php.ini` ファイルを編集する

    ```
    # vi /usr/local/php/php.ini
    ```

    ```php.ini
    cgi.fix_pathinfo=0
    
    expose_php = Off
    ```

5. php-fpm.confファイルを編集する

    ```
    # cp /usr/local/etc/php-fpm.conf /usr/local/etc/php-fpm.conf.org
    # vi /usr/local/etc/php-fpm.conf
    ```
    
    ```ini:php-fpm.conf
    (省略)
    
    (パスの設定を変更)
    pid = /var/run/php-fpm/php-fpm.pid
    
    (パスの設定を変更)
    error_log = /var/log/php-fpm/php-fpm.log
    
    (パスの設定を変更)
    include=/usr/local/etc/php-fpm.d/*.conf
    ```

6. php-fpm のサービスファイルを配置する

    ```
    # cp ./sapi/fpm/php-fpm.service /usr/lib/systemd/system/
    # vi /usr/lib/systemd/system/php-fpm.service
    ```
    
    ```
    [Service]
    Type=notify
    User=php-fpm
    PIDFile=/var/run/php-fpm/php-fpm.pid
    ExecStart=/usr/local/sbin/php-fpm --nodaemonize --fpm-config /usr/local/etc/php-fpm.conf
    ExecReload=/bin/kill -USR2 $MAINPID
    ```
    
7. サービスファイルを再読み込みする

    ```
    # systemctl daemon-reload
    ```

8. Nginx の設定ファイルを作成する

    ```
    # cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.`date +%F`
    # mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/wordpress.conf
    # vi /etc/nginx/conf.d/wordpress.conf
    ```

    ```nginx:wordpress.conf
    server_name localhost;
    root   /usr/share/nginx/html;
    （中略）
    
    location / {
        index  index.php index.html index.htm;
    }
    
    （中略）
    
    location ~* \.php$ {
        fastcgi_index  index.php;
        fastcgi_pass   127.0.0.1:9000;
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
    }
    ```

9. 設定ファイルが正しいことを確認する

    ```
    # nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    ```

10. php-fpm と Nginx を起動する

    ```
    # systemctl start php-fpm
    # systemctl start nginx
    ```

## 確認

```
# rm /usr/share/nginx/html/index.html
# echo "<?php phpinfo(); ?>" >> /usr/share/nginx/html/index.php
# systemctl restart nginx
```

ブラウザからサーバにアクセスして次のような画面になればOK

![PHP情報画面（テスト用）.png](https://qiita-image-store.s3.amazonaws.com/0/34297/12ecc1b2-c3b5-a969-b111-ce47b886b2ae.png)

## 参考
- [FastCGI Process Manager (FPM) | PHP 公式ドキュメント](https://www.php.net/manual/ja/install.fpm.php)
- [インストール | PHP 公式ドキュメント](https://www.php.net/manual/ja/install.fpm.install.php)
- [設定 | PHP 公式ドキュメント](https://www.php.net/manual/ja/install.fpm.configuration.php)
最新の電車は昔の電車より揺れないか調査したら衝撃の結果が！

# 本当に揺れないのか？
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/ebde61c9-e3fc-ca76-b1c1-3253ac22136b.jpeg)
みなさん電車の揺れ、気になりませんか？最近はコロナ禍の影響でつり革に掴まるのも躊躇するご時世ですから、気になりますよね！

総武快速線には、26年ぶりに新しい車両E235系が投入されました。前世代のE217系と比べて、車内は明るいし、車体も綺麗！新車のにおいがして、乗っていてとてもいい気分です。

私がE235系に乗ったときの第一印象は「揺れない」でした。しかし、本当に揺れないのでしょうか？新車の雰囲気に騙されていているのではないでしょうか？そこで、今回は科学技術の力（おおげさｗ）で本当に揺れないのか調べてみました。

# 身近な機器で測定する
調査にはiphoneを使います。iphoneには加速度センサーが搭載されているので、振動を簡単に拾うこと事ができます。採取した振動はアプリでテキストデータ化できるのであとはExcelで処理できます。

問題はなにを「振動」とみなすかですが、今回は加速度の変化量を振動とみなしました。

定義を簡単に説明します。まず、電車の停車時、加速度センサーは重力のみ影響を受けます。この時zが-1.0で、xとyは0です。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/5a6a6a15-46ca-f4fb-7f9b-15cb4860a75a.jpeg)

電車が加速すると、y方向がマイナスになります。停車から加速に際して、加速度が変化したことになります。この変化を振動とみなします。

$$振動u_{i}= \sqrt{(x_{i+1} - x_{i})^2+(y_{i+1} - y_{i})^2+(z_{i+1} - z_{i})^2}$$

$$ただしx_k,y_k,z_kは時間kにおけるそれぞれの軸の加速度$$

![3_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/828ba8de-9d9d-9345-6b4e-52b451c52089.jpeg)

この「振動」を決められた駅から駅までの区間で全て足し合わせたものを「揺れ」として、「揺れ」がどのくらい発生するか比較します。

$$揺れ=\sum_{i=1}^{n-1} u_{i}$$

# 測定環境
完全に同じ条件で217系とE235系の揺れを比較するのは不可能です。そこで、なるべく同じ条件で複数回それぞれの揺れを観測して、比較評価することとします。同じ日時同じ時間帯で同じ区間、同じ車両内の場所で測定をします。以下が測定環境です。

|項目|内容|
|:---|:---|
|日時|2021年12月23日|
|時間帯|10時～15時|
|区間|船橋駅→稲毛駅|
|測定箇所|9号車千葉方から2番目山側のドア前|
|測定回数|E217系、E235系でそれぞれ3回ずつ|

iphoneの設置条件は、x軸が枕木方向、y軸が線路方向、z軸が天地方向となるようにしました。ただし厳密測って設置したわけではなく、目測レベルです。紙袋に入れて風の影響を受けないようにしました。椅子に置かなかったのは椅子のクッションの性能差が混入してしまう可能性を排除するためです。
![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/7afc3119-eaf5-a9c8-0bb0-4a8cc7aebb4a.jpeg)

# 測定
計6回も同じ区間で測定するので、半日かけて測定を行いました（結構大変でした）。下図はE253系で測定したy軸の加速度です。y軸は進行方向がプラスなので、加速の時はマイナス、減速の時はプラスの値をとります。
![4_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/23ee3895-07bf-bf2f-c4b3-dea469115d72.jpeg)
今度は下図はE253系で測定したz軸の加速度です。z軸は天頂方向がプラス、地面方向がマイナスなので、常時重力の影響を受けます。
![5_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/ce319622-2e25-dd63-52f6-0507f2a10064.jpeg)

# 結果
さあデータが全て揃ったので評価しましょう。果たして「揺れ」に差は出るのでしょうか。結果は以下のようになりました！

|車種|回次|「揺れ」|
|:---|:---|---:|
|E235系|1回目|85.61|
|E235系|2回目|78.59|
|E235系|3回目|79.68|
|E217系|1回目|85.35|
|E217系|2回目|83.41|
|E217系|3回目|90.69|

![6_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670191/61673773-2725-c991-160d-fb4eb0b4b9b9.jpeg)
なんと、E235系ほうがE217系に比べて「揺れ」が小さいという結果になりました！

このE217系とE235系の数値をどう捉えるかかですが、同じ路盤をほぼ同じ加減速で走っていても数字に差が現れるという事は、本当にE235系のほうが揺れが小さいということだと思います。ただ乗っている人間が明らかに違いが分かるかといえば、それほどでもないというぐらいの差だと思います。

# 最新車両は本当に揺れなかった！

いかがでしたか？最新車両は本当に揺れないことがわかりました。正直、これほど数値として差がでるとは思いませんでした！正直数字には表れないと思っていたので、とても嬉しいです。体感って結構あてになるんですね。そして、技術の進歩というのは、我々の知らないところでしっかりと進んでいるのですね。

# この調査の限界
E217系とE235系で複数回測定したとはいえ、それぞれの測定で電車のダイヤが異なる可能性があります。できればサンプル数を3回でなく10回ぐらいにしたいところではあります。また今回は区間が船橋駅→稲毛駅と比較的まっすぐな線形でしたが、カーブの多い区間で測定するとまた結果が変わるかもしれません。

# 今後の課題
加速度についてx軸方向、y軸方向で独立して解析すれば、また違ったことがわかるかもしれません。x軸方向なら横揺れの多さ、y軸方向なら加減速のスムーズさがわかると思います。それはおいおい解析してみたいと思います。他路線で調査するのも面白いかもしれません。2021年12月現在、相模線では205系とE131系が混在して走っていますので、ねらい目だと思います。
json.Marshalの基礎理解


## 構造体　→  json  → 構造体


```go

package main

import (
	"encoding/json"
	"fmt"
)

// 横に`json:～`でjsonにした時のキーを記載
type Friend struct {
	Name string `json:"name_json"`
	Age  int    `json:"age_json"`
}

func main() {
	F := Friend{
		Name: "murama",
		Age:  44,
	}

	fmt.Println("F:  ", F)

	// 構造体からjsonへ
	j, err := json.Marshal(F)
	if err != nil {
		panic(err)
	}
	// string型に変換しないとbyte型で表示される。
	fmt.Println("j: ", j)
	fmt.Println("string(j): ", string(j))

	// 受皿となる空の構造体を作る。
	new_s := Friend{}
	fmt.Println("new_s: ", new_s)
	// 再び構造体へ
	err2 := json.Unmarshal(j, &new_s)
	if err2 != nil {
		panic(err2)
	}

	fmt.Println("new_s: ", new_s)

}



```

実行結果

```

F:   {murama 44}
j:  [123 34 110 97 109 101 95 106 115 111 110 34 58 34 109 117 
114 97 109 97 34 44 34 97 103 101 95 106 115 111 110 34 58 52 52 125]
string(j):  {"name_json":"murama","age_json":44}
new_s:  { 0}
new_s:  {murama 44}



```
Laravelでブラウザにプッシュ通知する機能

Laravelを使ってブラウザにプッシュ通知する機能を実装したいと思い下記の記事を見つけたので挑戦してみました。


https://blog.capilano-fw.com/?p=5404#env_error

### openssl_pkey_new(): private key length is too short; it needs to be at least 384 bits, not 0のエラーが出た


これで解決
https://qiita.com/meiyin/items/fae67a36f8f73fc1de88
AI業界で作られるAIの4つの分類

 
      
#本題
今回この記事を書いたキッカケとして、
「経済を、もっとおもしろく。」ビジネスパーソンや就活生必携のソーシャル経済メディアのNewsPicksで放映された、
番組の「未来を創る！新世紀のAI技術」という回でした。

#学びの詳細
・見る力👁
『識別系AI』
...画像認識AI
...顔認識AI
...文字認識AI
など。

・予測する力🧠
『予測系AI』
...需要予測AI
...顧客予測AI
...異常検知AI
など。

・話す力🗣
『会話系AI』
...翻訳AI
...自然言語処理AI
...文字認識AI
など。

・動く・作る力💨
『実行系AI』
...自動運転AI
...ロボット/ドローンAI
...画像生成AI
...作曲AI
など。  

これを見てもわかる通り、AI業界の現場仕事では4つに分類されておりAIについて知識がない人でも、身近にある物でも想像できるのではないでしょうか。これから更に発展していくAIの知見を高くすることは大事だと思いますし、どう動くのかどう育成するのかなどを深堀すると、更に学び楽しさが出来るのではないかと思いました。

#参考文献
NewsPicks
番組/OFFRECO/「未来を創る！新世紀のAI技術」
https://newspicks.com/movie-series/44?movieId=1735
【Cypress】ログイン情報をCircleCIの環境変数に追加する

# はじめに

Cypressに環境変数を定義する際は、`cypress.env.json`に記述し、`Cypress.env()`で取得可能ですが、E2Eテストで使用するログイン情報をGithubに公開したくなかった。CircleCIでも同じログイン情報でE2Eテストを実行できるよう、環境変数をCircleCIに追加し、Cypressで取得できるようにしていきます。

# カスタムコマンドの追加

ログイン処理は各specファイルで必ず使用するので、使い回しが出来るようにカスタムコマンドを追加していきます。

**support/commands.js**

```jsx
Cypress.Commands.add('login', () => {
  cy.get('body').contains('ログイン');
  cy.get('[data-cy=email-input]').type(Cypress.env('EMAIL'));
  cy.get('[data-cy=password-input]').type(Cypress.env('PASSWORD'));
  cy.get('[data-cy=login-button]').click();
});
```

[Custom Commands | Cypress Documentation](https://docs.cypress.io/api/cypress-api/custom-commands)

実際にspecファイルで使う場合は、`cy.login()`と記述することでログイン処理が実行できます。　

```jsx
context('Login Test', () => {
  before(() => {
    cy.visit('/login');
    cy.login();
  });
})
```

# Cypressのenvファイル作成

ローカルでE2Eテストを実行できるよう、ログイン情報を`cypress.env.json`に記述し、.gitignoreにenvファイルを追加します。

```jsx
{
  "EMAIL": "test@example.com",
  "PASSWORD": "test1111"
}
```

 これでローカルでCypressを実行した際、envファイルのemailとpasswordを用いてログイン処理を行ってくれます。

# Cypressに環境変数追加

Githubにはenvファイルを公開していないので、CircleCIでCypressを実行する際は別途環境変数を追加する必要があります。

CircleCIに環境変数は、**Project Settings > Environment Variables > Add Environment Variable** で追加することができます。CYPRESS_ プレフィックスをつけた環境変数を定義することで、`Cypress.env()`で呼び出すことが可能です。

![FireShot_Capture_526_-_Environment_Variables_-_enu-web_-_app_circleci_com.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/65e7b842-128a-e34d-1c08-6514cee829cc.jpeg)
【Nuxt.js】nuxt-i18nで他言語対応

# はじめに

Nuxt.jsで他言語対応をする際に使用したnuxt-i18nがとても良かったので布教したいと思い、導入から使い方までメモしておきます。

# ① インストール

まずは i18nのNuxt.js用Moduleをインストールします。

```bash
yarn add @nuxtjs/i18n
or 
npm install @nuxtjs/i18n
```

次に、`nuxt.config.js`に設定を追加します。
以下の設定の他にも色々なOptionがありますので、[公式ドキュメント](https://i18n.nuxtjs.org/options-reference)を参考にしてみてください。

```jsx
modules: [
	['nuxt-i18n', {
		locales: [
			{
				code: 'en', // localeの識別子
				file: 'en.json' // ファイル名。langDirに指定したディレクトリに置く
			},
			{
				code: 'ja',
				file: 'ja.json'
			}
		],
		lazy: true, // 翻訳を遅延読み込みさせるか
		langDir: 'lang/', // fileが存在するディレクトリを指定
		defaultLocale: 'ja', // デフォルトの言語
		strategy: 'no_prefix', // ルートにプレフィックスを追加できる。今回は無し
	}]
]
```

# ② 翻訳をjson形式で登録する

`nuxt.config.js`で指定したファイルに翻訳をjson形式で記載していきます。

```jsx
// en.json
{
	"title": "Hello World",
	"text": "I'm fine."
}
```

```jsx
// ja.json
{
	"title": "こんにちは世界",
	"text": "私は元気です。"
}
```

# ③ 出力する

登録した翻訳を実際に出力します。
template内にて`{{ $t('key') }}`の形で呼び出すことができます。

```jsx
<template>
	<div>
		<h1>{{ $t('title') }}</h1>
		<p>{{ $t('text') }}</p>
	</div>
</template>
```

切り替えボタン等、イベントで言語を切り替えたい場合は`setLocale`メソッドを使用します。

```jsx
ex)
<template>
	<div>
		<button @click="isJapanese">日本語</button>
		<button @click="isEnglish">English</button>
		<h1>{{ $t('title') }}</h1>
		<p>{{ $t('text') }}</p>
	</div>
</template>
<script>
export default defineComponent({
  setup() {
    const isEnglish = () => {
			this.$i18n.setLocale('en')
		}
		const isJapanese = () => {
			this.$i18n.setLocale('ja')
		}

		return {
			isEnglish,
			isJapanese
		}
  },
})
</script>
```

とても簡単に他言語対応を実装することができました。
[Callback](https://i18n.nuxtjs.org/callbacks)や[カスタムルートパス](https://i18n.nuxtjs.org/custom-paths)など、便利な機能がたくさんあるので、様々な要件に対応できそうです。
Ansible Tips: list of dictデータに、別のkey, valueを追加する

#課題 list of dictデータに、新規key, valueを追加する

以下のようなlist of dict構造のそれぞれの要素に


```yaml:元データ
- k0: v0
  k1: v1
- k0: v3
  k1: v4
```

以下のような新規のkey，valueを追加して

```yaml:追加したい属性
- k2: v2
- k2: v5
```

以下のようなデーターを作りたい


```yaml:作成したいデータ
- k0: v0
  k1: v1
  k2: v2
- k0: v3
  k1: v4
  k2: v5
```

# 方法

list of dict のため、そのままでは combine フィルターが使えない。
zip, map, combine フィルターを組み合わせて使用する。

```yaml
---
- hosts: all
  vars:

    test1:
    - k0: v0
      k1: v1
    - k0: v3
      k1: v4

    test2:
    - k2: v2
    - k2: v5

  tasks:

  - name: 途中経過
    debug:
      var: test1|zip(test2)  

  - name: 結果
    debug:
      var: test1|zip(test2)|map('combine')
```

実行結果

```
TASK [途中経過] ********************************************************************************************************************************************
ok: [localhost] => {
    "test1|zip(test2)": [
        [
            {
                "k0": "v0",
                "k1": "v1"
            },
            {
                "k2": "v2"
            }
        ],
        [
            {
                "k0": "v3",
                "k1": "v4"
            },
            {
                "k2": "v5"
            }
        ]
    ]
}

TASK [結果] ************************************************************************************************************************************************
ok: [localhost] => {
    "test1|zip(test2)|map('combine')": [
        {
            "k0": "v0",
            "k1": "v1",
            "k2": "v2"
        },
        {
            "k0": "v3",
            "k1": "v4",
            "k2": "v5"
        }
    ]
}

```
CentOS 6でZabbixエージェントをrootユーザーで起動するには

###0. 事象
CentOSにZabbixエージェントをインストールし、起動を行うとZabbixエージェントのプロセスが「zabbix」ユーザーにて起動される。

```
#ps -ef | grep zabbix | grep -v grep
zabbix    1900     1  0 05:13 ?        00:00:00 /usr/sbin/zabbix_agentd -c /etc/zabbix/zabbix_agentd.conf
zabbix    1901  1900  0 05:13 ?        00:00:00 /usr/sbin/zabbix_agentd: collector [idle 1 sec]
zabbix    1902  1900  0 05:13 ?        00:00:00 /usr/sbin/zabbix_agentd: listener #1 [waiting for connection]
zabbix    1903  1900  0 05:13 ?        00:00:00 /usr/sbin/zabbix_agentd: listener #2 [waiting for connection]
zabbix    1904  1900  0 05:13 ?        00:00:00 /usr/sbin/zabbix_agentd: listener #3 [waiting for connection]
zabbix    1905  1900  0 05:13 ?        00:00:00 /usr/sbin/zabbix_agentd: active checks #1 [idle 1 sec]
```
今回はこのZabbixエージェントのプロセスをrootユーザーにて起動する方法を、備忘録として纏めていきます。

###1. なぜrootユーザーで起動する必要があるのか
Zabbixの監視項目にはログファイル監視というものがある。
これはエージェントを導入したサーバ上のログファイルを監視（読み込み）し、監視対象の文字列がログファイルに書き込まれたら、エージェントがZabbixマネージャに通知する仕組みとなっている。
監視する対象のログファイルは自由に選べるが、「/var/log/messages」などのファイルはrootユーザーでしか読み込むことが出来ないため、これらのファイルを監視対象としたい場合はエージェントをrootユーザーにて起動する必要がある。

###2. CentOS 7以降での設定
Zabbixの公式ドキュメントを見ると、systemdのユニット定義ファイルの[Service]ディレクティブの内容をrootに書き替えることでrootユーザーにてエージェントを起動することが出来ると書かれている。
[Zabbix Documentation 5.4
└8 Running agent as root](https://www.zabbix.com/documentation/current/en/manual/appendix/install/run_agent_as_root)

```
[Service]
User=root
Group=root
```
しかしsystemdはCentOS 7以降で使われているサービス管理アーキテクチャであるため、CentOS 6以前のOSでは別の方法で設定を行う必要がある。

###3. CentOS 6以前での設定方法
**/etc/sysconfig**ディレクトリ配下に**zabbix-agent**ファイルが存在するため、このファイルの内容を下記に書き換える。

```linux:/etc/sysconfig/zabbix-agent
ZABBIX_AGENT_USER=zabbix
↓変更後
ZABBIX_AGENT_USER=root
```

次にZabbixエージェントの設定ファイルのroot起動設定を許可を行う。
これに関してはOSのバージョンが7以降でも一緒の手順である。

```linux:/etc/zabbix/zabbix_agentd.conf
# AllowRoot=0
↓変更後
AllowRoot=1
```

一連の設定が完了したら、Zabbixエージェントの再起動を行う。
そして起動プロセスを確認してみると、実行ユーザーがrootに変更されていることが確認できます。

```
#service zabbix-agent restart
Shutting down Zabbix agent:                                [  OK  ]
Starting Zabbix agent:                                     [  OK  ]
#ps -ef | grep zabbix | grep -v grep
root     24431     1  0 07:06 ?        00:00:00 /usr/sbin/zabbix_agentd -c /etc/zabbix/zabbix_agentd.conf
root     24432 24431  0 07:06 ?        00:00:00 /usr/sbin/zabbix_agentd: collector [idle 1 sec]
root     24433 24431  0 07:06 ?        00:00:00 /usr/sbin/zabbix_agentd: listener #1 [waiting for connection]
root     24434 24431  0 07:06 ?        00:00:00 /usr/sbin/zabbix_agentd: listener #2 [waiting for connection]
root     24435 24431  0 07:06 ?        00:00:00 /usr/sbin/zabbix_agentd: listener #3 [waiting for connection]
root     24436 24431  0 07:06 ?        00:00:00 /usr/sbin/zabbix_agentd: active checks #1 [idle 1 sec]
```

これにて設定は完了となります。
Mac でのgit導入に際して（xcodeのライセンス認証）

macでgitを導入するときに少しつまづいたので備忘録的に解決法を残しておく。

まずターミナルで

```
git --version 
```

とコマンドを入力してgitが入っているかとバージョンを確認しようとすると

```
You have not agreed to the Xcode license agreements. You must agree to both license agreements below in order to use Xcode.
```

とのメッセージが出てきた。
どうやらxcodeのライセンス許可がいるらしい。

ターミナルで

```
sudo xcodebuild -license
```

を実行し、macのパスワードを入力
何度かスペースを押して承諾していくと最後に

```
By typing 'agree' you are agreeing to the terms of the software license agreements. Type 'print' to print them or anything else to cancel, [agree, print, cancel]
```

と出てくるのでターミナルに

```
agree
```

と入力し完了。


再び

```
git --version
```

を実行すると

```
git version 2.32.0 (Apple Git-132)
```

と表示され見事使えるようになった。
Julia: MariaDB のデータを削除 (Delete)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.jl
└── maria_delete.jl
```

```julia:maria_delete.jl
#! /usr/bin/julia
#
#	maria_delete.jl
#
#						Feb/24/2023
# --------------------------------------------------------------------
using MySQL
include("config_mariadb.jl")
# --------------------------------------------------------------------
println(stderr,"*** 開始 ***")
key_in = ARGS[1]
println(key_in)

host, user, password, data_base = config_mariadb_proc()
conn =DBInterface.connect(MySQL.Connection, host, user, password)
command = "delete from " * data_base * ".cities where id = '" * key_in * "'"
println(command)
#
results = DBInterface.execute(conn,command)
println(results)
#
DBInterface.close!(conn)
#
println(stderr,"*** 終了 ***")
# --------------------------------------------------------------------
```

.env
config_mariadb.jl
はこちら
[Julia: MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/dd01c569d386c44213b3)

## 確認したバージョン

```text
$ julia -v
julia version 1.8.5
```
Julia: MariaDB のデータを更新 (Update)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.jl
└── maria_update.jl
```

```julia:maria_update.jl
#! /usr/bin/julia
#
#	maria_update.jl
#
#						Feb/24/2023
# --------------------------------------------------------------------
using MySQL
include("config_mariadb.jl")
# --------------------------------------------------------------------
println(stderr,"*** 開始 ***")
key_in = ARGS[1]
population_in = ARGS[2]
println(key_in,'\t',population_in)
#
today = Libc.strftime("%F", time())
println(today)

host, user, password, data_base = config_mariadb_proc()
conn =DBInterface.connect(MySQL.Connection, host, user, password)

command = "update " * data_base * ".cities" * " set population = " * population_in
command *= " , date_mod = '" * today * "'"
command *= " where id = '" * key_in * "'"
println(command)
#
results = DBInterface.execute(conn,command)
println(results)
#
DBInterface.close!(conn)
#
println(stderr,"*** 終了 ***")
# --------------------------------------------------------------------
```

.env
config_mariadb.jl
はこちら
[Julia: MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/dd01c569d386c44213b3)


## 確認したバージョン

```text
$ julia -v
julia version 1.8.5
```
Herokuにデプロイまで流れとつまずいたこと

<h2>はじめに</h2>
Ruby on Railsチュートリアルを学習していた際、Herokuにデプロイする時にエラーに苦戦し、情報共有できればと思い記事にしました。

<h2>自身のスキル</h2>
プログラミングの学習をし始めて２ヶ月になります。
現在Ruby on Railsチュートリアルを中心に学習しています。もし違っているところなどございましたら、ご指摘いただければうれしいです。

<h2>自身の開発環境</h2>
・Ruby 3.0.3
・Rails 6.1.4.4
・エディタ　Atom
・m1 mac

<h2>Herokuへデプロイを行う流れ</h2>

②ステージングエリアへ

```
$　git add -A
```

③コミットする

```
$ git add commit -m"コミットメッセージ"
```

④Herokuにloginする

```
$ heroku login
```

⑤Herokuに新しいアプリケーションを作成する

```
$ heroku create
$ heroku create アプリ名　※アプリ名を指定したい時
```

⑥Herokuへデプロイする

```
$ git push heroku main
```
<h1>エラーが...</h1>

```
Enumerating objects: 106, done.
Counting objects: 100% (106/106), done.
Delta compression using up to 8 threads
Compressing objects: 100% (87/87), done.
Writing objects: 100% (106/106), 142.35 KiB | 7.12 MiB/s, done.
Total 106 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote:  !     Warning: Multiple default buildpacks reported the ability to handle this app. The first buildpack in the list below will be used.
remote:                         Detected buildpacks: Ruby,Node.js
remote:                         See https://devcenter.heroku.com/articles/buildpacks#buildpack-detect-order
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.2.21
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-3.0.3
remote: -----> Installing dependencies using bundler 2.2.21
remote:        Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote:        Your bundle only supports platforms ["arm64-darwin-21"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote:        Bundler Output: Your bundle only supports platforms ["arm64-darwin-21"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote: 
remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !       Push rejected to アプリ名.
remote: 
To https://git.heroku.com/tw1226hello.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/アプリ名'

```

⑦エラーないに書いてあるbundle lock --add-platform x86_64-linuxを実行
その後、デプロイ

```
$ bundle lock --add-platform x86_64-linux
$ git add -A
$ git commit -m "Gemfile.lock fix"
$ git push heroku main
```

無事にデプロイできました。
SolrJ で NoSuchMethodError



# 現象

SolrJ を利用したら NoSuchMethodError org.apache.http.impl.conn.PoolingHttpClientConnectionManager.setValidateAfterInactivity(int) が出た．

```
Exception in thread "main" java.lang.NoSuchMethodError: 'void org.apache.http.impl.conn.PoolingHttpClientConnectionManager.setValidateAfterInactivity(int)'
	at org.apache.solr.client.solrj.impl.HttpClientUtil.createClient(HttpClientUtil.java:297)
	at org.apache.solr.client.solrj.impl.HttpClientUtil.createClient(HttpClientUtil.java:348)
	at org.apache.solr.client.solrj.impl.HttpClientUtil.createClient(HttpClientUtil.java:286)
	at org.apache.solr.client.solrj.impl.HttpClientUtil.createClient(HttpClientUtil.java:273)
	at org.apache.solr.client.solrj.impl.HttpSolrClient.<init>(HttpSolrClient.java:204)
	at org.apache.solr.client.solrj.impl.HttpSolrClient$Builder.build(HttpSolrClient.java:968)
	at nlp4j.solr.importer.SolrDocumentImporter.importDocument(SolrDocumentImporter.java:68)
```

# 原因

他のライブラリが先に httpclient-4.3.6 や httpcore-4.4.13 などをロードしており，このライブラリが古いためと思われる．

Eclipse で確認したら以下の通りだった．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/08f87cd7-88f6-2832-0759-b0837ef86334.png)


# 解決方法

httpclient 4.5.13 をライブラリとして指定する．

```
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.5.13</version>
</dependency>
```

Eclipseでも確認できました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/a87c3669-eec5-52ac-01c8-3e613ec78ff1.png)


以上．
Mecab を Javaから利用してエラーになったケース mecab_new2(org.bridj.Pointer)



# 現象

Mecab for Java を利用したら以下のエラーになった．

```
java.lang.UnsatisfiedLinkError: 'org.bridj.Pointer net.moraleboost.mecab.impl.StandardTagger.mecab_new2(org.bridj.Pointer)'
	at net.moraleboost.mecab.impl.StandardTagger.mecab_new2(Native Method)
	at net.moraleboost.mecab.impl.StandardTagger.<init>(StandardTagger.java:36)
...
```

# 解決方法

以下を参考に，64ビット版を導入して，DLLをSystem32にコピーしたら直りました．

https://qiita.com/oyahiroki/items/cffa913866289a2bb928



以上．
【python】python×sakuraエディタのgrep自動化メモ

#1.はじめに

仕事をしていると、何度も同じ作業が発生したりすることがある。

あるフォルダにあるソースを毎日、いくつかの項目でgrepする。前日との差分比較をしたいため、テキストファイルに実施日付もファイル名に追加して保存。
大した時間ではないが、毎回だと鬱陶しい。

今回は(1),(2)を実行するスクリプトを作成することにした。

(1)sakuraエディタで指定フォルダをlotoでgrepをしたものをgrep_result_yyyymmdd.txtと名前を付けて保存

(2)sakuraエディタで指定フォルダをinsert into またはでgrepをしたものをinsert_result_yyyymmdd.txtと名前を付けて保存

#2.sakuraエディタ

下記場所からインストールできるフリーの高機能エディタ。
[サクラエディタ](https://sakura-editor.github.io/)
使用頻度の高いgrep機能と、豊富なコマンドラインオプションが魅力的なエディタだと個人的には思っている。
コマンドラインオプションを使用することで、やりたいことのほとんどが実行できる。


#3.実施手順

実装方法としては極めてシンプル。
（１）時刻の文字列を取得
（２）同じファイル名がある場合は削除
（３）サクラエディタのコマンドを実行

コマンドプロンプトにコマンドを打ち込むだけで、やりたい事はできるが
毎回コマンドを打ち込むのは面倒だ。

当初カッコよさを求めてpyautogui(マウス操作キーボード操作の自動実行モジュール)もトライしたけど上手くいかないことがわかって、上記方法に辿り着いた。

※pyautoguiでの自動実行を考えている場合は、本記事は役にたちません。

実行環境:OS:windows10,Python:3.8.10


#4.メモ(sakuraエディタのコマンドラインオプション)

__`(1)GFILE:検索対象のファイル`__
例）-GFILE="\*.java|\*.jsp"

__`(2)GFOLDER:検索対象のフォルダ`__
例）-GFOLDER="C:\data"

__`(3)GKEY:検索文字列`__
例）-GKEY="loto6"

__`(4)GOPT:オプション`__

S:サブフォルダも検索
R:正規表現を使える
U:結果出力先のファイルを指定できる(リダイレクトやパイプの後に出力ファイルを指定)

例)-GOPT="SRU"

#5.メモ(python)

__`(1)subprocess.run`__
指定したコマンドが終了してから、次のコマンドを実行する。
Popenは非同期で実行するところが違う。
例）subprocess.run(cmd0,shell=True)


#6.ソース

```python:sakura_auto.py
# -*- coding: utf-8 -*-
import subprocess
import time
import os
from datetime import datetime as dt
tdatetime=dt.now()
tstr=tdatetime.strftime('%Y%m%d')

def exec_grep(cmd0,fname0):
  if os.path.isfile(fname0):
    os.remove(fname0)
  subprocess.run(cmd0,shell=True)

pgname="\"C:\Program Files (x86)\sakura\sakura.exe\""+" -GREPMODE"
dirname="-GFOLDER=\"C:\pleiades\workspace\""
gfile="-GFILE=\"*.java | *.jsp\""
gkey1="-GKEY=\"loto\""
gopt="-GOPT=SRPW1UH"
fname1="C:\grep_result\grep_result_"+tstr+".txt"
cmd1=pgname+" "+dirname+" "+gfile+" "+gkey1+" "+gopt+">"+"\""+fname1+"\""
exec_grep(cmd1,fname1)

fname2="C:\grep_result\sql_result_"+tstr+".txt"
gkey2="-GKEY=\"insert into |select \* from \""
cmd2=pgname+" "+dirname+" "+gfile+" "+gkey2+" "+gopt+">"+"\""+fname2+"\""
exec_grep(cmd2,fname2)
```
※>の前後にはスペースなどを入れるとエラーが出るので注意。
PDFをPowerPointに張り付ける

# 1. PDFファイルをPPTに張り付ける方法はいくつかある。
PDFをPPTに取り込むと、解像度が落ちたり、フォントが変わったりしやすい。A4の解像度が決まっているなら、何らかの形で、解像度の画面を作成すれば回避できる。


## 1.1. 図として貼りつける

- (手順) PDFを図として取り込み。解像度をそろえるには、A4の場合、300dpi(縦の場合2480x3508)もしくは600dpi(縦の場合4961x7016)のイメージを用意しておく必要がある。例えば、Adobe Acrobat Readerなら、以下のように行う。
  - 編集=>環境設定=>一般=>スナップショットツール画像に固定解像度を使用(600dpiなど)
  - 編集=>スナップショットで画面コピー 
- (得失) きっちり解像度を揃えるのが面倒である。ただし、そこそこ使える解法が存在する。


## 1.2. オブジェクトとして貼りつける。

- (手順) オブジェクトの挿入=>ファイルの挿入
- (得失) 解像度がおちる。ただし、クリックすると元のPDFファイルがそのまま表示される。

## 1.3 Adobe Acrobat/PDFelementで変換

- (手順) PDFelementでPPTに変換する。(透かし入りなら無料で試せる。)
- (手順) Adobe AcrobatでPPTに変換する　(こちらもWebでは試せる)
- (得失) フォントは、詳細に表示される。しかし、フォントが変わる。

# 参考資料

- [PDFファイルを画像に変換する方法【高解像度・Acrobat 無料版】](https://kamelab.info/pcskill/pdf-image/#PDF-3)
- [(microsoft) PDF ファイルの内容を PowerPoint プレゼンテーションに挿入する](https://support.microsoft.com/ja-jp/office/pdf-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92-powerpoint-%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E6%8C%BF%E5%85%A5%E3%81%99%E3%82%8B-5e7719d5-508c-4c07-a3d4-68123c373a62)
- [Wondershare PDFelement](https://pdf.wondershare.com/)
- [(Adobe Support Community)パワポとうまくリンクできる方法](https://community.adobe.com/t5/indesign%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0-discussions/%E3%83%91%E3%83%AF%E3%83%9D%E3%81%A8%E3%81%86%E3%81%BE%E3%81%8F%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%A7%E3%81%8D%E3%82%8B%E6%96%B9%E6%B3%95/td-p/10311396)
- [印刷解像度と画素数](https://popup.jp/dpi/)