OmniAICreator/Qiita-1.07M huggingface dataset:
単回帰分析における最小二乗誤差について

#　はじめに
　最小二乗誤差、残差、、
　これらの言葉は聞いたことがある、、
　でも何を指している言葉なのか、どのように利用されているのか曖昧な方も多いと思います。
　なので今回はこれらの言葉を説明していきたいと思います
　簡単のため今回は単回帰しか触れません、重回帰は次回の記事で触れます。
　今回は単回帰についての説明は省きますね
　もしわからない方は単回帰について学んでから読んでいただけると理解が深まると思います
　では学んでいきましょう！！

#　単回帰における最小二乗誤差について
　まずは最小二乗誤差についてみていきましょう
　ですが、その前に**「誤差」**について知っておく必要があります
　**「誤差」**とは、実際の目標値と回帰を利用して予測した値の差のことです。「差」なので絶対値を取ります。
　図式と数式でみていきましょう

![PART2 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2135815/4a53cb3b-613c-eacd-5797-76a55a0f59e9.png)



　ちょっと(だいぶ)画質荒いですが許してください笑
　青点が実際に観測されている点で青の実線が近似曲線になっています
　ここでいうと**「誤差」**は黒直線部分になります
　さて、これを数式化させてみていきましょう

```math
誤差:error \\
実際の(真の)値:t_i\\
単回帰式:wx + b\\
誤差は以下式で与えられます\\
error = |t_i - (wx + b)|\\
```
　
　上記のように与えられますね
　なんですけど、結局は**「誤差」**を最小化させたいですよね。これを**「最適化」**っていうんですけど最適化するには絶対値って邪魔ですよね。いちいち中身の正負を見ないといけないですから。なので**二乗**しましょうとします。
　ってして生まれるのが**「二乗誤差」**になります。
　で、全部の事象においての**「二乗誤差」**を足しあわせてこれを最小化させたとします。
　そうすると、二乗誤差の和が最小値になる、つまり最も当てはまりが良くなりますよね。これが**「最小二乗誤差」**になるわけです。つまり最小二乗誤差の数式は以下のように表されます。

``` math
最小二乗誤差:E(w) \\
実際の(真の)値:t_i\\
単回帰式:wx + b\\
データ数:N\\
最小二乗誤差は以下のように与えられます\\

E(w) = \frac{1}{N}\Sigma_{i = 1}^{N}(t_i - (wx_i + b))^2
```

　で少し数式見て欲しいんですけど我々が決めなきゃいけないのは**wとbだけ**ですね。

#　残差について
　**「残差」**というものを押さえておきましょう。
　これは最小二乗法の代数的法則についての説明に使われるのですが、先に触れておきます。
　一部最小化についてのお話が出てくるので普通順番は逆なんですけど、こちらはあまり複雑にならないので先に説明をして肩慣らしをしてもらおうと思います。
![PART2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2135815/5495b344-3fd7-820e-f76a-e32d7fe41f38.png)
　この図は前の章で紹介したのと同じものになります。ただ、乱数入れてるので真の値の部分の分布が若干異なります。
　さっきは青の直線(元の直線、真の回帰式)　との差を見ていましたが今回は予測した直線との差を見ます。
以下の図のような感じですね
![PART2 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2135815/fa24ec48-aa4b-cc98-9306-60940d8f1f59.png)
　この差が**「残差」**と呼ばれます。そして残差には大きく3つの特徴があります。
　　一つ目は総和が0になること
　　二つ目は説明変数と残差の積和が0になること
　　三つ目は推定値(t_i)と残差が無相関であること


　残差の総和が0になるってことだけは肩慣らしとして証明します
![スクリーンショット 2021-11-16 19.34.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2135815/9f60c29b-da5c-0aed-1adc-d9a23d68f188.png)

　字が下手なのは許してください、、笑
　まあ、これで残差の総和が0になることがわかりましたね
　説明変数と残差の積和が0になることは**相関係数が0**であることを示しています。これはwの方で微分してあげれば同じ形で証明が可能です。こちらは今回省略させていただきます。

#　単回帰における最小二乗誤差の最適化
　それじゃ本題です
　最小二乗誤差の最適化(最小化)について考えましょう
　先ほどの手書きの証明部分にもありましたが、w^とb^(^は「ハット」だと思ってください)についての微分がそれぞれ0になるようなw^とb^を求めましょ、という話です。これも手書きで失礼しますね。
![PART 2 (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2135815/6e8643f7-9462-b86a-e38f-0be9845050b4.jpeg)
![PART 2 (6).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2135815/b3686d6f-4232-ab4c-2454-1fcb8664a3c9.jpeg)
　いやあ、長かった笑
　赤線の部分が前章で触れた回帰係数が標本平均点を通る証明になりますね。
　また、求めたかったb^とw^が求まりましたね。
　これが最小二乗誤差を最小にする値になります。

#　最小二乗法の代数的法則
　ここは今までのまとめなんでさっと終わらせようと思います。
　まずは前々章で触れた残差に関する三つの法則です。

　　**1.総和が0になること**
　　**2.説明変数と残差の積和が0になること**
　　**3.推定値(t_i)と残差が無相関であること**

　また、前章において赤線で強調している部分を見てもらうと予測された回帰直線はtとxそれぞれの平均をプロットした点を必ず通ります。この点のことを**標本平均点**と呼びます。これをまとめると

　　**4.予測された回帰直線は標本平均点を通る**

　これら4つが大きな代数的法則になります

#　さいごに
　今回は単回帰の最小二乗誤差とその最適化について学んでいきました。

　写真で手書きになってしまったところは申し訳ありませんが、なるべく途中式を省かずに書いたつもりです。参考になっていれば幸いです

　次回は重回帰について学んでいこうと思います！！
【Python】商圏分析のためにYahooローカルサーチAPIから周辺店舗情報を取得してみた

# 初めに
商圏分析ために、周辺店舗情報をAPIにて取得する。Google Maps Platformの[PlaceAPI](https://developers.google.com/maps/documentation/places/web-service/overview)でも同じことはできそうだが、無料で試せるYOLPにて取得してみた。
[Yahoo!ローカルサーチAPI ](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/localsearch.html)を使用し、中心位置を指定して円範囲で絞り込む。

>[リファレンス](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/localsearch.html)より引用
>Yahoo!ローカルサーチAPI(以下、ローカルサーチAPI)は、店舗、イベント、クチコミ情報などの地域・拠点情報(POI)を検索するためのAPIです。
検索対象は、全国の店舗を網羅した電話帳データおよび店舗オーナーなどからの投稿データです。

## 環境
-Windows10
-Python 3.9.8

## パラメータ
* appid => Yahooデベロッパー登録をし、取得する
* lat => 中心緯度(世界測地系)
* lon => 中心経度(世界測地系)
* output =>  出力形式を指定(json/xml)
* date =>日時を指定(YYYYMMDDHHMI形式)
* distance => 中心からの距離(km)
* sort =>さまざまなパラメータにより算出した適合度順/距離(hybrid/geo)
* gc => [業種コード](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/genre.html)。今回は01「グルメ」にて取得。

本コードではyahoo_url.formatにてパラメータをセットしてください。

## 仕様による条件
* 検索距離は、最大20km
* 1回の取得件数は、最大100件
* 1条件の取得件数は、最大3000件(初期値を指定し取得する必要がある)今回のプログラムでは未対応

# コード
```python:yahoo_location_api.py
# -*- coding:utf-8 -*-
import requests
import json

# Yahoo weather APIにて気象情報を取得する
yahoo_url = "https://map.yahooapis.jp/search/local/V1/localSearch?appid={appid}&lat={lat}&lon={lon}&dist={distance}&output={output}&sort={sort}&gc={gc}&start={start}"
yahoo_url = yahoo_url.format(appid="xxxxxxxxxxxxxxxxxxx",
                             lat="34.000000", lon="135.00000000", output="json", distance="5", sort="geo", gc="01")
# distance=km,gc=業種コード

yahoo_json = requests.get(yahoo_url).json()
print(yahoo_json)
```
# 終わりに
他にもいろんな条件を指定できるので、リファレンスを調べてみてください。
また業務で使用する際は、使用許諾等を確認する必要があります。（[ガイドライン等](https://developer.yahoo.co.jp/webapi/map/faq.html)）

諸注意が必要なものの、[ぐるなびやゼンリン、電話帳データ](https://map.yahoo.co.jp/promo/app/license/attribution.html)が無料で使用できるのは非常にありがたいことです。今後もこのAPIを使っていろんなことをしてみたいと思います。

## 参考
Google Maps Platformの方が掲載数が多そうですが、利用許諾の範囲が狭く、下記のような[Google Maps API 利用規約](https://developers.google.com/maps/terms-20180207?hl=ja)の遵守が必要です。

>一部抜粋
10.5 知的財産権に対する制限
d.コンテンツをキャッシュ保存または保管しない。
本サービス以外で使用するコンテンツをプリフェッチ、キャッシュに保存、インデックス登録、または保管しないものとします。

>10.4 本サービスおよびコンテンツの不正利用に対する制限 
 d.お客様の Maps API 実装に対する制限
Google マップを表示せずに本コンテンツを使用しない。Maps API ドキュメントで明示的に許可されていない限り、対応する Google マップなしでは Maps API 実装で本コンテンツを使用しないものとします。

つまり、CSV等での保存ができない。Google Map以外の地図と組み合わせての分析ができない。
などの制限があると言うことです。
Excelでリストを作ったり、GISでの分析ができないため、使用には注意が必要です。



# 参考サイト
https://developer.yahoo.co.jp/webapi/map/

https://serendipity0926.hatenablog.com/entry/2021/06/12/214759

https://developers.google.com/maps/terms-20180207?hl=ja
springのInvalid character found in method name [...]. HTTP method names must be tokens

spring-boot使用時に以下のエラーが発生した。

```java

java.lang.IllegalArgumentException: Invalid character found in method name [0x160x030x010x020x000x010x000x010xfc0x030x030xda0xb8Aqh0xc5,0x910xfa0xc30xc90xbf0x8a0x8f?0xf50xf80x14K0x930xf2Y0xd10xb0A%0xa30xef0x8e.Q+ ]. HTTP method names must be tokens
	at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:419) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:269) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
```

これの原因は https://stackoverflow.com/questions/38891866/when-spring-boot-startup-throw-out-the-method-names-must-be-tokens-exception にあるように、```http```のところ```https```でアクセスしてしまった時に主に発生するようだ。クライアントは暗号化されたデータを送信するが、サーバはraw dataとして処理しようとするのでエラーになる。
HIVE-6384 さんにお帰りいただいた話

検索しても有用な情報が少なかったのですが、直面した HIVE-6384 エラーを解消した話です。

# 出たエラー

```
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. java.lang.UnsupportedOperationException: Parquet does not support date. See HIVE-6384
This query ran against the "xxx" database, unless qualified by the query. Please post the error message on our forum
or contact customer support with Query Id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

# 実行した SQL on Athena

```sql
CREATE EXTERNAL TABLE IF NOT EXISTS xxx.fact_members
(
  member_id  INT          COMMENT '会員ID',
  birth_date DATE         COMMENT '生年月日',
  trigger    VARCHAR(216) COMMENT '会員登録のきっかけ'
)
COMMENT '会員ファクト'
STORED AS PARQUET
LOCATION 's3://{BUCKET}/fact_members/process_date=2021-11-16'
TBLPROPERTIES (
  'parquet.compress' = 'SNAPPY'
);
```

## 調べたこと

カラムを削ってみたりしたところ `trigger` が悪さをしてそうなこと
DATE 型のカラムがなければ問題なく動くことがわかりました。

DATE 型のカラムは欲しかったので `trigger` をなんとかできないか検討。

Athena で例えばスペース入りのカラム名でクエリするときなどはダブルクォートだったのですが、それでは動かない。

```sql
CREATE EXTERNAL TABLE IF NOT EXISTS xxx.fact_members2
(
  member_id  INT          COMMENT '会員ID',
  birth_date DATE         COMMENT '生年月日',
  "trigger"  VARCHAR(216) COMMENT '会員登録のきっかけ'
)
COMMENT '会員ファクト'
STORED AS PARQUET
LOCATION 's3://{BUCKET}/fact_members/process_date=2021-11-16'
TBLPROPERTIES (
  'parquet.compress' = 'SNAPPY'
);
```

>line 1:8: mismatched input 'EXTERNAL'. Expecting: 'OR', 'SCHEMA', 'TABLE', 'VIEW'

# 解決

カラム名をバッククォートで囲むことで対応できました。

```sql
CREATE EXTERNAL TABLE IF NOT EXISTS xxx.fact_members2
(
  member_id  INT          COMMENT '会員ID',
  birth_date DATE         COMMENT '生年月日',
  `trigger`  VARCHAR(216) COMMENT '会員登録のきっかけ'
)
COMMENT '会員ファクト'
STORED AS PARQUET
LOCATION 's3://{BUCKET}/fact_members/process_date=2021-11-16'
TBLPROPERTIES (
  'parquet.compress' = 'SNAPPY'
);
```
Ubuntu上でQUIC対応のWiresharkをビルドする

手元のUbuntuマシンでインストールされているWiresharkのバージョンが3.2.3でQUICに対応していなかったので、QUICに対応しているバージョン3.4.9のものをビルドした。

その時の手順をまとめておく。

## 環境
- Ubuntu20.04 x86_64

## ソースの取得

```bash
$ wget https://2.na.dl.wireshark.org/src/wireshark-3.4.11.tar.xz
$ tar -xf wireshark-3.4.9.tar.xz
$ cd wireshark-3.4.9
```

## ビルドに必要なツールのインストール

```bash
$ sudo ./tools/debian-setup.sh --install-optional --install-deb-deps --install-test-deps
```

## ビルド

```bash
$ mkdir build && cd build
$ cmake -G Ninja ..
$ ninja
```

かなり時間がかかるので気長に待つ。

## 動作確認

```bash
$ ./run/wireshark -v
Wireshark 3.4.9 (Git commit 365e236f5efe) 
.
.
.
```

## 参考資料
- [Chapter 2. Quick Setup | Part I. Wireshark Build Environment](https://www.wireshark.org/docs/wsdg_html_chunked/ChapterSetup#ChSetupUNIX)
- [Download Wireshark](https://www.wireshark.org/download.html)
Apple WatchでSafariブラウザ相当の機能を使う方法（ショートカットアプリ経由）

# はじめに

Apple Watchでブラウザが使えたらなぁ・・・。
iOS14の時はショートカットアプリを使えば出来ていたのだけど、iOS15にバージョンアップして使えなくなっていて諦めていました。
でもきちんとショートカットの内容を確認したら、出来るようになりました。

# 動作環境

- iPhone8 Plus
  - iOS15.1
- Apple Watch Series 6
  - WatchOS 8.1(19R570)

# 期待する結果

実用性は微妙ですが、Apple Watchでブラウザが使えます。
ショートカットアプリ経由でですが、ちょっとした確認がスマホを取り出さなくても出来るのは、良いことですよね。

![E970CC1D-C7BC-4919-903F-AAF6E01D95F8_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/26b7ae4c-5c3d-d0b1-c186-06c85343bd0a.jpeg)

# 実験内容

ショートカットを2つ用意しました。
ブラウザ実験Aとブラウザ実験Bです。
（画像の順序は逆になってますがお許しください...）

![37E0DB78-206A-4399-A9E0-D6F8C30B1D74_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/273c5cb1-98cc-d246-bfae-98e8dbd01d2a.jpeg)

## ブラウザ実験A

![IMG_4225.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/e924ff92-0d23-5a71-7789-1474eed853d9.jpeg)

この方式だと期待通りの挙動になりませんでした。

![3C999C94-85D0-42BC-91E3-F52D6A7C4238_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/ef8fd880-ee3e-ac44-66fd-c79eb8fe1b5b.jpeg)


## ブラウザ実験B

![IMG_4226.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/9e0e8f42-deb0-7944-bbb1-0657f90301a8.jpeg)

こちらの方式だと期待通りになりました。

![E970CC1D-C7BC-4919-903F-AAF6E01D95F8_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/26b7ae4c-5c3d-d0b1-c186-06c85343bd0a.jpeg)

# 考察

ブラウザ実験Aの場合は、ショートカットの定義で「URLを開く」

ブラウザ実験Bの場合は、ショートカットの定義で「Webページを表示」

「URLをSafariで開く」 か「Safariビュー コントローラで開く」　の違いです。
Apple Watchには、Safariがインストールされていないので、ブラウザ実験Aは失敗しました。
当たり前と言えば当たり前なのですが、この記事がどなたかのお力になれば幸いです。

最後に、macOS MontereyはiOS版と連動してショートカットを編集できるようになったので、以前よりも作りやすくなりました。
皆さまも是非何か作ってみてはいかがでしょうか。
【Python】Yahoo 気象情報API から雨量情報を取得してみた

# 初めに
ダッシュボード作成のために、雨量をAPIにて取得する
[YOLP 気象情報API ](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/weather.html)を使用する。

>[リファレンス](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/weather.html)より引用
>指定した緯度経度の雨の強さを取得できるAPIです。
>現在時刻の降水強度実測値から、60分後までの降水強度予測値を取得できます。

## 環境
- Windows10
- Python 3.9.8

## パラメータ
* appid => Yahooデベロッパー登録をし、取得する
* lat_lon => 経度,緯度(世界測地系)
* output =>  出力形式を指定(json/xml)
* date =>日時を指定(YYYYMMDDHHMI形式)

本コードではyahoo_url.formatにてパラメータをセットしてください。

# コード
```python:yahoo_weather_api.py
# -*- coding:utf-8 -*-
import requests
import json
import datetime
now = datetime.datetime.now()

# Yahoo weather APIにて気象情報を取得する
yahoo_url = "https://map.yahooapis.jp/weather/V1/place?appid={appid}&coordinates={lat_lon}&output={output}&date={date}"
yahoo_url = yahoo_url.format(appid="xxxxxxxxxxxxxxxxxxxxxxxxx", lat_lon="135.0000000,34.000000", output="json",
                             date=now.strftime("%Y%m%d%H%M"))

yahoo_json = requests.get(yahoo_url).json()
yahoo_date = yahoo_json["Feature"][0]["Property"]["WeatherList"]["Weather"][0]["Date"]
yahoo_rainfall = yahoo_json["Feature"][0]["Property"]["WeatherList"]["Weather"][0]["Rainfall"]

# 出力
print(yahoo_date)
print(yahoo_rainfall)
```
# 終わりに
実測値といえども、気象レーダー解析雨量のため実際の降雨量と差異があるが、アメダスがない地点の雨量も取得できるのは魅力的。
>※降水強度は、気象レーダーで観測された降水の強さを時間雨量(mm/h)に換算した値で、実際の雨量とは異なります。

# 参考サイト
https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/weather.html
【Unity】コルーチンを使わざるを得ないとき

余計な依存を増やしたくないとき、バニラ Unity で完結したいときは割とあります。

そんな時はコルーチンを使うことも選択肢に入ってきますね。


<!--
https://qiita.com/sator_imaging/items/2be781c1a396537fef20
-->

# なんでもコルーチン化できるヤツ


DOTween の代わりに使うコルーチンとして作った、けどこれであらゆる用途全部行けるのでは？ という `delegate` と `IEnumerator`。

今まで必要な数だけコルーチン用メソッドを作ってたけど、それも不要に。


```csharp
delegate bool AnimateFunction();

IEnumerator Animate(AnimateFunction func)
{
    var loopCount = 0; // increases faster when coroutines run simultaneously
    while (func() && loopCount++ < 9999) yield return null;

    if (9999 <= loopCount) Debug.LogError("Animate: Too many loops, take care.");
    yield break;
}
```


`loopCount` はコルーチンを複数走らせると増え方変わるけどまあおっけ。



# つかいかた


なんでも気軽にコルーチンとして処理出来て完璧に見える。

ほんのちょっと遷移入れたいだけだから、数行だから！ って時に便利。

```csharp
IEnumerator AnimateTestRoutine; // for StopCoroutine()

void AnimateTest()
{
    var t = 0f;
    var start = 0f;
    var end = 1f;

    AnimateTestRoutine = Animate(() =>
        {
            t += Time.deltaTime / 3.0f;
            Do_Something = Mathf.SmoothStep(start, end, t);
            return (t < 1);
        });

    StartCoroutine(AnimateTestRoutine);
}
```


便利すぎて何か落とし穴がありそう。



```csharp
int numCoroutinesRunning = 0;

IEnumerator Animate(AnimateFunction func)
{
    numCoroutinesRunning++;
    while (func()) yield return null;

    numCoroutinesRunning--;
    yield break;
}
```


こんな感じにすればアクティブなコルーチンの数もチェックできる。ハズ。




--


以上です。お疲れ様でした。
Unityの画面を動画として出力する

以下を参考にUnity Recorderを使ってUnityの画面を動画として出力してみたが、UIが異なり戸惑う点もあったので以下に手順をメモする。

https://learn.unity.com/tutorial/working-with-the-unity-recorder-2019-3-1?language=ja#5f714f92edbc2a0cebf51228

## 確認環境
- Unity 2019.4.31f1
- MacBook Pro (16-inch 2019)
- macOS Big Sur 11.5.2

## 手順

Window -> Package Manager と選択する。
![スクリーンショット 2021-11-16 19.59.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/0fff2f27-2df1-0cb4-4c48-a21054fe4d20.png)

Package Managerの画面で「Unity Registry」を選択し、検索窓に「recorder」と入れ、出てきたUnity RecorderをInstall。

![スクリーンショット 2021-11-16 20.00.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/dadb4123-a5b8-20b2-fece-22d79fcceed3.png)

インストールが完了したら、Window -> General -> Recorder -> Recorder Window。

![スクリーンショット 2021-11-16 19.42.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/1ff22515-ae64-5397-f12c-3c56fad0a85b.png)

Add Recorderを押す。

![スクリーンショット 2021-11-16 20.07.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/ee506f3e-6a1c-22df-13ac-60f9c33b4771.png)

Movie　を選ぶ。

![スクリーンショット 2021-11-16 20.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/b039f3f3-a854-0c00-5f93-db86edb635f1.png)

Output Resolutionで解像度、Aspect Ratioでアスペクト比を選ぶ。ここでは「HD - 720p」「16:9」を選ぶ（これはTwitter用動画の推奨設定の一つである。）

![スクリーンショット 2021-11-16 20.19.10 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/c49d5e0c-9b3f-0389-16f6-75bb9dc6e8b4.png)

START RECORDINGを押すと、自動的にPlay Modeに入り動画録画が開始される。
キーや操作パッド、マウスによる操作入力の結果も当然ながら録画されるので注意すること。

![スクリーンショット 2021-11-16 20.19.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/6b561c4f-7d96-6ead-d51c-bc9c642a2d62.png)

STOP RECORDING (1のところ)を押すと録画が停止される。動画は、画像の2のところに表示されているパスに保存されている。

![スクリーンショット 2021-11-16 20.10.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198108/dc8704cf-8448-a4d0-f574-3100215b8d81.png)

以下は試しに録画した動画

https://twitter.com/kabosu3d/status/1460579491919450115


以上。


## 参考
Twitterの推奨動画サイズ

https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/uploading-media/media-best-practices
> 推奨されるビデオ解像度：1280x720（横向き）、720x1280（縦向き）、720x720（正方形）
> 推奨アスペクト比：16：9（横向きまたは縦向き）、1：1（正方形）
aptからnodejsとnpmをインストールし、nから最新版のNode.jsのインストール

# aptからnodejsとnpmをインストール
```
$ sudo apt install nodejs npm
```

# npmからnパッケージをインストール
```
$ sudo npm install -g n
```

# nから最新版のNode.jsをインストール
```
$ sudo n latest
```

# nから最新のLTS版のNode.jsのインストール
```
$ sudo n lts
```

# 任意のバージョンのNode.jsのインストール
```
$ n ls-remote
# 12.8.1をインストールしたい場合
$ sudo n 12.8.1
```

# 参考
[Ubuntu18.04で任意のバージョンのNode.jsをインストールする方法](https://www.trifields.jp/how-to-install-node-js-on-ubuntu1804-3544)
kaminariを使用してbootstrap5でCSSを追加する

#はじめに

railsチュートリアルをローカル環境で進めています。
will_pagenate　gemを使っていますが、kaminariを使って実装してみようと興味本位でやってみた備忘録です。
こちらの記事を参考にされる方はバージョンにお気をつけください。

#環境
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [arm64-darwin20]
Rails 6.1.4.1
kaminari (1.2.1)
bootstrap (5.1.0)

#前提
bootstrapがアプリ内で使えているものとします。

https://qiita.com/mocomou_/items/95f1be13c9b0aafc422b

bootstrapの導入はこちらでどうぞ。

#①kaminariのインストール

https://rubygems.org/gems/kaminari

こちらからkaminariをインストールします。

これだけだと
![no-CSS-paginate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1836602/506d26b4-cc3a-7cd5-8e45-715b3b42d900.png)

こんな感じで寂しいので

![paginate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1836602/690b75df-7415-f67a-daee-7eaf33b52d59.png)

このようにするために

https://rubygems.org/gems/bootstrap5-kaminari-views

こちらもインストールします。

具体的には

```ruby:Gemfile
gem 'kaminari', '~> 1.2', '>= 1.2.1'
gem 'bootstrap5-kaminari-views', '~> 0.0.1'
```

としてから

```ruby:command
% bundle
```

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

#②下準備
今回はindexページにてユーザー一覧をページネーションを使用して実装します。

index.html.erb使うために、user_controllerのindexアクションでDBのUserテーブルから全てのユーザーを取得します。

```user_controller.rb
def index
  @users = User.all.page(params[:page]).per(30)
end
```

`User.all` でDBから全てのユーザーを取得し
`.page(params[:page])`でページネーションを使う指示をして
`.per(30)`で１つのページにつき30件データを表示させるようにします。

index.html.erbで表示させます。

```index.html.erb
<ul class="users">
  <% @users.each do |user| %>
    <li>
      <%= gravatar_for user, size: 50  %>
      <%= link_to user.name, user, class: "user" %>
    </li>
  <% end %>
</ul>

<%= paginate @users, theme: 'bootstrap-5' %>　　#ここがページネーション
```

先ほどコントローラで定義した＠usersに格納されたユーザーデータはeachを使って一つずつ表示されるのに使われ、さらにページネーションにも使われます。

`theme: 'bootstrap-5'`
こちらをつけることでCSSが適用されます。

#こちらを忘れずに！

rails serverを再起動したら読み込まれます。


#参考

https://note.com/yukinooffice/n/nedc2a9af2347

https://qiita.com/rio_threehouse/items/313824b90a31268b0074
「issueを立てるな！」

## 要約

OSS プロジェクトに issue を立てる事について。「最適化するな！」と同程度に「issueを立てるな！」を守りましょう。

## 導入

OSS プロジェクトに対して気軽に issue を立てられる事が良い事だと思ってる人が存外多いようで、その事に危機感を覚え、この記事を書き殴りました。
OSS プロジェクトに対して気軽に issue を立てられる事が良い事だとする認識は「地獄への道は善意で舗装されている」を地で行ってます、、、

## 見えてる景色の違い

世の中、無数に OSS プロジェクトが存在しますが、恐らく、、、

- 90% の OSS プロジェクトは作ってる本人以外誰にも見向きされてない。
- 9% の OSS プロジェクトは作ってる本人以外にも多少は興味を持たれている。
- 0.9% の OSS プロジェクトは普通に人気がある。
- 0.1% の OSS プロジェクトは大人気。

、、、細かい数字の精度はともかく、ノリとしてはパレートの法則よろしくこんな感じでしょう。

## 枯れ木も山の賑わい

貴方のプロジェクトは十中八九、人気が無いでしょう。素晴らしいソフトウェアであれば必ず人気が出ると言うモノでもありませんし、元より９割方のプロジェクトは人気が無いモノなので、別にそれを貴方が気に病む必要ありません。

人気のないプロジェクトにおいては、本来的には「そんなの README の一番最初に書いてあんだろうが！💢」ってブチ切れてもいいような内容の問い合わせの issue が立てられても、自分のプロジェクトに興味を持ってもらえた！ってだけで嬉しいモノでしょう。そしてそういうノリから、「みんなで互いに気軽に issue を立て合っていけばいいよね！」みたいな感じに考えてしまうかもしれません。

## 人気プロジェクトの運営者は疲弊している

人気プロジェクトとなると、話が全然変わってきます。真っ当な issue の対処だけでも大変ですし、さらに日常的に

- 要領を得ない機能要求
- 要領を得ない質問
- 要領を得ないバグ報告
- 実装の都合も、他の利用者の都合もガン無視した本人の都合全開の機能要求
- 不正確なバグ報告
- README に書いてある事すら読まずに投げてくる質問

、、、等々、手間暇かけさせられひたすら消耗させられるだけの issue が立て続けられます。
モノにもよりますが数としては１つや２つでも、メンタルにクる時はかなりキます。

## 「最適化するな！」

貴方が立てようとしてる issue は本当に必要なモノですか？　ちゃんとドキュメントには目を通しましたか？　レポート内容は正確ですか？　貴方は自分の立てる issue の品質に自信を持てますか？
特に個人でやってるプロジェクトだと、貴方が立てたクソ issue １つが切っ掛けでその OSS プロジェクトが終わりかねません。

最適化に関する「最適化するな！」と言うベストプラクティスに倣い、issue も「issueを立てるな！」がベストプラクティスだと思われます。

## issueを立てよう！

パフォーマンスがそのプロジェクトの至上命題である場合ですら「最適化するな！」というベストプラクティスは有効です。
無闇に最適化を施せばメンテナンス性を損ない競争力を失い、結局はパフォーマンスも出せなくなる為です。
もちろん、最適化が必要な場面はあります。しかし、それには事前にプロファイリングを行い、また、最適化を施したコードの速度が、犠牲にしたメンテナンス性に見合うモノであるか慎重に判断する必要があります。

issueも同じです。本当に必要なissueは立てましょう。過去issueに類似したモノはないか？　関連する範囲のドキュメントには全て目を通したか？　バグ報告ならバージョン、 expected(こうなる事が期待されるが), result(こうなった), 再現環境が適切に記述されてますか？　等々抜かりが無いように慌てず慎重にissueを立てましょう。

そして、 **立てたissueには責任を持ちましょう。** プロジェクトの運営者からの応答に対して、必ずなんらかのリアクションを行いましょう。

## 個人的見解

「ルールを作るな、ツールを作れ！」とも言われますし「人の善意やモラルに強く依存するシステムはクソ」だとも考えているので、現行の issue 周りのシステムには大胆な改善が必要だと考えてます。ただ、それが簡単にできる話なら、誰も苦労してねぇよ！ってところですが、、、

## 追記

いくつかの反応を頂いて、いろいろ補足が必要なように思いましたし、もっと色々言及しておきたい気持ちにもなりましたが、蛇足にもなりそうなので少しだけ追記しておきます。

### OSS はフラジャイルで儚い

大半の OSS は個人で且つプライベートの時間で作成されています。そのプロジェクトが貴方の目に留まった時点で、すでにかなりのボリュームのプライベートでの労力が投入されてるハズです。
そしてその OSS は言わば個人のプライベートでの時間的負担と精神的負担の犠牲の上に運営されています。
貴方や他の誰かが issue を立てて関わる関わらないに関係なく元よりいつ終了してもおかしくないフラジャイルで儚い存在です。
大半の OSS はクソ issue １つで簡単に終わりかねない前提にあります。「やってらんね」って思われたらそれで終わるんです。
Power BIレポート「DX Criteria・非公式ボード」

##はじめに
　今年を振り返り、いろいろ作ったPower BIレポートの中で私の中で印象的な「[DX Criteria v2021版・非公式ボード](https://ishiayaya.net/dxc2021)」を紹介します。

## DX Criteriaとは
　DX Criteriaとは、[一般社団法人 日本CTO協会](https://cto-a.org/)が公開しているもので、今年の4月に改訂しました。私はDX Criteriaが素晴らしいと思っており、これまでの取り組みをインタビュー記事にもしていただきました。

[自分の状態を知るのは何事も改善の第一歩。ノーコードツールを使い倒してアセスメントも簡単に | DX解体新書 auカブコム編 - 一般社団法人 日本CTO協会](https://cto-a.org/news/2021/04/21/4825/)

　日本CTO協会のオフィシャルのサイトは、元データがNotionで作られており、コンテンツをリリースサイトに自動発行される形で公開されています。
　DX Criteriaって内容が素晴らしい！とかなり強く思っていまいますが、いかんせん項目が320個と多い... 初めてみる方は、うっとくると思います。
　そこでも少しでも何のことが書かれているのかわかるといいなと重いって作成しました。

## Power BI レポート
　このレポートは、本家のDX Criteriからみると、**非公式なもの** です。

https://ishiayaya.net/dxc2021 がアドレスになります。

### ページ切り替え

　レポートの下部にあります。一般公開したPower BIレポートの共通のインターフェイスです。4ページあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/e90de5d5-fa5d-1bb8-f057-c5270a5d927f.png)


### 1ページ目
　上の5つのテーマを選択すると、その項目だけがクロスフィルターでフォーカスされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/5c22cca8-dab3-7850-f326-2708c1240ee8.png)
　右下のメモで、どこのデータの引用なのか明記しています。

### 2ページ目
　1テーマの中に8つのカテゴリがあり、その1つのカテゴリに4つのクライテリアがあります。クライテリアは4つの観点
　- メトリクスの計測 1つ
　- 学習と改善 1つ
　- プラクティス 3つ
　- アンチパターン (3つ。できている = 〇、の判定だと、それでいいの?という振り返り項目）
に分かれています。URLで、本家サイトの私のコピーサイトに飛びます。そこには、FAQや用語解説もあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/d548da95-2a31-cd12-f362-01f1e2d440bf.png)

### 3ページ目
　4月の改訂時に、導入ガイドとして、簡易アセスメントができる項目をチョイスしました。
大分類のシーン別に、10選+αのクライテリアをチョイスしています。「まずはここから」というものですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/1cd9215e-f7f1-eecd-fdf6-5aad4d41072e.png)

### 4ページ目
　DX Criteria は、広木大地 @hirokidaichi さんにより、5つのポリシーで整理されています。その内容と、キーフレーズをPower BIで品詞分解して、Word Crowdで載せました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/2c9a27e2-cc0a-bb2d-2e4c-974ae41ab025.png)

　品詞分解は、Power QUeryエディターのリボン[AI分析情報]/[Text Analytics]から行いました。Premium Per Userライセンス等が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/8f1a2554-6b14-6290-2290-8bcd3844695e.png)


##おわりに
 DX Criteria、良さそうだけど、まだ項目が多くて大変だな、と思われた貴方、10分で簡易診断するミニミニツールを、広木さんが2021年10月に作ってリリースしてくださいました。 こちらから　[日本CTO協会、デジタルの日に自社のDX偏差値を10分で分析できる「DX クライテリア簡易診断」リリース -デジタル化率と成長率を徹底分析「DX動向調査レポート」も一般公開- 一般社団法人 日本CTO協会](https://cto-a.org/news/2021/10/08/5524/) 是非お試しを。 AIにより、**10分の回答で** ほぼ320項目の診断を行った結果がわかりますよ~

[DXクライテリア簡易診断 | 日本CTO協会](https://dxcirt.cto-a.org/)

 また、広木さんがどのような背景で、DX Criteriaを作られたかについては、こちらのQiitaもご参照ください。

[「技術的負債」への処方箋と「２つのDX」 - Qiita](https://qiita.com/hirokidaichi/items/64b444a89410190d965f)
Amazon Location Serviceのジオコーディングのオプションを試してみる

## 概要
Amazon Location Serviceのジオコーディングでは、以下のオプションが用意されています

- 近くの場所のジオコーディング
- 境界ボックス内のジオコーディング
- 国内のジオコーディング

これらのオプションを、デモサイトに実装しましたので、紹介したいと思います

https://als.mierune.io/

![スクリーンショット 2021-11-17 2.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2788/73f4b62a-3f32-eb70-ec36-ee44ea8101a5.png)


## 近くの場所のジオコーディング

位置の近くの場所のジオコーディングを行います
デモサイトでは、表示されている箇所の中心位置に近い場所に対して行っています

```Javascript
// 中心から近い箇所の検索設定
// 中心位置オプションのチェックボックスが入っていた場合
if (this.search.selectedBiasCenterSearch === true) {
    // 中心座標の取得
    const center = this.mapObject.getCenter();
    // ポストパラメーターの設定
    params.BiasPosition = [center.lng, center.lat];
}
```
`BiasPosition`というオプションに、位置を設定すると、その位置から近い場所のデータが優先されて返ってきます

## 境界ボックス内のジオコーディング

指定した範囲の場所のジオコーディングを行います
デモサイトでは、表示されている範囲の場所に対して行っています

```Javascript
// 範囲の検索設定
// 範囲位置オプションのチェックボックスが入っていた場合
if (this.search.selectedBboxSearch === true) {
  //現在表示されている範囲のBBOXを取得
  const bounds = this.mapObject.getBounds();
  //　ポストパラメーターの設定
  params.FilterBBox = [
    bounds._sw.lng,
    bounds._sw.lat,
    bounds._ne.lng,
    bounds._ne.lat,
  ];
}
```
`FilterBBox`というオプションに、バウンディングボックスを設定すると、その範囲でジオコーディングしてくれます

## 国内のジオコーディング

`FilterCountries`というオプションに [ISO3166](https://www.iso.org/iso-3166-country-codes.html) の3桁の国コードを指定すると、指定した国の中だけでジオコーディング可能となります

デモサイトでは日本を指定してジオコーディングしています
パラメーターの値は配列で、複数の国を指定可能です

```Javascript
FilterCountries: ['JPN'],
```

---

以上、Amazon Location Serviceのジオコーディングのオプションの紹介でした
これらを実装したデモサイトはこちらになります

https://als.mierune.io/
メガネ販売員からエンジニアになってみて

# 概要
30歳を目前に控えた大人が何を思ったか長年勤めたメガネ販売員を突然やめ、なんやかんやで未経験からJavaエンジニアになりましたという話をしていきます。
同じような境遇の方に共感・力になれたら幸いです。

# 経歴
フリーターを経てメガネ販売員に就職。
アルバイトで入社して最終的に店舗責任者を任せられるまでになり７年以上勤務していましたが、エンジニアに役立つようなスキルとは一切関係ない仕事に生きてきました。

# エンジニアを目指した理由
長く勤めていた仕事を辞めた理由は、今後一生を共にできるような職を別の職種で模索したかったからです。
正直なところ、「エンジニアになりたかったから」辞めた訳ではありませんでした。

30歳を目前にし転職するには今しかないと思い辞める決意をしたのはいいものどこに転職したらいいのか…
そこが分からなかったからこそ今まで転職する勇気が持てなかったわけですが…今回こそはそうも言ってられないので、自身の棚卸からあらゆる職種の調査まで徹底的に行い自分にマッチする職業をひたすら調査しました。
幸いコーディングWebを漁れば無料で実践ができる環境がすぐ手に入るので、とりあえず実践できるのは大きかったですね。

結局エンジニアを目指した一番の理由は「コーディングしてみたら楽しかった」ですが、
他にも未経験転職のチャンス度、自分の長所・性格に合っているか…色々と総合的に考えた上で、一番自分に向いている職種だと思うことができたのが決め手でした。

# 実際エンジニアになってみて
まず第一に、転職して本当に良かったと思います。
最高の仕事をする為に、自分に合わない事柄を自分自身に強いて苦しむ必要はもうありません。。
仲間とコミュニケーションをとりながら、ひたすら画面と向き合って目指すものをコードに換えて実装するのみです。

学習はいくらやっても足りないです。未経験なので尚更です。
大分コードを書かせてもらえるようになりましたが自分がコーディングした個所を改修する度に苦しんでいます。誰がこんなコード作ったんだと。私です。
特に自分が実装したコードで本番環境でバグが出たときは本当にへこみますし責任を感じます。影響が出る範囲が前職とは色々な意味で比べ物にならないからでしょうか。

しかし失敗しても変に塞ぎ込むことも逃げ込むこともせずにきちんと受け止めることができています。自分に合う仕事を選ぶというのは逆に言えば色々な意味で言い訳が出来なくなるからかもしれません。
ともかく、毎日前を向きながら仕事ができています。
前職に勤めていたころは、こんな仕事ができるなんて考えてもいなかったことです。

# 今後はどんなエンジニアになりたいか
今ではコーディングの応用に加えある程度設計も考えられるレベルになることを目指し、日々学習し先輩のソースコード見たりしています。
とにかく「これを作って」と言われたら設計から考えコーディング出来るレベルになりたいです。
成果物は就職用で作って以来何も手を付けていないので、その内プライベートで何かWebアプリ（もしくはandroidアプリ）も作っていきたいところです。

# 最後に
前職にいる間、転職したほうが自分のためになると考えていたものの経歴の長さと努力の結果得た役職もあり、職替えする勇気がずっと出ませんでした。

しかし今では本当に勇気を出してよかったと心から思っていますし、毎日充実した生活を送れています。
未経験転職を成功させるには何より折れない強い気持ちが大事です。年齢が高い方は尚更大事です。

年齢は関係なく、転職するか否かはともかく、PCやモノ作りに興味ある方は是非一度コーディングを試してみてください。
初めて記事を書いたのでうまく書けてないとは思いますが、皆様に何か一つでも参考になるようなことがあれば幸いです。
Ubuntu20.04にて、warden svc upがERROR: docker-compose could not be found; になったので直した。

#はじめに
warden svc upがERROR: docker-compose could not be found; になったので
直すまでの道のり。

# 最終更新日
2021年11月16日

# 環境の情報
OS
Ubuntu20.04


# 注意
最新の状態を確認して下さい。

# 公式はこちら
https://docs.warden.dev/installing.html
https://docs.docker.jp/compose/install.html#linux-compose
https://docs.docker.com/compose/install/

#参考さま
https://ytyaru.hatenablog.com/entry/2019/07/07/000000

# 状況
```
$ warden svc up
ERROR: docker-compose could not be found; please install and try again.
```
wardenはインストールしたが、warden svc up出来ない。
ことの発端は、このようになっていたからであった。
docker-composeが無いようであった。

#私は誰（確認）
```
$ who
user   :0           2021-11-16 09:58 (:0)
```

#取ってくるのだが、、
```
$ sudo curl -L https://github.com/docker/compose/releases/download/2.1.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
[sudo] user のパスワード: 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     9    0     9    0     0     20      0 --:--:-- --:--:-- --:--:--    20
```

よし！（あとでここを、よく見ると良くない）

```
$ docker-compose version
bash: /usr/local/bin/docker-compose: 許可がありません
```
パーミッションね！

```
$ sudo chmod +x /usr/local/bin/docker-compose
```

パーミッション直した！


```
$  docker-compose --version
/usr/local/bin/docker-compose: 行 1: Not: コマンドが見つかりません
```

・・・・

```
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
$ docker-compose version
/usr/local/bin/docker-compose: 行 1: Not: コマンドが見つかりません
```
パスやシンボリックリンクも設定してみるが、うぬ？

#気付く

```
$ sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
[sudo] user のパスワード: 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   633  100   633    0     0   2041      0 --:--:-- --:--:-- --:--:--  2041
100 8648k  100 8648k    0     0  6601k      0  0:00:01  0:00:01 --:--:--  9.7M
$ sudo chmod +x /usr/local/bin/docker-compose
$  docker-compose --version
docker-compose version 1.16.1, build 6d1ac21
```
チュートリアルを確認してみるとスん！とでるではないか。


```
$ sudo curl -L https://github.com/docker/compose/releases/download/1.29.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   633  100   633    0     0   1062      0 --:--:-- --:--:-- --:--:--  1060
100 12.1M  100 12.1M    0     0  7492k      0  0:00:01  0:00:01 --:--:-- 16.3M
$  sudo chmod +x /usr/local/bin/docker-compose

```
該当のバージョンが、なかっただけらしかった。

```
$ docker-compose --version
docker-compose version 1.29.1, build c34c88b2
```
表示されましたので

```
$ warden svc up
```

やり直してできました。
政府のdata.go.jpでデータセットを検索する

　日本政府が公開しているデータセットを一括して検索できるデータカタログサイトが[data.go.jp](https://www.data.go.jp/)である。ここから何かしらのデータを得て分析してみたい。まずは，そのようなデータがあるかを見ていく。

　PDFは処理が面倒なので，XLSX形式のデータを検索することにした。次のような手順を作成した。

```プロデル
データ取得する手順
	パラメタ（「q」）は，「res_format:XLSX」。
	パラメタ（「rows」）は，50。
	URIは，「https://www.data.go.jp/data/api/action/package_search」
	HTTPでURIへパラメタを送信する。
	データは，それをJSON形式として読み取ったもの。
	タイトルは，｛｝。
	データ（「result」）（「results」）をデータムへそれぞれ繰り返す
		タイトルへデータム（「title」）を追加する。
	繰り返し終わり
	タイトルを返す。
終わり
```

　パラメータはPOSTで送れば良いことになっている（CKAN APIの仕様上一部のAPIはGETでも使える）。今回は，クエリqに対してフォーマットを指定する「res_format:XLSX」を設定している。また，デフォルトだと10個しか結果が返ってこないので，rowsに50を設定している。

　返答はJSONになっているので，`JSON形式として読み取る`手順で辞書に変換している。また，プロデルでは配列の宣言は不要だが，これをしないと`追加する`手順が正しく動作しないので`タイトルは，｛｝`で初期化している。

　以下のコードで実行する。

```プロデル
データ取得。
それをタイトルにそれぞれ繰り返す
	タイトルを報告。
繰り返し終わり
```

　結果は次の通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150160/5224a1f7-ab0c-ef88-0ab2-4ead11e94605.png)

　きちんと取れることが分かったので，次はその他のAPI操作も含めて種類にまとめたい。
widthとheightが反応しない原因

横と高さを指定してるのに有効にならない時があります。
<br>
原因は
１つめ　　　aのタグをつかっているとき
２つめ　　　spanのタグをつかっているとき
<br>
これらのタグはインライン形式になってます。
インライン形式にはwidthとheightが反応しません。
<br>
なので
インラインブロック形式に変えてあげれば高さと横を指定することができます。
<br>
この記述でインライン属性からインラインブロック属性になります。
display: inline-block;
<br>
これで高さと横を指定することができるようになります。
sympyでcubeのoffsetをしてみました。

いい方法ないでしょうか?平面のオフセット。3平面の交点計算してみました。


#Pycharmで

```python
from sympy import *
def myUnitVector(myPoint3D):
    myL=myPoint3D.distance((0, 0))
    return Point3D(myPoint3D.x/myL,myPoint3D.y/myL,myPoint3D.z/myL)
def myHtoP(myHairetu):
    return Point3D(myHairetu[0],myHairetu[1],myHairetu[2])
def my3PLaneIntersection(PTO,PTA,PTB,PTC,RA,RB,RC):
    vA =myUnitVector(myHtoP(Plane(PTO, PTB, PTC).normal_vector))
    PLA=Plane(PTO - RA * vA, normal_vector=vA)
    vB =myUnitVector(myHtoP(Plane(PTO, PTC, PTA).normal_vector))
    PLB=Plane(PTO - RB * vB, normal_vector=vB)
    vC =myUnitVector(myHtoP(Plane(PTO, PTA, PTB).normal_vector))
    PLC=Plane(PTO - RC * vC, normal_vector=vC)
    return PLC.intersection(PLB.intersection(PLA)[0])
def myCubeOffset(PT1,PT2,PT3,PT4,PT5,PT6,PT7,PT8,
                 w1234,w5678,w1265,w2376,w3487,w4158):
    PT1s = my3PLaneIntersection(PT1, PT5, PT2, PT4, w1234, w4158, w1265)[0]
    PT2s = my3PLaneIntersection(PT2, PT6, PT3, PT1, w2376, w1265, w2376)[0]
    PT3s = my3PLaneIntersection(PT3, PT7, PT4, PT2, w1234, w2376, w3487)[0]
    PT4s = my3PLaneIntersection(PT4, PT8, PT1, PT3, w1234, w3487, w4158)[0]
    PT5s = my3PLaneIntersection(PT5, PT8, PT6, PT1, w1265, w4158, w5678)[0]
    PT6s = my3PLaneIntersection(PT6, PT5, PT7, PT2, w2376, w1265, w5678)[0]
    PT7s = my3PLaneIntersection(PT7, PT6, PT8, PT3, w3487, w2376, w5678)[0]
    PT8s = my3PLaneIntersection(PT8, PT7, PT5, PT4, w4158, w2376, w5678)[0]
    return PT1s,PT2s,PT3s,PT4s,PT5s,PT6s,PT7s,PT8s
# input
PT1,PT2,PT3,PT4=Point3D(0,0,0),Point3D(1,0,0),Point3D(1,1,0),Point3D(0,1,0)
PT5,PT6,PT7,PT8=Point3D(0,0,1),Point3D(1,0,1),Point3D(1,1,1),Point3D(0,1,1)
w1234,w5678,w1265,w2376,w3487,w4158=0.3,0.3,0.3,0.3,0.3,0.3
# cal
PT1s,PT2s,PT3s,PT4s,PT5s,PT6s,PT7s,PT8s\
=myCubeOffset(PT1,PT2,PT3,PT4,PT5,PT6,PT7,PT8,
              w1234,w5678,w1265,w2376,w3487,w4158)
# check
print("#",PT1s.distance(PT2s), PT2s.distance(PT3s), PT3s.distance(PT4s), PT4s.distance(PT1s))
print("#",PT5s.distance(PT6s), PT6s.distance(PT7s), PT7s.distance(PT8s), PT8s.distance(PT5s))
print("#",PT1s.distance(PT5s), PT2s.distance(PT6s), PT3s.distance(PT7s), PT4s.distance(PT8s))
# output
print("#",(1.6)**3)
# 8/5 8/5 8/5 8/5
# 8/5 8/5 8/5 8/5
# 8/5 8/5 8/5 8/5
# 4.096000000000001
```

#参考

https://qiita.com/7note/items/4beb0dd3ba4bdde82609
EC2 に RDS for Redis と通信を行う Docker コンテナを起動する

## 経緯

- プライベートなサブネットに配置した RDS for Redis (TLS暗号化) と パブリックなサブネットに配置した EC2 内の Docker コンテナの間に通信が必要になった

## 対応

- AWS 公式ドキュメントの "redis-cli を使用して送信中の暗号化を有効にした Redis クラスターに接続するには" 以降の手順を参考にし、dockerfile を作成した
- 具体的には、stunnelを利用する方法を採用した

## 内容

- それぞれのファイルを作成し、Docker イメージをビルド
- API の Docker イメージにするときは、dockerfile にソースコード取り込みなどの処理を追加すればいい

### dockerfile 

```
FROM alpine:latest

RUN apk add --no-cache stunnel
COPY ./redis-stunnel.conf /etc/stunnel/redis-stunnel.conf
COPY ./docker-entrypoint.sh /usr/local/bin

ENTRYPOINT [ "docker-entrypoint.sh" ]
```

### docker-entrypoint.sh

```
#!/bin/sh
stunnel /etc/stunnel/redis-stunnel.conf
```

### redis-stunnel.conf

```
fips = no
setuid = root
setgid = root
pid = /var/run/stunnel.pid
debug = 7 
delay = yes
options = NO_SSLv2
options = NO_SSLv3
[redis-cli]
   client = yes
   accept = 127.0.0.1:6379
   connect = master.my-redis-cluster.xxxx.yyyy.cache.amazonaws.com
```
自動車メーカー勤務からエンジニアになってみて

## 前職の内容
昔から車が好きだったので、大学院卒業後、自動車メーカーに入社しました。入社してからは車の乗り心地性能に関する開発を行っていました。企画時に性能目標を提案し、それをモノ（製品）に落とし込むのが主な仕事です。乗り心地性能は車の数ある性能の中でも特に重要な性能なので多く部署と連携が必要だったり、開発フェーズ毎に業務内容が大きく変わったりと非常に大変な仕事でしたが、車づくりの面白さや大変さを身を持って体感することができたのでとても良い経験になりました。

## エンジニアになろうと思ったきっかけ
新卒から約5年間働き、運良く自分の行きたい部署、やりたいことをさせてもらったので、自動車開発をある程度やり切ったと感じていました。そこで、何か新しいことを始めて、次のキャリアステップを歩みはじようと思った時にプログラミングと出会いました。学生時代にもプログラミングの授業があったのですが、当時はあまり理解できず面白さも分からなかったので、何年か振りの機会に逆にチャレンジしてみたいという気持ちもありました。そんな中、ポテパンキャンプのHPを見て、多くの人が未経験からでもプログラミングを習得して新たなキャリアをスタートしていることを知り、自分もやってみようと思いました。

## エンジニアとして働いてみた感想
まず現場のスピード感や技術レベルの高さに驚きました。コードを読み解くだけで大変で、ついていくのに必死でしたが、ポテパンキャンプで自走力がついていたおかげで、必要以上に質問することなく、効率よく開発に携わることができたと思っています。よく「未経験からプログラミングを習得するならいち早く現場に入ることが大切」と言われますが、入ってからまさにその通りだなと思いました。
またITサービス開発は自動車開発と比較して開発期間が短いので、要件定義から実装、保守運用まで一度に経験でき、プロダクト開発全体に携わることができる点が面白いです。自分が開発した機能・サービスが世に出るところまで見届けられるのはやりがいがあります。IT業界は変化が早いですが、その分、新しい技術に触れることができるので、好奇心旺盛な人には特におすすめできる職種だと思います。

## 今後はどんなエンジニアを目指したいか
エンジニアとして転職してからは、バックエンドを中心にフロントエンド・インフラ周りも担当するようになりました。今後もより幅広い技術を身に着け、フルスタックエンジニアとして活躍できればと思っています。
ElastiCache(Redis)の認証トークンを変更する手順

掲題のことをやろうとしてハマったのでメモ書き。

##TL;DR
認証トークン（パスワード）を変更する場合は、まず`トークンをローテーション`でパスーワードを追加する。
その後、`トークンを設定`で新しいパスワードを指定し、古いパスワードを無効化する。

##やりたいこと
ElastiCacheの認証トークン（パスワード）にダミー値を設定していたので、本物のパスワードと差し替えたい。

##ハマったこと
`トークンを設定`で新しいパスワードを設定しようとしても、以下のエラーが出てきて

```
The AUTH token provided does not match the AUTH token provided for rotation. 
To SET, please use an AUTH token that is the same as the AUTH token provided for rotation.
```

パスワードが合致しない的なことが書いてあるけど、そりゃ新しいパスワードなんだから当然である。


##解決編
ドキュメントを彷徨っていると、こんな記述が。

```
2 つの AUTH トークンをサポートする Redis サーバーを、1 つの AUTH トークンをサポートするように更新するには、
ModifyReplicationGroup API オペレーションを呼び出します。
```
https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/auth.html

つまりこの`トークンを設定`という機能は、`2つあるパスワードのうち1つを指定し、他方は削除する`という機能だった。
そのためには、まず新しいパスワードを`トークンをローテーション`で追加する必要があった、というわけ。

##あとがき
いやわかるかーい。
Ubuntu20.04にて、 /var/run/docker.sock: connect: permission deniedになったので直した。

#はじめに
$ docker version　したら、
/var/run/docker.sock: connect: permission denied
になってしまったので、$ docker versionを動かすまでの、道のり。

# 最終更新日
2021年11月16日

# 環境の情報
OS
Ubuntu20.04


# 注意
最新の状態を確認して下さい。

# 公式はこちら
https://docs.docker.com/

#参考さま
https://akamist.com/blog/archives/3536


#状況

```
$ docker version
Client: Docker Engine - Community
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 25 07:42:59 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/version": dial unix /var/run/docker.sock: connect: permission denied
```

dockerインストールしてきましたが、このように、permission deniedになってしまいます。


#確認
###グループ確認　コマンド

```
$ cat /etc/group | grep docker
docker:x:998:
```

グループが出来ているか確認してみます。
出来ては、いるようです。

###私は誰（記憶喪失）

```
$ who
user   :0           2021-11-15 09:54 (:0)
```

ユーザーが誰になっているのか確認してみます。



#グループ追加

```
$ sudo gpasswd -a user docker
ユーザ user をグループ docker に追加
```

このようにすれば、グループに、ユーザーを追加出来るようです。

https://tech.librastudio.co.jp/entry/index.php/2018/07/14/post-1924/

```
$ cat /etc/group | grep docker
docker:x:998:user
```

再び確認。

#パーミッション確認

```
$ cd /var/run/
/var/run$ pwd
/var/run
```

戻らなかったので、/var/run/の箇所を、
見に行きます。

```
$ ls -la
srw-rw----  1 root              docker    0 11月 15 15:46 docker.sock
```

ユーザーが違うみたいです。

```
$ sudo chown user:user  docker.sock
[sudo] user のパスワード: 
/var/run$ ls -la
srw-rw----  1 user            user   0 11月 15 15:46 docker.sock
```

userで使いたいので、まるっと変更してみます。


#終わり

```
$ docker version
Client: Docker Engine - Community
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 25 07:42:59 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.10
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       e2f740d
  Built:            Mon Oct 25 07:41:08 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.11
  GitCommit:        5b46e404f6b9f661a205e28d59c982d3634148f8
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

無事に、表示されるようになりました。
ApexLegendsの戦歴をPythonで取得してみよう

# はじめに
この記事ではPythonのライブラリである[ApexTrackerPy](https://github.com/nerrog/ApexTrackerPy)を使用したPythonでのApexlegendsの戦歴の取得方法などを解説します。

# 目次

* APIの登録
    * APIの種類について
    * 登録
* 実際に戦歴を取得してみる
    * APIの呼び出し方
    * 値を取り出してみる
* おまけ:現在のマップを取得してみる

# APIの登録
## APIの種類について
ApexTrackerPyでは[UNOFFICIAL APEX LEGENDS API](https://apexlegendsapi.com/)と[TRACKER NETWORK API](https://tracker.gg/developers/docs/titles/apex)の2種類に対応しています。
UNOFFICIAL APEX LEGENDS APIは戦歴以外にもサーバーステータスやマップローテーションなど多くの情報が取得できます。
戦歴(プレイヤーステータス)の取得はどちらでもいいのですが、この記事ではUNOFFICIAL APEX LEGENDS APIを使ってみます。

## 登録
[このページ](https://apexlegendsapi.com/documentation.php)にアクセスすると上の方にこのようなフォームがあると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701723/eccf6c88-c991-346e-28b4-de1617312bfb.png)
上から**Project URL (not required)** 使用するサイト等へのURL(必須ではない)、**(Very) short usage description**(簡単な使いみちの説明)とあるので入力し送信ボタンをクリックします。

最後にAPIキーが発行されるのでそれを安全な場所に保管して登録は完了です。

# 実際に戦歴を取得してみる
## ライブラリのインストール
`pip3 install ApexTrackerPy`
pipで一発で入ります

## APIの呼び出し方
```py
import ApexTrackerPy
res = ApexTrackerPy.GetApexPlayerStatus(APIキー, 機種, ユーザー名)
```
返り値にはapexclassという独自のクラスとして値が返却されます。
機種は

* PC
* PSN
* XBOX
* SWITCH

に対応しています。

ユーザー名は各機種のID(OriginならID、PS4ならPSNID)
Steam版は紐付けたOriginユーザー名でOKです。
スイッチ版はAPIの制約でUID指定のみの対応です。
ApexLegendsStatusのClub等からUIDを見つけてきてユーザー名にUID、4つ目の引数をTrueにしてください。

## 値を取り出してみる
```py
print("ユーザー名: "+res.name)
print("プレイヤーレベル: "+res.level)
print("バトロワランクの現在のランク: "+res.CurrentRank)
print("合計キル数: "+res.total_kill)
print("選択中のレジェンド: "+res.legends_json["selected"]["Legendname"])
print("レイスの一番上のトラッカーの値(自分はキル数): "+res.legends_json['all']['Wraith']['data'][0]['value'])
```
詳しい戻り値については[Github Wiki](https://github.com/nerrog/ApexTrackerPy/wiki/GetApexPlayerStatus#%E6%88%BB%E3%82%8A%E5%80%A4)を参照してください。

`legends_json`からレジェンドの詳細情報を取り出すことができます。
全部の関数で共通なのが`row_json`でAPIから取得したJSONを直で出力することができます。あと`elapsed_time`でAPIの呼び出しにかかった時間を取得できます。

# おまけ:現在のマップを取得してみる
現在のバトロワ(カジュアルの)マップを取得してみる例

```py
import ApexTrackerPy
res = GetApexMapRotation(api_key)
print("現在のマップ: " + res.BattleRoyal_Current_Map)
```
標準ではマップ名の出力は英語ですが、取得する前に
`ApexTracerPy.LANG = "ja-JP"`
これを入れてあげると日本語化できます(v1.8からの新機能)

```
# 標準(en-US)
現在のマップ: Storm Point
# 日本語化後(ja-JP)
現在のマップ: ストームポイント
```

# 終わり
他にも取得できる情報が沢山あるので[Wiki](https://github.com/nerrog/ApexTrackerPy/wiki)も覗いて見てください！
legends_jsonのところは各レジェンドごとに変数を用意してあげるとかRespawnAPIから直接取得していなぁなんて思ったりしています。
[TAR|SSH]複数ファイルをディレクトリごとローカル・リモート間で一括転送

# ローカルからリモートへ

ローカルフォルダ内のファイルをリモートのサーバに一括転送。

```sh
tar -cf - ./* | ssh user@hostname tar -xf - -C public_html/dir
```

tarを使うのは転送効率がよいから。普通にファイルを転送する場合、ファイル数が1万個あれば1万回のハンドシェイクが発生します。tarでひとつの書庫にまとめると、ハンドシェイクは1回で済みます。

`-cf -` は、書庫を「**c**reateする」「**f**ile名を`-`とする」という意味。

`-` (半角ハイフンひとつ) が意味するものは「標準出力」で、普通はハイフンではなくファイル名を指定します。

`./*` は「カレントフォルダの中身全部」です。サブフォルダも全部まとめます。

書庫データは標準入力を通じてsshに渡します。半角ハイフンひとつの `-` で受け取ります。

`ssh user@hostname` の後ろの文字列は、SSH接続後にそのままコマンド文字列として実行されます。

## 転送に失敗する場合

```
tar: Damaged tar archive
tar: Retrying...
tar: Damaged tar archive
tar: Retrying...
tar: Damaged tar archive
tar: Retrying...
tar: Error exit delayed from previous errors.
```

「アーカイブが壊れている」みたいなメッセージが多数表示されることがあります。もしPowerShellを使っている場合は、Bashなど他のシェルを試してみてください。

## リモートからローカル(手元のPC)へ

```sh
ssh user@hostname "cd public_html/dir; tar -zcf - *" | tar -zxf -
```

リモートからローカルに転送する場合は上記のように実行します。
slickの導入方法・jqueryの導入方法（自分用）

#slickの導入方法

https://kenwheeler.github.io/slick/

１上のリンクに飛ぶ

２headerのget it nowを押しdownload nowをクリック

３ダウンロードしたものの中からslickのファイルをコピーし自分のファイルのindex.htmlと同じ階にペースト

４headタグのcssの直前に
`<link rel="stylesheet" href="slick/slick-theme.css" /><link rel="stylesheet" href="slick/slick.css" />`
をこのように！！！！順番！！！！に気をつけて追加

５bodyタグの前のjsの前に
`<script src="slick/slick.min.js"></script>
    <script src="slick/slick.js"></script>`
の順番で追加

#jqueryの導入方法
https://code.jquery.com/

１上のリンクに飛ぶ

２最新バージョンのminifiedをクリックしてコピー

３jsの前にペースト
Katalon RecorderでRecordした数字が入力されないときの対処法



リグレッションテストの自動化を実現するためにKatalon Recorderを試していました。
その際数字入力の項目で、Recordでは問題なく記録できるが、作成したテストケースをPlayすると入力されずに空欄になる、また、Katalon Recorder上ではエラーになっていないという問題が起こったため、その解決策を記録しておきます。

#環境
Chrome拡張機能の[Katalon Recorder (Selenium tests generator)](https://chrome.google.com/webstore/detail/katalon-recorder-selenium/ljdobmomdgdljniojadhoplhkpialdid?hl=ja-jp)を使用しました。

#どういった問題が起こったか
下記のような数字を入力するボックスに適当な数字を入力しKatalon RecorderでRecordしました。
Katalon Recorder上では値も正しく記録できていました。
![screenshot-centurion-stg.signite.jp-2021.11.15-17_42_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563069/a17fa501-65b7-d535-f749-4f2b20df0680.png)

しかし、その後PlayするとRecord時に記録された数字は入力されず空欄になりました。
![screenshot-centurion-stg.signite.jp-2021.11.15-17_41_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563069/ea0cdd45-0725-d0a7-760e-dc842622d13b.png)

Katalon Recorderを確認するとエラーは出ておらず入力したことになっていました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563069/a66e7075-f9bc-eef1-2785-ff3026c9f96c.png)

#解決策
Commandを`setText`に変更をしてPlayすると、記録された数字が入力されました。
Katalon Recorderでは文字列や数字を入力した際、Commandにデフォルトで`type`が使用されますが、`<input type = "number">` `<input type = "tel">` `<input type = "time">` の入力フォームのときは、`setText`のCommandを使用することで問題なく入力されるようになりました。

![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563069/b95e95eb-5646-c947-fb5f-d9aa020bdf9f.png)
CloudWatch Logs Insightsのコマンド例

# 概要

AWS IoTで出るログを例に、Logs Insightsの基本的で便利なコマンドを紹介します。

より応用的なことは、[CloudWatch Logs Insights のクエリ構文 - Amazon CloudWatch Logs](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html)のページを見ながら作ると良いです。

# 今回仮定するデータ

検索対象のCloudWatchLogsには以下のJson形式のデータが入るとします。
Logs Insightsは`json`であれば勝手にパースしてくれ、`logLevel`や`accountId`などと入力すれば、普通に使えるようになります。
オリジナルのデータなどは`parse`コマンドでパースします。本記事では触れません。
(参考: [CloudWatch Logs Insights のクエリ構文 - Amazon CloudWatch Logs](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html))

```json
{
    "timestamp": "2021-11-16 04:03:46.596",
    "logLevel": "INFO",
    "accountId": "accountId",
    "status": "Success",
    "eventType": "RuleExecution",
    "clientId": "testclient",
    "topicName": "topic",
}
```

# 特定のフィールドのみを表示する

```sql
display @timestamp, eventType, topicName, clientId
```



# 特定のフィールドの数を表示する


```sql
stats count(*) by topicName
```

ちなみに2つのフィールドでのコンボも可能

```sql
stats count(*) by eventType, topicName
```

# フィールドに特定の文字列が入っているものを検索対象から外す。

eventTypeに`Rule`が入っているものを排除

`""`を使うと、部分文字列一致を確認します。
`\\`を使うと正規表現が使えます([CloudWatch Logs Insights のクエリ構文 - Amazon CloudWatch Logs](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html#CWL_QuerySyntax-regex))

```sql
filter eventType not like "Rule"
```


すでに出たcountとコンボで使います。

```sql
filter eventType not like "Rule"
| stats count(*) by eventType, topicName, clientId
```

さらにcountでソートしたい場合

```sql
filter eventType not like "Rule"
| stats count(*) as count by eventType, topicName, clientId 
| sort count desc 
```

# 検索結果を可視化する

「可視化」というタブをクリックするとグラフで結果を見ることができます。
この時、`sort`してあげるとグラフも綺麗になります。

```sql
filter @message not like "Rule"
| stats count(*) as count by eventType, topicName, clientId 
| sort count desc　   #ここでソートしてあげる
| limit 90
```


## ソートなしの円グラフ

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/7d38209b-8835-6f28-a125-9f14544d67ff.png" />

## ソートありの円グラフ

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/19f15cc0-2a5b-7e14-68a4-9906ae72952a.png" />


## ソートなしの棒グラフ
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/f8bd27f6-41b1-60bb-aa52-9d74855de71d.png" />


## ソートありの棒グラフ
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199256/95b46c53-5d8a-7a50-21e9-37275a1b7789.png" />

# まとめ
insightsは便利なのでジャンジャン使いましょう！