OmniAICreator/Qiita-1.07M huggingface dataset:
【jQquery】change()

input/select/textarea等の`要素の中身が変更された時`に実行されるメソッド。

##実際の挙動
```
<input type="radio" name="test">
<input type="radio" name="test">
<input type="radio" name="test">
```
上記のようなラジオボタンがあった時に`change()`を使用することで、いずれかのラジオボタンがクリックされた瞬間に何らかのイベント処理を自動的に実行することが出来るわけです。

他にも、セレクトボックスから任意の項目を選択した時や、入力ボックスに文字が入力されてフォーカスが外れた瞬間に実行することも可能です。

```html
<body>
<select>
    <option>おはよう</option>
    <option>こんにちは</option>
    <option>こんばんは</option>
</select>
 
<script>
    $('select').change(function() {
        var text = $('option:selected').text();
    
        console.log( text );
    });
</script>
</body>
```
上記のコードはラジオボタンがクリックされた時に任意のイベントが発生するようになっています。

```js
    $('select').change(function() {
        var text = $('option:selected').text();

        console.log( text );
    });
```
こちらのコードではラジオボタンが選択された時に任意のテキストを表示されるようになっています。

###changeイベントの発生方法

```html
<body>
<input type="text">
<button>ボタン</button>
 
<script>
    $('input').change(function() {
        console.log('変更されました！');
    });
 
    $('button').click(function() {
        $('input').change();
    })
</script>
</body>
```
`change()`の引数を無しにすると`change()イベント`を意図的に発生させることができます。
上記のサンプルコードだとボタンをクリックした後に`change()イベント`が発生されるようになっておりコンソールログには`変更されました！`の文字が表示されるようになっています。

###changeイベントが発生しない場合

```html
<body>
<input type="text">
<button>ボタン</button>
 
<script>
$('input').change(function() {
    console.log('変更されました！');
});
 
$('button').click(function() {
    $('input').val('こんにちは');
})
</script>
</body>
```
上記のようにクリック時にテキストボックスに`val()`で文字列を代入させても、コンソールログには`変更されました！`とは表示されません。

実はテキストボックスは`val()`で文字列を代入しても`change()イベント`が動作しない仕様になっています。

そこで引数なしの`change()`を使用することで、この問題を解決することができます。

```js
$('button').click(function() {
 
    $('input').val('こんにちは').change();
 
})
```
これで無事に動くようになりました。
3D プリンタでつくるフェイスシールドについて調べてみた

モノづくり大好きで家に3Dプリンタを持っています。コロナの感染拡大に伴って、世界中でフェイスシールドがモノづくり好きな人たちによって作られ、医療現場を助けているニュースを目にするようになりましたので、フェイスシールドについて調べてみることにしました。

###1. 調べるきっかけはシアトルのコミュニティ活動

私の3Dプリンタ師匠がシアトル在住。シアトルはアメリカでは早くにコロナ感染が確認されて死者も確認されてからのコミュニティの結束はとてもはやかったです。師匠が、以下のコミュニティへ参加したことが共有されました。

https://opencollective.com/wa-state-3d-visor-mask-hub

この活動は、フェイスシールドを病院へ提供するために行われ、募金とボランティアを募っています。ボランティアスタッフは、実際に3Dプリンタを使って印刷したり、裁縫したりして自分のできることで活動をします。師匠に実際に聞いたところ、3Dプリンタで印刷すると、印刷した部品をボランティアが車で収集にくるそうです。その後、各部品がとある場所に集められ、組み立てられ、消毒され、必要な医療現場に届けられる、ということです。募金で集まったお金は、原材料費などに充てられ、開始２週間で1400個のシールドを提供したそう。やっぱり、こういうところすげえ、アメリカ。(同じことは難しいかもしれないけど、コミュニティの作り方とか、分業とか参考になるかも。)

###2. フェイスシールドの種類（海外編）

#### Prusa フェイスシールド
https://help.prusa3d.com/en/guide/assembling-the-prusa-face-shield-rc1-rc2-rc3-community-version_125830#125838

私が持っている3D プリンタは、Prusa というメーカーのものです。この会社を作ったPrusaさんは、超天才で3D プリンタを3Dプリンタで作って売る、という画期的なビジネスモデルで産業革命を起こしています。そして、コロナウイルスがニュースになった初期のころから、フェイスシールドのモデルファイルを無料で提供しました。世界で作られているフェイスシールドはここからの派生が多いです。

派生例：
アメリカ国立衛生研究所：Prusa版が改造されてるバージョン。上からも守るようになっています
https://3dprint.nih.gov/discover/3dpx-013359

#### Budmen フェイスシールド
https://budmen.com/
こちらも3Dプリンタメーカーのページから提供。シンプルなで上からの飛沫にも対応しています。このサイトでは、欲しい人と作りたい人のマッチングも行っています。（一応登録してみたけど連絡あるかな...）


#### #3DVFaceShield
https://3dverkstan.se/protective-visor/
スウェーデンの3Dプリンタソリューション会社が無償で提供を始めたモデル。シンプルなので印刷部分がすくなく短時間で印刷できるのが人気。最初に書いた師匠のシアトルのコミュニティもこちらのモデルを利用しています。

###3. フェイスシールドの種類（日本編）

日本もいろいろがんばってます！しらべたいくつかのモデルを書いておきます。

#### ENGINE フェイスシールド
http://www.project-engine.org/
大阪大学とメガネフレームメーカーのシャルマンが共同開発したもの。フェイスシールドを頭に止める部品が別途いらないところに、メガネフレームメーカーのアイデアが光っています。また、A4のクリアファイルを開いて使う、という形がユニーク。かっこよくはないけど、アイデアがとんがってます。

#### 神大 フェイスシールド 
https://www.kanagawa-u.ac.jp/news/details_20062.html
神奈川大学の准教授が3Dプリンタと輪ゴムなどの身近な道具で作れるように設計したモデルです。Githubにとても丁寧な日本語の解説があります。日本で手に入りやすいツールで、シンプルな設計です。

日本でもフェイスシールドのニュースを目にすることが増えましたが、企業が作って提供する、というものが多いです。モデルを無料公開するのでみんな使ってね！というものは少ないかな...という印象。

###4. 作成する上での注意点
実際に医療現場にフェイスシールドを提供している師匠から聞いた作成上の注意点。フェイスシールドは、アルコール消毒をする、ということを前提に素材をえらぶこと。例えば、フィラメントはPLAではくABSやPETGなどを使う、プラスチック板もアクリルやビニルを使うなど。素材についても作る前に調べます。アルコールに強い素材を！

###5. さいごに
フェイスシールドについての情報をまとめました。なんで調べたかというと、それはもちろん作るから。ひとまず、これらのモデルを実際に作成したいと思います。この情報が、役立つような危機的な状態にならないといい、と願いつつ、できることはやっておきたい、と思っています。
enebularでLチカ

#概要

enebularでLチカしてみた。仮想です

#写真
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3999dd05-af5d-9e81-79bb-e79c7d1ee4c1.png)


#flow

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c87bb8fd-ae6e-0926-7fbf-8c8b568b300a.png)

#サンプルコード


```
var ws = new WebSocket("wss://ev2-prod-node-red-d2dbd1f0-936.herokuapp.com/pub");
ws.onopen = function(e) {
};
ws.onerror = function(e) {
	alert("err");
};
ws.onmessage = function(e) {
	if (e.data == "0") 
  {
    off();
  }
  if (e.data == "1") 
  {
    on();
  }
};
function on() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.04)';
  ctx.fillRect(0, 0, 100, 100);
  ctx.fillStyle = '#f00';
  ctx.arc(30, 30, 30, 0, 2 * Math.PI);
  ctx.fill();
}
function off() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.04)';
  ctx.fillRect(0, 0, 100, 100);
  ctx.fillStyle = '#800';
  ctx.arc(30, 30, 30, 0, 2 * Math.PI);
  ctx.fill();
}
var canvas;
var ctx;
canvas = document.createElement('canvas');
canvas.width = 100;
canvas.height = 100;
ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
on();
off();




```

#成果物

https://embed.plnkr.co/plunk/DiYnyQJccBogyi8u

以上。
SNI（Server Name Indication）の必要性

#概要
SNI（Server Name Indication）の必要性について調べました。

#■SNIとはなにか
SNI（Server Name Indication）は、「※バーチャルホスト」を「※TLS」に対応させるための機能。

##※バーチャルホストとは
HTTP1.1から導入された機能。
この機能を使用すると、同じIPアドレスを複数のドメインで共有できる。

　→ユーザーが「〇〇.com」と「××.com」のURLにアクセスした際、webページはそれぞれ別物だが、裏でつながっているサーバーは同じというイメージ。

###◎バーチャルホストのメリット
・サーバ台数を節約でき、運用コスト下げられる
・IPアドレスを節約できる

##※TLS（SSL）とは
webブラウザでwebサーバーにアクセスするときに、データを暗号化して安全性を高めるための技術。

#■SNIの必要性
#####SNIを使用していないと、バーチャルホスト環境で異なるwebページにアクセスしているのにも関わらず同じサーバ証明書を使用するしかなくなる。
　→レンタルサーバサービス等で複数のユーザーが同じサーバを使用しているときに、サイトごとの証明ができない

#■機能イメージ
######↓　HTTPSの通信の流れを、使用時と非使用時それぞれで確認する。
###【SNIを利用していない場合】
#####＞▲クライアント
①webサーバのIPアドレスにアクセス
#####＜□サーバ
②共通のサーバ証明書を返送　
　→この時点ではどのドメインに接続するかわからないから、サーバ共通の証明書しか使えない
#####＞▲クライアント
③暗号化通信でドメインAを指定
#####＜□サーバ
④ドメインAのwebページを返信

###【SNIを利用する場合】
#####＞▲クライアント
<font color="DarkOrange">①SNIでドメインを指定してアクセス</font>
#####＜□サーバ
<font color="DarkOrange">②ドメインAのサーバ証明書を返送</font>
　→この時点で接続先のドメインが指定されているため、ドメインごとの証明書を使える。
#####＞▲クライアント
③暗号化通信でドメインAを指定
#####＜□サーバ
④ドメインAのwebページを返信

#まとめ
・SNIを使用することで、ユーザーアクセス時にサーバ側で接続先ドメインがわかるため、サーバ内のドメインに応じたそれぞれ別の証明書を発行できる。

・レンタルサーバーサービス等で、複数人で同じサーバを使用するときに便利。

#参考サイト
以下のページを参考にさせていただきました！
https://jp.globalsign.com/blog/articles/server_name_indication.html
ATOM Matrixを触ってみた

M5Stackシリーズの小型デバイスが日本でも技適付きで販売されるようになりましたので、趣味の一端で触ってみました。

私は[スイッチサイエンス](https://www.switch-science.com/)で購入しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/306e8dc0-b4f2-efe6-62b5-fd5917ff4044.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/3e10556c-1318-47fc-5987-729b4abce825.png)

ほかの記事
[ATOM Matrixに心拍センサを繋ぐ](https://qiita.com/jksoft/items/1307056b2d001388974a)
[ATOM MatrixをAmbientに繋ぐ](https://qiita.com/jksoft/items/915f917fd76c2b045fe0)
[ATOM MatrixのセンサとIO](https://qiita.com/jksoft/items/40082d680558cefb71cd)

# スペック
スペックは以下のようになってます。

* CPU：240 MHz Dual Core Tensilica LX6
* RAM: 512KB
* FLASH: 4MB
* 通信: Wi-Fi、Bluetooth
* センサ：6軸センサ、ホールセンサ
* GPIO：6ピン ＋ Grove互換コネクタ
* サイズ：24 x 24 x 14 mm（チロルチョコぐらい）

小型な割にもりもりなスペックだと思います。
遊ぶには良いですね。（小型の[うおーるぼっとLED](http://www.runele.com/ca4/46/)でも作ってみようかな）

# 開発環境
とりあえず、簡単にいじるなら以下の環境に対応してます。

* [Arduino](https://docs.m5stack.com/#/en/arduino/arduino_development)
* [UIFlow](https://docs.m5stack.com/#/en/quick_start/atom/atom_quick_start)

※リンク先はATOM Matrixのチュートリアルになっているので、参考にしてください。

# ファーストタッチ
とりあえず、慣れているArduino環境を[チュートリアル](https://docs.m5stack.com/#/en/arduino/arduino_development)どおりに構築して、動かしてみました。（ちょっとハマりポイントもあったので、そこも説明します。）

[ATOM用のArduinoライブラリ](https://github.com/m5stack/M5Atom)がサンプル付きで用意されているので、まずはそれをライブラリとしてArduino IDEに追加します。

GithubからZIPファイルをダウンロードして、追加もできますが、ライブラリ管理画面から`M5Atom`と検索したほうが早いので、その様にしました。

`スケッチ`→`ライブラリをインクルード`→`ライブラリを管理`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/8f7f92dc-e77a-6054-bfab-1b708b8a98be.png)

ライブラリマネージャで`M5Atom`と検索して、インストールをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/0ae89cda-3d3b-409d-e81f-2d8bce78768f.png)

実は、`M5Atom`だけではダメで、サンプルをコンパイルするとエラーになります。
FastLED.hが無いというエラーが出るので、同じくライブラリマネージャから`FastLED`を検索して、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/295687ff-f20a-a75a-2e0a-84084a5dba54.png)

サンプルが同梱されているので、`ファイル`→`スケッチ例`→`M5Atom`→`Basics`→`Buttom`を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/5835908d-2c76-abc9-8268-711aad5d6d05.png)

私の場合、そのままコンパイルし、書き込む段階で、エラーが起きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/f172f2e3-fd22-91b5-7134-6dd17f13d764.png)

どうやらボーレートが早すぎて、通信エラーが出てるっぽいので、ボーレートをデフォルトだった`921600`から`115200`に変更しました。（もうちょっと早くても大丈夫かもしれません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/1b7fddfa-9a3f-b6b2-e5cb-9a1d94e5cfa1.png)

無事、サンプルの書き込みができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/0a7fdd96-163d-785c-7739-900703537a14.png)

書き込んだ後は、横のリセットボタンを押して、動作確認。
LEDパネルを押すごとに色が変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/f4d6538e-177c-10b3-4a7e-942b8313ce57.png)

# あとがき
Wi-FiもBluetoothもセンサー内蔵しているので、単体でも遊べそうです。
GPIOやGrove互換コネクタも出てるので、電子工作的にも面白そうですね。
というか何より安いっていうのがポイントかも。

（UIFlowも試そうとしたのですが、チュートリアル通り動かなかったので、ちょっと断念しました。）
[Unity初級]マウスポインタの位置を取得

#概要
マウスをクリックした時に、マウスポインタの座標をコンソールに表示します。

#本文
```cs

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) {
            Vector3 mousePos = Input.mousePosition;
            Debug.Log("x:"+mousePos.x+"    y:"+mousePos.y);
        } 
    }
```
Vector3型は
～.xでX座標
～.yでY座標
～.zでZ座標が取り出せます
  
![スクリーンショット (73).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/86d67911-66b2-d91f-0384-b27815347159.png)
FloatingActionButtonが黒い場合の対処


2020/5/12現在のお話
今後ハマるかもしれないので備忘録として

### 環境

```gradle
implementation 'com.google.android.material:material:1.2.0-alpha03'
```

### 実装

```xml
<com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="16dp"
            android:backgroundTint="@color/hogehoge"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:srcCompat="@drawable/ic_add_white_16dp" />
```

`ic_add_white`はAndroid StudioのVectorAssetsから作ったいたって標準のもの

```xml
<vector android:height="16dp" android:tint="#FFFFFF"
    android:viewportHeight="24.0" android:viewportWidth="24.0"
    android:width="16dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FF000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>
```

こんな感じでなにごともなく実装していたが、なぜかic_add_white部分が黒く表示される
アイコン自体は白なのに・・・

なぜかと思ったらまさに[こちら](https://github.com/material-components/material-components-android/issues/1106)の話だった

```xml
app:tint="@androd:color/white"
```

を追加することで白くなりました
Flaskのアクセスログをカスタマイズする

## やりたいこと

以下のようなFlask(version 1.1.2)のプログラムを作成し

```python
from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello():
    return "Hello World!"


if __name__ == "__main__":
    app.run(host='0.0.0.0')
```

実行してアクセスすると以下のようなログが出ますが、

```
127.0.0.1 - - [14/Apr/2020 19:13:43] "\x1b[37mGET / HTTP/1.1\x1b[0m" 200 -
```

このアクセスログは（私にとって）不要な文字列が入っている上、本文のメッセージに色がついていて、扱いにくいです。

なので、このログをカスタマイズする方法を説明します。

## カスタマイズ方法

結論からいうと、Flaskが内部で利用しているWerkzeug (version 1.0.1) という名前のloggerが上記のログを出力しているため、以下のようにWerkzeugのloggerを取得してカスタマイズします。

### 例１）ログのレベルをERRORに変更する

```python
from flask import Flask
import logging

# ロガーの取得
werkzeug_logger = logging.getLogger("werkzeug")
# レベルの変更
werkzeug_logger.setLevel(logging.ERROR)

app = Flask(__name__)


@app.route("/")
def hello():
    return "Hello World!"


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=4001)
```

#### 例２）出力する文字列の変更

デフォルトでは `(IPアドレス) - - [(日時)] (メッセージ(色付き))` というフォーマットで出力されますが、以下の例では、`(メッセージ)` の部分を色無しで出力しています。

```python
from flask import Flask
import logging
from werkzeug.serving import WSGIRequestHandler
from werkzeug.urls import uri_to_iri

werkzeug_logger = logging.getLogger("werkzeug")


def custom_log_request(self, code="-", size="-"):
    try:
        path = uri_to_iri(self.path)
        msg = "%s %s %s" % (self.command, path, self.request_version)
    except AttributeError:
        msg = self.requestline
    code = str(code)
    werkzeug_logger.info('"%s" %s %s' % (msg, code, size))


# 関数の置き換え
WSGIRequestHandler.log_request = custom_log_request

app = Flask(__name__)


@app.route("/")
def hello():
    return "Hello World!"


if __name__ == "__main__":
    app.run(host='0.0.0.0')

```

出力されるログは以下のように色がなくシンプル

```
"GET / HTTP/1.1" 200 -
```

### なぜこの方法でいいのか？

Flaskは内部でwerkzeugというパッケージを利用しています。

そのため、Flaskでは２つのloggerが登場します。
一つは `logging.getLogger("app.flask")` で取得できるFlaskが使うlogger,
もう一つは `logging.getLogger("werkzeug")` で取得できるwerkzeugが使うloggerです。

上記のログはwerkzeugのソースコードの↓の場所で出力しています。

https://github.com/pallets/werkzeug/blob/1.0.x/src/werkzeug/serving.py#L406

なのでこの関数を置き換えてあげることで、カスタマイズ可能になります。

`app.flask` のloggerをいくらいじってもこのログは消えないのでだいぶハマりました（笑）
AWS Amplifyについての調査報告

# 本記事概要
本文はAWS Amplifyについて簡単に概要をまとめた記事です。
今後、勉強される方、ざっくりとAWS Amplifyについて知りたい方にご活用頂けたら幸いです。

# AWS Amplifyとは？
Web およびモバイルアプリ開発のためのフレームワーク

- CI/CD やホスティングのためのコンソールを含んでいて便利なのが利点

## 構成要素
構成要素は全部で3つ

- Amplify CLI
    - コマンドラインで対話形式でAWSのバックエンドを構築できるインタフェース
- Amplify Framework
    - 数行でバックエンドとの連携をできるクライアント側のフレームワーク
- Amplify Console
    - ホスティング、CI/CD の運用を自動化するマネージドサービス


## 使うメリット

- 認証アクセス権限制限ロジックなど必要最小限の機能は備わっているのでそれを使えばいいので楽
-  スケールしやすい
- 開発環境の変化にも柔軟に対応できる

*なお、AWSやらインフラの知識をあまり知らなくても作業が可能とのこと*

# 参考
https://aws.amazon.com/jp/blogs/startup/techblog-3reasons-amplify/
heroku apps は 5個までらしいです。

Ruby on Rails チュートリアル 5.1（第4版）を学習中。
学習途中におきた出来事をつらつら備忘録として書いているチラシの裏のようなもの。
Qiita見切り発車。たぶん動くからリリースしようぜって偉い人が言ってた。
見にくさも技術も良くなっていくと思います。たぶん。知らんけど。

```
$heroku create
```

createコマンドを実行したら以下のとおり言われてしまった。

```
 ▸    You've reached the limit of 5 apps for unverified accounts. Delete some apps or
 ▸    add a credit card to verify your account.
```

######（訳）
>ver未確認のアカウントのアプリ数の上限5に達しました。 
>一部のアプリを削除するかaccountクレジットカードを追加して、アカウントを確認します。

無料のうちはアプリを５つ以上は作れないらしい。

```
$heroku apps
```

上記コマンドで、現在作成したappを表示できた。

```
hmbrsnmhrgk
mysterious-atoll-47707
pure-hollows-45904
radiant-harbor-62133
rails-tutorial-nmhrgk
```

……確かに５個作成していた。

```
$heroku destroy --app hmbrsnmhrgk（アプリ名）
```

古いappを１つ削除してみる。

```
 ▸    WARNING: This will delete ⬢ hmbrsnmhrgk including all add-ons.
 ▸    To proceed, type hmbrsnmhrgk or re-run this command with
 ▸    --confirm hmbrsnmhrgk
```

######（訳）
>▸警告：これにより、すべてのアドオンを含む⬢hmbrsnmhrgkが削除されます。
>proceed続行するには、hmbrsnmhrgkと入力するか、次のコマンドでこのコマンドを再実行します
>▸-hmbrsnmhrgkを確認します

hmbrsnmhrgkを入力してみた。

```
$heroku apps
```

```
mysterious-atoll-47707
pure-hollows-45904
radiant-harbor-62133
rails-tutorial-nmhrgk
```

５個あったappが４個に減っている。
削除に成功したようだ。

```
$heroku create
```

無事新しいappを作成できました。
YZRH社のテレワーク環境と運用ルールのご紹介


# 概要
新型コロナに伴い、いろんな会社がテレワークを導入しているかと思います
弊社は、まだ出来て1年ぐらいの会社です。
設立当初から、個人の都合にあわせてテレワークを許可する事があり、環境は自然に作られてきていました。
今回は、その弊社のテレワーク環境とルールを紹介します。

# テレワークで利用するツールの紹介

##クラウドストレージやメール

[Google Workspace](https://gsuite.google.co.jp/intl/ja/pricing.html)

ファイルサーバを置かずに全てクラウドストレージを利用します。
Businessプランだと容量無制限なので、チームドライブで適切な権限管理すれば、
クラウドで全てコト足りる感じです。
Google Workspaceアプリケーションも使いやすいですし。

## ナレッジ/情報共有ツール

[Growi](https://growi.org/ja/)

以前は、esaを利用していましたが、協力会社さんが増えると情報へのアクセス権限が必要となったため、Growiに変更しています。
WikiでMarkdown、リッチテキスト、図表も書ける編集機能がいいです。
表現の幅がふえていい感じではありますが、個人的にはesaのほうが好きでしたね。


## コミュニケーションツール（テレカン・チャットツール）

[Slackスタンダードプラン](https://slack.com/intl/ja-jp/pricing)

社内メンバーとの朝礼や会議のテレカンもこれで十分。
ゲストアクセスを使えば、クライアントととのテレカンも出来ます。

色んなサービスと連携することできます。
弊社では、Slackだけで重要なメール来た事を通知やシステム監視のアラートも全てSlackです。

## 開発・運用インフラ環境

AWSやAZURE、GCP（クラウドがメイン）

テレカンの場合、社外からクラウドサーバにアクセスする必要があります。
弊社は、アクセス制御を行っており、AZURE、AWSで構築されたVPNを介してのみの
アクセスを許可しています。
２つあるのはクラウドの障害に引っ張られないようにです。
テレワークだと社外からのアクセスも気を付けないといけないですからね。

## タスク管理
[Clickup](https://clickup.com/)をつかっています。
以前は、JIRAでしたが、弊社のエンジニアがClickupを薦めてくれて、無料で結構使えるので、コストが下がるという非常にいやらしい考えで利用することにしました。
エンジニアやクリエイティブのメンバーたちからは不満もなく、良い感じみたいです。


# テレワークのルールの紹介

## 弊社のルールは、ほんまにシンプル。
・勤怠連絡は、SLACKで。出勤、退勤、休憩開始終了を連絡する。

・朝礼を必ずやる。（メリハリです）

・退勤時に翌日分のタスクをCLICKUPに書いて、書いたことを報告する。

日報とか考えたんですが、返信しないと形骸化しやすいのと
弊社の規模だと、がちがちにすると管理する側もされる側も疲弊するので。
規模にあったやり方を日々模索という感じです。

## 最後に
新型コロナの場合、日頃と違って外出も自粛なんで、同じテレワークでもストレスが掛かりやすいと思います。
管理ではなく、自主性を引き出しつつ、ストレスの少ない環境で気持ちよく仕事をしてもらうかを考えています。
サボるやつもいるかもしれませんが、うちの規模だと何となくわかりますから。

あと、自粛の中でゴールデンウィークは、メンバーも全く嬉しくないですよね。
1カ月ずらして、お客さんに迷惑掛からないようにゴールデンウィークをつくろうかと。
でも、自粛が延長されたら知りませんが。

弊社のテレワークも日々、模索中なので色々考えが変わるかもしれませんが、
導入を考えている同じ規模程度の企業の参考になれば、良いのですが。
【Rails】order

取得した値を並び替えるメソッドになります。

#orderとは
```rb
create_table "posts", force: :cascade do |t|
 t.string "content"
 t.datetime "created_at", null: false
 end
```
通常、上記のような`Postモデル`だとデータベースに格納される値は昇順になります。

```
:id => 1
:created_at =>3.days.ago
:id =>2
:created_at =>1.days.ago
:id =>3
:created_at =>Time.zone.now
```
ただし、実際のアプリケーションであれば投稿を行う際に時間などは降順で表示されます。
そこで`order`を使用します。

以下は`order`を使用したサンプルになります。

```rb
class Post < ActiveRecord::Base
  default_scope -> { order(created_at: :desc) }
end
```
default_scopeは読んだままデフォルトのスコープを定義するメソッドです。ここで定義されたスコープは全てのクエリに適用されます。
※ クエリ：データベースさんに対する命令文のこと。
  スコープ：影響範囲

created_atの後の:descはdescendingの略で降順という意味です。
「監視は役割ではなくスキル」 by 入門監視

**Mike Julian「入門監視」 オライリー刊**を読んで、カルチャーショックというか、「我が意を得たり！」という思いをしたので、紹介します。

[O'Reilly Japan \- 入門 監視](https://www.oreilly.co.jp/books/9784873118642/)

# 「監視は役割ではなくスキル」

私はソフトウェアエンジニア（Dev）に監視の知識は不要であり、
監視はインフラエンジニア（Ops）にお任せするものだと思っていました。
実際、これまでの職歴では、それで困りませんでした。

しかし、「入門監視」はこれを明確にアンチパターンだとしています。

> ソフトウェアエンジニアはアプリケーションについて誰より詳しいので、素晴らしいアプリケーション監視の仕組みをデザインするには最高の場所にいるのです。

考えてみれば当たり前です。Opsはアプリの中身をよく知りません。
Opsが監視を任せられても、通り一辺の監視（CPU使用率など）しかできませんし、異常時にも自分で対応できないんです。

Opsが、

「CPU使用率が増えてるんですけど、大丈夫ですか？」

とDevに尋ねていたら「役割としての監視」に陥っている兆候です。


# ユーザー視点での監視

「監視は役割ではなくスキル」を補強するのが、このデザインパターンです。

「監視」というとCPU使用率などの低レベルの指標がまず思い浮かびますが、
低レベルの指標は改善には役立たない、むしろノイズになってしまうことがあります。
です。

> データベースサーバのCPU使用率が急上昇しても、ユーザーが影響を受けていないならそれは本当に問題でしょうか。
>
> 入門監視 P.30

「入門監視」では逆に「できるだけユーザーに近いところから監視を初める」ことを勧めています。

WEBサービスなら、CPU使用率より

- HTTPレスポンスコード
- レスポンス時間

の方が適切です。レスポンス時間が伸びていれば、少なくとも**ユーザーが何か影響を受けている**ことはすぐに分かります。

「入門監視」では、さらにユーザーに（ある意味）近い部分の指標として、月次収支収益、顧客の解約数、アクティブユーザー数といった、ビジネスの指標も監視対象として挙げています。

# 今後は否応なしに、Devにも監視のスキルが必要になる

「そうは言っても、うちには優秀なOpsがいるし」と思う人もいるかもしれません。

しかし、最近はサービスを構築するときはクラウドがデフォルトの選択肢になっています。

クラウドでは物理サーバー構築が不要なので、Opsが他プロジェクトと兼任である、
あるいはOpsが不在のこともあるでしょう。

また、**最近はインフラエンジニアが採用難である**そうです（AWSやGCPなどのクラウドベンダーに引き抜かれてしまうので）。
となると、今後増々、

「DevだけのOpsが居ないチームがクラウドで構築する」

という体制が増えていくことでしょう。

そうなったら、監視を構築するのはDevのあなたです。

#「入門監視」は全エンジニア必読

「入門監視」は228ページと、オライリーとしては薄めです。

監視とは何か、何をどんな監視するべきかという、プリンシプル・技術以前のところから説明しており、ツールの流行り廃りに囚われない本質的な知識を教えてくれる本です。具

定価3,080円と、大変お求め安い価格なので、ぜひ買って読んでください。
Bash と cURL で YouTube DATA API からプレイリストを取得するサンプル

> YouTube API（YouTube Data API）を cURL で叩いて、YouTube プレイリストの一覧を取得したい。

「[youtube api curl プレイリスト 取得](https://www.google.com/search?q=site:qiita.com+youtube+api+curl+%E3%83%97%E3%83%AC%E3%82%A4%E3%83%AA%E3%82%B9%E3%83%88+%E5%8F%96%E5%BE%97&tbs=qdr:y)」と Qiita 記事に絞ってググってもピンポイントでヒットしなかったので、自分の備忘録として。

## TL; DR

- <font color=green>【**ポイント**】</font>発行した API キーには「`YouTube DATA API`」の制限をかけておくこと。

```bash:Bash+cURLによるGETリクエストのサンプル
#!/bin/bash

# API エンドポイント（リクエスト先の URL）
url_api_endpoint='https://www.googleapis.com/youtube/v3/playlistItems'

# 必須クエリ・パラメーター
key_api_youtube='<Google API Key>'
id_playlist_youtube='<ここに Youtube プレイリストの ID>';
part='snippet'

# オプションのクエリ・パラメーター（0〜50）
num_result_max=50

# クエリ作成
query="key=${key_api_youtube}&part=${part}&playlistId=${id_playlist_youtube}&maxResults=${num_result_max}"

# リクエスト作成
url_request="${url_api_endpoint}?${query}"

# リクエストの実行と取得結果表示
curl -s $url_request | jq .
```

## TS; DR

![スクリーンショット 2020-04-14 17.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78776/90fd364a-d0b5-daaa-441c-78ed98741560.png)

- ポイント
    - API キーの作成／発行は [Google Developer Console の「認証情報」](https://console.developers.google.com/apis/credentials?hl=JA)から行う
        1. 「ライブラリ」から YouTube Data API v3 を有効にする
        1. 上部の組織選択（GoogleAPIs のロゴの隣にあるドロップダウン）メニューから、プロジェクトを作成する
        1. 認証情報を作成（API キー）する
        1. 作成／発行した API キーは、編集して「YouTube DATA API」の制限をかけておきます。<br><font color=darkorange>制限がかかっていないと、リクエスト時に「403 Forbidden」エラーが返ってくる</font>

### Google API の[プロトコル](https://qiita.com/KEINOS/items/cb7f629268b90ef6493d)に関する覚書

- [YouTube API の全体的な仕様](https://developers.google.com/youtube/v3/docs?hl=ja)
- [YouTube プレイリスト項目（アイテム） API の仕様](https://developers.google.com/youtube/v3/docs/playlistItems?hl=ja)
- エンドポイント
    - `https://www.googleapis.com/youtube/v3/playlistItems`
- <code>[part](https://developers.google.com/youtube/v3/docs/videos/list)</code> パラメーターの `snippet` とは
    - リクエストのレスポンスに「動画のプロパティ」（動画情報）を含める
- アクセス・トークンの指定
    - クエリの `keys=` パラメーターで指定する
- アクセス・トークンの種類
    - API キー: 
        - 自前で発行したアクセス・トークンのこと
        - トークンは全てのユーザーで共通のものになる
        - 利用する API（ここでは YouTube Data API）で **API キーを制限する必要あり**
        - :thumbsup: メリット　：
            - 簡単
        - :thumbsdown: デメリット：
            - API キー発行者のクォータ（利用制限の容量）を使う
            - OAuth トークンでないと取得できないデータがある（動画の字幕など）
    - OAuth 2.0 トークン:
        - OAuth クライアント・キーを使って OAuth 認証で得たアクセス・トークンのこと
        - トークンは個々のユーザーごとで異なる
        - :thumbsup: メリット　：
            - クォータ（利用制限の容量）は各ユーザーごとのを使う
        - :thumbsdown: デメリット：
            - 面倒
            - [OAuth 2.0 認証](https://developers.google.com/youtube/v3/guides/authentication?hl=ja)を実装してアクセス・トークンを取得する必要がある
RSpec の request テストで response.status が 403 になった

## 概要
Docker に構築した Rails 6 で、 RSpec の request テストを実行したら、 response.status が 403 になりテストコードが通らなくなりました。
解決に半日以上使ってしまったので、原因と解決方法を残します。

## 環境
Rails 6.0.2
Docker

## RSpec の実行方法
```
docker run --rm -v /hege/app:/app rails_app bundle exec rspec spec/requests
```

## 出ていたエラー
```
Blocked host: www.example.com
To allow requests to www.example.com, add the following to your environment configuration
```
テストコード内で p response を実行して確認しました。

## 原因
Rails6 で追加された DNS リバインディング攻撃防止機能
RSpec でテストを実行すると www.example.com というホスト名でテストが実行されます。
www.example.com が登録されていないホスト名だった為にブロックされたようです。

## 解決方法
アクセスを許可するドメインを Rails.application.config.hosts に追加します。
config/application.rb に、ドメインを追加しました。

```
module XXXXX
  class Application < Rails::Application
    # 略
    config.hosts << '.example.com'
  end
end
```

## 最後に
Rails 6 で ホスト名を指定していないとエラーになる事は知っていたのですが、 RSpec でも同様にエラーになるとは思ってもいませんでした。
最初はパーミッションの問題だと思いこみ、全然違う所を見ていました。
response を出力して読んでいれば半日も潰れる事はなかったです。
Rails からのメッセージをちゃんと読むべきでした。
bq query --destination_table でパーティションテーブルを扱う

`bq query -- destination_table` でパーティションテーブル使う時のメモ。

特に伝えたいことは前回同様パーティション日付の前の **バックスペースを忘れない！**
**バックスペースを忘れない！!**
**バックスペースを忘れない！!** 

# 1. 新規のパーティションを指定する

```bash
bq query --destination_table=dataset.table\$20200401 "SELECT * FROM dataset.table_2 WHERE _PARTITIONTIME = TIMESTAMP('2020-01-01')"
```

# 2. 既存のパーティションに追加(append)する
```bash
bq query --append_table --destination_table=dataset.table\$20200401 "SELECT * FROM dataset.table_2 WHERE _PARTITIONTIME = TIMESTAMP('2020-01-01')"
```
オプションつけないで既存パーティション指定するとappendされる。

# 3. 既存のパーティションを上書き(write_truncate)する
```
bq query --replace --destination_table=dataset.table\$20200401 "SELECT * FROM dataset.table_2 WHERE _PARTITIONTIME = TIMESTAMP('2020-01-01')"
```
バックスペースなしで `--replace` つけると、他のパーティションも全部吹っ飛ぶ大事故に繋がるので気をつける。

# 参考
[BigQuery | bq load コマンドでpartitioned table を作成する](https://qiita.com/YumaInaura/items/7180b0c919dfe584bed2)
画像ファイルのアップロード時に複数のプレビュー画像を表示する【Vue.js】

# ファイルアップロード時に複数の画像プレビューを表示する
題名の通りですが、今回は備忘録として、
画像アップロードを行う際に複数の画像プレビューを
Vue.jsを利用して表示する方法について書いていこうと思います。

## FileAPI
FIleAPIについては以下のドキュメントを参照してください。
https://developer.mozilla.org/ja/docs/Web/API/File

## 実装例

```vue

<template>
  <div>
    <input
      @change="inputFileList($event)"
      multiple="multiple"
      accept="image/*"
    >
    <div
      v-for="(uploadFile, index) in updatedFileList"
      :key="index"
    >
      <p>ファイル名: {{ uploadFile.fileName }}</p>
      <p>ファイルタイプ: {{ uploadFile.fileType }}</p>
      <p>サイズ: {{ uploadFile.size.width }}×{{ uploadFile.size.height }}</p>
      <img :src="uploadFile.url">
    </div>
  </div>
</template>
<script>
export default {
  data: {
    uploadFileList: []
  }
  computed: {
    // this.uploadFileListに変更が加わった際に検知するためです
    uploadFileList() {
      return this.uploadFileList
    }
  }
  methods: {
    async inputFileList(event) => {
      // event.target.filesはファイルデータが格納されたリストです
      const fileList = event.target.files
      if (fileList === 0) {
        return
      }
      // FileAPIは、APIなので複数ファイルを扱う時は、
      // for文の中でawaitする必要があります
      for (file of fileList) {
        // ファイルデータ用のオブジェクトを用意します
        const fileData = {
          name: '',
          type: '',
          size: { width: 0, height: 0 },
          url: ''
        }
        const image = new Image()
        const fileReader = new FileReader()
        // 即時関数をawaitすることで処理の完了までループが終わりません
        await (async () => {
          fileReader.onload = async () => {
            image.src = fileReader.result
            // ファイルURL取得
            fileData.url = fileReader.result
            // 即時関数をawaitすることでfileData.sizeのデータを担保します
            await (() => {
              image.onload = () => {
                // ファイルサイズ取得
                fileData.size = { width: image.naturalWidth, height: image.naturalHeight }
              }
            })()
          }
          // FileAPIの起動
          fileReader.readAsDataURL(file)
        })()
        // 取得したファイルデータのオブジェクトをuploadFileListにpushします
        this.uploadFileList.push(fileData)
      }
    }
  }
}
```
##おわりに
間違いや質問などありましたらコメントお願いします。
useDispatchでredux-thunkを使ったらthenができない件の解決法 (Typescript)


# redux-thunkのthen
たとえばTodo listに一つアイテムを追加・編集・削除した後、
改めてサーバーにRetrieve Listをしたい場合ありますよね。
redux-thunkはこういう感じができます：

```javascript

const createActionCreator = (item) => {
  return dispatch => {
    return axios
      .post('api/todo', item)
      .then(response => {...}) // 割愛します
  }
}

const retrieveActionCreator = () => {
  return dispatch => {
    return axios
      .get('api/todo')
      .then(response => {...}) // 割愛します
  }
}

// どこかで
dispatch(createActionCreator(newItem))
  .then(() => {
    dispatch(retrieveActionCreator())
  })

// ちなみに
dispatch(createActionCreator(newItem))
dispatch(retrieveActionCreator())
// こういう風に書くと、両者ともAsync Callなのでどれが先に完成するのかは保証できませんので。
// 上みたいにthenを使う必要はあります。

```

# useDispatchのdispatchを使うとできなくなる
言語：Typescript
JSだと多分エラー出ないですね。

```javascript
import { useDispatch } from 'react-redux';

const dispatch = useDispatch()

dispatch(createActionCreator(newItem))
  .then(() => { // このthenでエラーが出ます
    dispatch(retrieveActionCreator())
  })
```
実例：
![2020-04-14 16-50-54 的螢幕擷圖.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443144/610c5317-679b-2f55-2858-4c065f8b21b2.png)

`Property 'then' does not exist on type '...'` みたいなエラーが出ますね。
`type`は`actionCreator`の`return type`なので人によっては違いますが。

# 解決法
多分react-reduxがredux-thunkの`dispatch`の型を知らないので、`type check`が通ってない気がします。

storeHelper.ts

```javascript
import { ThunkDispatch } from 'redux-thunk';
import { Action } from 'redux';
import { useDispatch } from 'react-redux';

import { SystemState } from 'features/systemState';
// このSystemStateは自分で定義したReduxのStore構成、詳細は割愛します
// Todo Listだと { items: {name: string ,finished: boolean}[] } みたいな

export type ReduxDispatch = ThunkDispatch<SystemState, any, Action>;
export function useReduxDispatch(): ReduxDispatch {
  return useDispatch<ReduxDispatch>();
}
```

元のファイルで：

```javascript
import { useReduxDispatch } from './storeHelper'

const dispatch = useReduxDispatch()
dispatch(createActionCreator(newItem))
  .then(() => { // できました
    dispatch(retrieveActionCreator())
  })
```

# 終わりに
ご指摘がございましたら、コメントを頂けるとありがたいです。
もしお役に立ちましたらいいねを貰えると嬉しいです。
vimでのコピー(カット)&ペースト(ファイル間での作業も)

vimでのコピー(カット)&ペーストは、メモ帳やVSCodeといった他のエディタとは勝手が違うのでメモ代わりに残そうと思います。
また、ファイル間のコピペもやりづらいのでそちらのやり方も載せておきます。

## 基本的なコピー(カット)&ペースト
編集中のファイルのみで有効な方法です(ファイル間については後ほど紹介)

#### 1行コピー
カーソルをコピーしたい行に移動させて

```
yy
```

#### 1行切り取り
カーソルを切り取りしたい行に移動させて

```
dd
```

#### ペースト

カーソルを切り取りしたい行に移動させて

```
p
```

#### 複数行で行いたいとき(例：3行切り取り)

```
3dd
```
カーソルの位置から何行分かをコマンドの先頭に記述します。

#### 全体のコピー
```
:%y
```
でEnterをするとファイルの全行をコピーできます。

## ファイル間でコピペしたいとき
【参考記事】
[Vimでファイル間のコピー＆ペースト](https://advanceffort.com/vim%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E9%96%93%E3%81%AE%E3%82%B3%E3%83%94%E3%83%BC%EF%BC%86%E3%83%9A%E3%83%BC%E3%82%B9%E3%83%88/)

1. コピー元のファイルを開く
2. コピーをする
3. 以下のコマンドを入力

```
:new コピー先のファイル名
```
例えば、viewsディレクトリ内のoutput.erbだとすると`:new views/output.erb`と入力します。

![image3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480714/567dc203-50e9-a811-59c8-120e6b9ef505.jpeg)
このようになります。
黄色くなっている方が操作できるファイルです。
後は、カーソルを合わせてペーストすれば完了です。

__ファイルの移動をしたいとき__
`CTRL + w + w` カーソルを次のウィンドウに移動する
`CTRL + w + h` カーソルを左のウィンドウに移動する
`CTRL + w + j` カーソルを下のウィンドウに移動する
`CTRL + w + k` カーソルを上のウィンドウに移動する
`CTRL + w + l` カーソルを右のウィンドウに移動する
TypeError: __init__() got an unexpected keyword argument 'status'の対処方法

#はじめに
firebaseをpythonで使用する際、

```swift:エラー内容
TypeError: __init__() got an unexpected keyword argument 'status'
```
上記エラーに遭遇したため、解決方法を記録として残しておきます。


#解決方法
下記コマンドは以下の通りです。

```python:解決方法
pip uninstall requests
pip install requests==2.23.0
pip install firebase_admin
```
上記コマンドで解決できました。
2.23.0のところはrequestsの最新バージョンを指定してください。


今回参考にしたGitHubの記事です。
より詳細に記載がりますので、よろしければご参照ください。
https://github.com/firebase/firebase-admin-python/issues/262

ご参考になれば幸いです。
Pythonで毎日AtCoder #36

### はじめに
[前回](https://qiita.com/taxfree_python/items/d769235774311bbfe964)
今日は頭が動かなかったので、1問しか解いてません。

### #36
[ARC086-A](https://atcoder.jp/contests/arc086/tasks/arc086_a)

**考えたこと**
全ての要素の対してcountしているとTLEします。
countは使えないので、sortした後に隣り合う要素同士を比較していって要素の数を数えます。
要素の種類$set(a)$が$k$よりも多い場合は、$set(a)$から小さい順にansに足していきます。

```python
n, k = map(int,input().split())
a = list(map(int,input().split()))

a.sort()
count = []
c = 1
for i in range(n-1):
    if a[i] != a[i+1]:
        count.append(c)
        c = 1
    else:
        c += 1
    if i == n - 2:
        count.append(c)

l = len(count)
#print(a)
#print(count)
c = 0
if l <= k:
    print(0)
else:
    count.sort()
    for i in range(l):
        l -= 1
        c += count[i]
        if l <= k:
            print(c)
            quit()
```

### まとめ
countは遅い。(おそらく$O(N)$)。ではまた。
.yamlとは

構造化されたデータの表現⽅法:hugging:
xmlやmarkdownのように簡易的な記法。
DockerやRubyでよく見かける:whale:

##用法
1. 各種設定ファイル
2. ログファイル
3. データ交換用のフォーマット

##特徴
1. 読みやすく書きやすい
2. インデントでデータ構造を表す
3. スペースや改行に気をつけないとすぐエラーになる
4. **ハッシュ・配列・スカラー**の三種類の組み合わせでデータを表現する

※スカラー…値。⽂字列や数値、真偽値など

##ハッシュ形式
```yaml
name: puku
address: Tokyo
#出力： {"name"=>"puku", "address"=>"Tokyo"}
```

##配列形式
```yaml
- apple
- banana
- lemon
#出力： ["apple", "banana", "lemon"]
```
jQueryとeach()とreturn false

なんてないことですけど備忘録。
`$('hoge').each()`
なんてので総当たりする。
ifを使って判定して条件にマッチしたときに処理を止めるとき

```js
$('.hoge').each(function(){
 if(!$(this).hasClass('active')){
  $('.fuga').removeClass('active');
  return false;
 } else {
  $('.fuga').addClass('active');
 }
});
```

と、「return false;」を入れる。
もしページ内の.hogeに.activeが無ければそこで処理を止める。
ページ内の.hogeに全部.activeがあればelseを通ります。

忘れていたのでここに書いとく。
[自動運転]　自作のラジコンバスを作る。シャーシ設計編

#ラジコンバスを1から設計
##開発の経緯
日本では様々なラジコンカーが発売されているが、大型車のラジコンはあまり多くない。過去に発売された、アオシマ製のドアが開閉するラジコンを持っているが、ギミックは面白いものの、走行性能は本物と比べると劣る。この度、バスの動きに重点を置いたラジコンを作りたいと思い、設計を始めた。また、制御機器には以前友人から頂いた最新の「Raspberry Pi4」を使用し、人間の操作だけでなく、カメラ画像を使用した自動運転や危険予測にも対応させる。昨今、バスの運転士の不足が問題となっており、コンピューターによる自動運転は大変重要になってきている。自動運転のためには画像認識が大切である。今回のプロジェクトを経て、自動運転や画像認識の理解を深めたいと思う。なお走行の実験をすることが主な目的であり、見た目はあまり重視していない。

**[画像]アオシマ製のラジコンバスと自作のラジコンバス**
![01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613597/29d845c5-b250-692c-1176-b299bcd66e80.jpeg)

車体は未定となっており、今回は実験のため東京都交通局の都バスのペーパークラフトを使用した。制御機器の都合上、天井は取り付けていない。
[都バスペーパークラフト](https://www.kotsu.metro.tokyo.jp/bus/minkuru/papercraft.html)

##走行動画（テスト）
###YouTube
[自作ラジコンバス運転テスト動画](https://youtu.be/hgfTvHg49QU)

##回路図
Raspberry Pi4の回路ソフトで設計した。
![RCBus_ブレッドボード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613597/bf7bdfcc-aefc-a5ec-030f-62b28338734d.png)
DRV8835の向きは画像左側が素子の上側（VM/VCC）、右側が素子の下側（GND/BIN2）である。向きに注意されたい。

##車体設計
###製図
今回はリアルな動きを再現するため、いすゞエルガのサイトや三菱エアロスターのサイトを参考にして寸法を決定した。ステアリング部は特にこだわり、いすゞのサイトに載っていたタイヤの切れ角53°を意識して製作した。スケールはタイヤのサイズより決定し、およそ1/40である。タミヤのユニバーサルボードを用いて製作した。

[いすゞエルガ](https://www.isuzu.co.jp/product/bus/erga_rt/erga_rt.html)
[三菱エアロスター](https://www.mitsubishi-fuso.com/content/fuso/jp/lineup/buses/aero_star/variation.html)

###車体裏側
![DSC01168 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613597/576a60f5-9858-8a93-e567-19a6925afa06.jpeg)
この画像では前方にシャープ製の測距モジュールを取り付けている。（改めて記述予定）


###ステアリング
![DSC01170 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613597/5b689b14-7a19-6eb0-8021-9431df79abdc.jpeg)

タミヤの部品やプラ板を加工したパーツを組み合わせて、ステアリングのスライダ機構を製作した。外側と内側で切れ角を変化させる機構はつけていない。タイヤが設計した角度よりも曲がりすぎないように、紙で作った仮のパーツを挟んでいる。

###後輪部
![DSC01171.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613597/1ced44d8-d823-fc19-7d44-347f8d0caba6.jpeg)

タミヤのギアボックスを取り付けただけである。今回はサスペンションやデフギアなど複雑な機構は取り入れていない。

##使用材料
###[ハードウェア]
・Raspberry Pi4 4GBモデル
・Arduino nano 互換モデル
ラズパイは主に通信と画像処理に使用し、回路の制御はArduinoに任せることにした。ラズパイとArduinoは「Pyserial」のライブラリを用いて行った。

###[材料]
・タミヤ　ユニバーサルプレートセット
・タミヤ　ユニバーサルアームセット
・タミヤ　ユニバーサルプレート用スライドアダプター
・タミヤ　ミニモーター標準ギヤボックス （8速）
・タミヤ　1.5mmプラ板
・M2/M3ネジ　いろいろな種類があるとよい。
・ブレットボード
・ジャンパ線
・積層セラミックコンデンサ0.1[μF]
・浅草ギ研　RCサーボ ASV-15　タイプA
・DRV8835使用ステッピング&DCモータドライバモジュール
・朝日電器 ELPA エルパHK-M25H [タイヤ25mm 2個入]
→探した中で最もバスのタイヤに近いと思う。

##おわりに
今後も自動運転に向けた開発を続けていく。
JerseyでHttpServletRequestなどのコンテキスト情報を得る

[Jersey+SpringFrameworkでRESTFulAPIを実装](https://qiita.com/kasa_le/items/2714f4deac718715f2d2)していて、以下の情報が必要になりました。

- HttpServletRequest
- HttpServletResponse

その方法を調べたので覚え書き。

# 環境など

|ツールなど|バージョンなど|
|:--|:--|
| MacbookPro |macOS Mojave 10.14.5|
|IntelliJ IDEA |Ultimate 2019.3.3|
|Java |AdoptOpenJDK 11|
|apache maven |3.6.3|
|Jersey|2.30.1|
|JUnit|5.6.0|
|Tomcat|apache-tomcat-8.5.51|
|Postman|7.19.1|
|Spring Framework|5.2.4-RELEASE|

# 取得方法

`@Context`をつけてメンバー変数に宣言するだけ。

```java
@Service
@Path("/my")
class MyResourceApi{
    @Context
    HttpServletRequest httpServletRequest;

    @Context
    HttpServletResponse httpServletResponse;
}
```

これ以外のコンテキスト関係の情報は、どれも同じようにして取得可能かと思われます。

# もうちょっと詳しく

これは、Jerseyのそのものの機能というより、Jerseyがversion2から組み込んでいる[HK2](https://javaee.github.io/hk2/)というアノテーションベースでのDI機能のおかげのようです。

詳しくはこちらで。

HK2
https://javaee.github.io/hk2/introduction.html

Jersey2に組み込まれてるDI機能（HK2）を試す
https://qiita.com/opengl-8080/items/9bdc98aa5269512bd70e
fish で rbenv with anyenv が動かなくなっての解決策

anyenv は -v でバージョン表示されたが、rbenv は存在しない状態。
恐らく初期設定でパスを通す設定作業をスルーしたのが原因。

**解決策**

```
$ echo 'status --is-interactive; and source (anyenv init -|psub)' >> ~/.config/fish/config.fish
```


上記は `~/.config/fish/config.fish` に一行追加するだけのコマンドです。
対象の行が有ったらこの記事は参考にならなさそうなので無視してください。

ちなみに解決に至ったのは下記のコマンドから、です。

```
$ anyenv init
# Load anyenv automatically by adding
# the following to ~/.config/fish/config.fish:

status --is-interactive; and source (anyenv init -|psub)
```
ポアソン分布間のKLダイバージェンスのメモ

ポアソン分布に従う２つの確率分布のKLダイバージェンスの計算をメモとしてまとめました。  

## 前提

２つの確率分布$p, q$はパラメータ$\lambda_p, \lambda_q$をそれぞれ持つポアソン分布に従っている。  
$p$の確率密度関数は以下のように定義する。  

$$p(x) = e^{-\lambda_p} \frac{\lambda_p^x}{x!}$$

また離散確率分布のKLダイバージェンスは以下のようになる。

$$D_{KL}(p, q) = \sum_{x=0}^{\infty} p(x) \log \frac{p(x)}{q(x)}$$

## 計算式

```math
\begin{equation*}\begin{split}D_{KL}(p,q) &= \sum_{x=0}^{\infty} p(x) \log \frac{p(x)}{q(x)} \\&=\sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot \log \frac{e^{-\lambda_p} \frac{\lambda_p^x}{x!}}{e^{-\lambda_q} \frac{\lambda_q^x}{x!}} \\&=\sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot ( \log e^{-\lambda_p} \frac{\lambda_p^x}{x!} - \log e^{-\lambda_q} \frac{\lambda_q^x}{x!} )\\&=\sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot (-\lambda_p +\log \frac{\lambda_p^x}{x!} +\lambda_q - \log \frac{\lambda_q^x}{x!} )\\&=\sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot (\lambda_q -\lambda_p +\log \frac{\lambda_p^x}{x!} \frac{x!}{\lambda_q^x} )\\&=\sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot (\lambda_q -\lambda_p +\log \frac{\lambda_p^x}{\lambda_q^x} )\\&=\sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot (\lambda_q -\lambda_p) + \sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot \log \frac{\lambda_p^x}{\lambda_q^x} \\&=\lambda_q -\lambda_p + \sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^x}{x!} \cdot x \log \frac{\lambda_p}{\lambda_q} \\&=\lambda_q -\lambda_p + \sum_{x=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^{x-1}}{(x-1)!} \lambda_p \cdot \log \frac{\lambda_p}{\lambda_q}\\&=\lambda_q -\lambda_p + \sum_{t=0}^{\infty} e^{-\lambda_p} \frac{\lambda_p^{t}}{t!} \lambda_p \cdot \log \frac{\lambda_p}{\lambda_q} &\mbox{$t=x-1$とする}\\&=\lambda_q -\lambda_p + e^{-\lambda_p} e^{\lambda_p} \lambda_p \cdot \log \frac{\lambda_p}{\lambda_q} \\&=\lambda_q -\lambda_p + \lambda_p \cdot \log \frac{\lambda_p}{\lambda_q}\\\end{split}\end{equation*}
```



## 検証

scipyのpmf, entropyを利用したKLダイバージェンスの計算と上の数式での結果が等しくなるかどうか試した。

```python
import numpy as np
from scipy.stats import poisson, entropy


x = np.linspace(0, 100, 101)

# パラメータλをalphaとして定義
alpha_p = 1
alpha_q = 5
p = poisson.pmf(x, alpha_p)
q = poisson.pmf(x, alpha_q)
kl = entropy(p, q)

# 上の式に基づいた計算
kl_alpha = alpha_q - alpha_p + alpha_p * np.log(alpha_p / alpha_q)

print("entropy関数を利用したKLダイバージェンス：", kl)
print("alphaを利用したKLダイバージェンス：", kl_alpha)

```

出力結果

```
entropy関数を利用したKLダイバージェンス： 2.3905620875658995
alphaを利用したKLダイバージェンス： 2.3905620875658995
```
とある学生がゲーム開発してみた。#4(私がバカだった話)

#問題解決!
前にTerrainで樹木が出てこない話をしたのですが、問題無事解決しました!
#チェック·····あれ?
実は私、Terrainの設定の樹木を表示(だったかな?)のチェックボックスにチェックしてなかったのです。
#解決したけど·····
解決したのはよかったのですが、チェックを入れた途端、うなりを上げる(訳:冷却ファンを全力で回す)私のWindows君。はい、チェックを入れる前にバカみたいに木を植えられないか試してた私が悪いんです。ということで今回はTerrainを使わず(私のWindows君をうならせたTerrainは消しました。)blenderでローポリ地形を作ることにしました。
axiosでファイルダウンロード

# はじめに
JavaScriptでCSVなどを作成し保存させる場合、ブラウザにより実装方法が異なります。
FileSaver.jsライブラリを利用してクロスブラウザ対応しファイル保存できるようにします。

[FileSaver.js](https://github.com/eligrey/FileSaver.js)

# サンプルコード

```javascript

import { saveAs } from "file-saver";
import axios from "axios";

function csvDownload() {
  axios.get('/csv', {
    responseType: "blob",
  }).then(response => {
    const blob = new Blob([response.data], {
      type: response.data.type
    });
    const fileName = 'hoge.csv';
    saveAs(blob, fileName);
  });
}
```
rails 開発日記1 トップページの実装

#　トップページの実装

＊この記事は技術や知識の共有目的ではなく、完全に自己満足のアウトプット用です。

＜開発環境＞
1. ruby 2.6.3
2. Rails 5.1.6
3. AWS Cloud9
4. GitHub
5. Heroku（予定）



SNSのコピーサイトの開発にあたり、トップページを実装をした。
<img width="1422" alt="スクリーンショット 2020-04-14 16.14.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618929/fd08a5d4-26b1-855c-e7c2-d48cf4aa5ca2.png">
　　　　　　　　　　　　　　　　　１、トップページの完成系


自分なりに工夫した点

1.パーシャルの使用
パーシャルは開発時にHTMLの中身を整理する為のものである。
Railsチュートリアルを参考に、headerとIE用のHTML shimをまとめてみた。

```
<!DOCTYPE html>
<html>
  <head>
    <title>JiroApp</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= render 'layouts/shim' %>
  </head>

  <body>
    <%= render 'layouts/header' %>
    <%= yield %>
  </body>
</html>
```
これによって、headerのHTMLを <_header.html.erb>　に移行することができました。

HTML CSSはあまり得意ではないのでこだわるつもりはないです。。。

次はユーザー登録機能の実装をしていきます。
[Android] レビューダイアログ表示


# レビューダイアログ表示

以下の手順となります。

・ライブラリ導入して使う
・ダイアログ表示タイミングコンフィグレーションする

## ライブラリ導入

**1.dependencies に追加する **

```kotlin

implementation 'com.vorlonsoft:androidrate:1.2.5-SNAPSHOT'
```
<img width="948" alt="sshot_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/586cc11f-e4fc-60d5-9718-77439a911999.png">

**2. Gradle Syncしてライブラリを入れる**
<img width="921" alt="sshot_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/4b078211-c629-74a6-4577-eaba86540249.png">

## ライブラリ使う

**1. 表示したいクラスでインポートする**

```kotlin

import com.vorlonsoft.android.rate.*
```

<img width="919" alt="sshot_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/deeee21a-ca71-22db-ad08-a83daae3beef.png">

**2. レビューダイアロ作成する**

```kotlin

AppRate.with(this)
```


**3. ダイアログ出るタイミングをコンフィグレーションする**

下の設定なら、この条件になります。

アプリインストールした後、５回起動し２０日以上時にダイアログが出る。
「また今度」ボタン押した後、５回起動し２０日以上時にダイアログが出る。
「レビューしない」または「レビューする」押した後、ダイアログが出ない。

```kotlin

.setStoreType(StoreType.GOOGLEPLAY)
.setTimeToWait(Time.DAY, 10)
.setLaunchTimes(3)
.setRemindTimeToWait(Time.DAY,20)
.setRemindLaunchesNumber(5)
.setSelectedAppLaunches(1)
.setShowLaterButton(true)
.setVersionCodeCheck(false)
.setVersionNameCheck(false)
.setDebug(false)
.setCancelable(false)
.setTitle(R.string.new_rate_dialog_title)
.setTextLater(R.string.new_rate_dialog_later)
.setMessage(R.string.new_rate_dialog_message)
.setTextNever(R.string.new_rate_dialog_never)
.setTextRateNow(R.string.new_rate_dialog_ok)
.monitor() 
```


<img width="842" alt="sshot_4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/a9dcf002-a45a-a9b8-7c78-a6d39d378312.png">

**4. ダイアログのボタンクリックイベント追加**

```kotlin
AppRate.with(this).setOnClickButtonListener(object: OnClickButtonListener {
            override fun onClickButton(which:Byte) {
              
                if(which.toString().equals(RATE)) {
                    //inApp_レビューする
                } else if(which.toString().equals(RATE_LATER)) {
                  
                } else if(which.toString().equals(RATE_NEVER)) {
                    //nApp_レビューしない
                }
            }
        })
```


<img width="843" alt="sshot_5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/b0218219-eb70-b3b4-d81d-f261ba0be4e9.png">

**5. コンフィグレーションした設定と合わせる時に表示するため**

```kotlin

        if (AppRate.with(this).getStoreType() == StoreType.GOOGLEPLAY) { // Checks that current app store type from library options is StoreType.GOOGLEPLAY
            if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING) { // Checks that Google Play is available
                AppRate.showRateDialogIfMeetsConditions(this) // Shows the Rate Dialog when conditions are met
            }
        } else {
            AppRate.showRateDialogIfMeetsConditions(this)    // Shows the Rate Dialog when conditions are met
        }
```


<img width="940" alt="sshot_6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618722/dbd4237b-74d0-2cc8-8371-f56f25500702.png">
ファイル名を検索して移動(R)

file.copyとfile.removeを使う。

```kiritori.R
lf_from <- paste0("移動前のディレクトリ", list.files(path="移動前のディレクトリ", pattern="検索文字列")
lf_to   <- paste0("移動後のディレクトリ", list.files(path="移動前のディレクトリ", pattern="検索文字列")
file.copy(from=lf_from, to=lf_to)   #ファイルをコピー
file.remove(lf_from) 　　　　　　　   #元のディレクトリにあるファイルを削除
```
Zsh 環境に anyenv をインストールする手順

Mac のデフォルトの SHELL が Bash から Zsh になったので、zsh に anyenv を１からインストールする手順を示します。

環境 : macOS Catalina バージョン 10.15.4

### 1.Xcode インストール
app store から Xcode をインストールします。
### 2.homebrew のインストール
参考 :
https://brew.sh/index_ja
こちらに書いてある手順で homebrew をインストールします。

インストールできているか確認します。

```
brew
```
Homebrew のコマンドが表示されればインストールされています。

### 3.anyenv のインストール
参考 :
https://github.com/anyenv/anyenv
homebrew から anyenv をインストールします。

```
brew install anyenv
```
「anyenv init -」を実行する処理を echo と >> を使って .zshrc に記述します。

```
echo 'eval "$(anyenv init -)"' >> ~/.zshrc
```

シェルを再起動させます。

```
exec $SHELL -l
```

インストールできているか確認します。

```
anyenv
```
anyenv のコマンドが表示されればインストールされています。

あとは、rbenv なり、nodenv なり好きにインストールしてください。
Component UIのテーブル内でHTMLを有効化したい

[Componentテーブル](https://element.eleme.io/#/en-US/component/table)内に表示するデータをHTMLを表示したいと考えてはまった時のメモ。
データそのものは有効化できなかったが、以下の方法で目的が達成できた。
### 変更前
name_telデータ内でHTMLデータを記載すると、そのままエスケープされて出てきてしまう。

```
// 氏名と電話をまとめて取得
<el-table-column
 prop="name_tel"
 label="氏名"
 width="200px">
</el-table-column>
```

### 変更後
`<template>`で表示内容を分岐させて、装飾させて解決。

```
// 氏名と電話を分けて取得し、分けて表示
<el-table-column
 prop="name_tel"
 label="氏名">
  <template slot-scope="scope">
   <div>{{ scope.row.name}}</div>
   <div v-if="scope.row.tel"><i class="fas fa-phone-square"></i>{{ scope.row.tel }}</div>
  </template>
</el-table-column>
```
IQ Bot：分類不能になったドキュメントを見る方法

IQ Botの[分類がうまくいかない場合に確認するべきポイント](https://qiita.com/IQBotter/items/b9f6bd9abeb4b9925744)について先日記事を書きましたが、そもそも分類不能になったドキュメントがどれなのかを調べる方法についてこちらにまとめます。

#分類不能になったドキュメントのありか

分類不能になったドキュメントは、V11系統であれば、IQ Botサーバ上に入っています。
インストール時にOutputフォルダのPathを特にいじっていなければ、以下のフォルダに入っているはずです。

**C:\Users\Public\Documents\Automation Anywhere IQBot Platform\Output\対象のインスタンス名\Unclassified**

上記のフォルダ配下に、分類不能（Unclassified）になった画像のデータがコピーされてそのまま入ります。

#分類不能になったドキュメントのネーミングルール

Unclassifiedフォルダに入ったドキュメントは、もとのファイル名の頭にIDがついた形で上記のフォルダに入っています。

たとえば「サンプル.pdf」というドキュメントを処理して分類不能（Unclassified）になった場合は、以下のようなファイル名になっているはずです。

**1234567a-123b-456c-789d-1234567890ef-サンプル.pdf**

IDの部分はIQ Botによって自動付番され、書類ごとに変わります。
SPRESENSE + LTE + Arduino Library で eDRX を設定する

# この記事について

SPRESENSE + LTEボード を Arduino Library を使用して実装するときに、eDRX の設定を行う方法をまとめてみます。

# eDRX とは？
簡単に言うと、LTE-M / NB-IoT での省電力の手法です。
詳細はドコモの [この辺の資料](https://www.nttdocomo.co.jp/binary/pdf/corporate/technology/rd/technical_journal/bn/vol26_2/vol26_2_008jp.pdf) を参照してみてください。

# SPRESENSE + Arduino Library での eDRX 設定方法

SPRESENSEの [Arduino Libraryのリファレンス](https://developer.sony.com/develop/spresense/developer-tools/api-reference/api-references-arduino/) を見てみても、eDRX の設定を行うための関数などは用意されていません(2020/04現在・ver.1.5.1)。
しかし、より低層のライブラリである Spresense SDK の関数を使用することにより、eDRXの設定が可能となるようです。

## 実装内容
ざっと説明していきます。

### include 

SPRESENSE SDK の LTEライブラリである `lte/lte_api.h` を include しておきます。

```cpp:spresense_edrx_test.ino
#include <LTE.h>          // SPRESENSE Arduino Lib LTEライブラリ
#include <lte/lte_api.h>  // SPRESENSE SDK LTEライブラリ  ←これを include しておく
```

### setup()

eDRXの設定は、モデムの初期化後から回線を接続するまでの間に設定する必要があります。つまり `LTE.begin()` と `LTE.attach()` の間です。

eDRX の設定は、`lte_edrx_setting`構造体の各メンバに設定値を代入し、`lte_set_edrx_sync()`関数にそれを渡します。 `lte_edrx_setting`構造体で設定する値は [こちらのページ](https://developer.sony.com/develop/spresense/developer-tools/api-reference/api-references-spresense-sdk/structlte__edrx__setting.html) をご参照ください。

```cpp:spresense_edrx_test.ino

// APN data
#define LTE_APN       "your.apn.info.here"
#define LTE_USER_NAME "username"
#define LTE_PASSWORD  "password"

// initialize the library instance
LTE lteAccess;

void setup() {
  while (true) {
    if (lteAccess.begin() == LTE_SEARCHING) {
      setup_edrx();    // この部分でeDRXの設定を行う。この関数の内容はこの後に記載。
      if (lteAccess.attach(LTE_APN, LTE_USER_NAME, LTE_PASSWORD) == LTE_READY) {
        Serial.println("attach succeeded.");
        break;
      }
      Serial.println("An error occurred, shutdown and try again.");
      lteAccess.shutdown();
      sleep(1);
    }
  }
}

int setup_edrx() {
  //eDRXの設定を記述する
  //設定値は https://developer.sony.com/develop/spresense/developer-tools/api-reference/api-references-spresense-sdk/structlte__edrx__setting.html を参照。
  lte_edrx_setting edrx;
  edrx.enable = LTE_ENABLE;              // eDRXを有効にする
  edrx.act_type = LTE_EDRX_ACTTYPE_WBS1; // LTE-Mを使用する場合は LTE_EDRX_ACTTYPE_WBS1 を設定しておく
  edrx.edrx_cycle = LTE_EDRX_CYC_16384;  // eDRXサイクルを 163.84sec に設定する
  edrx.ptw_val = LTE_EDRX_PTW_512;       // PTWを 5.12sec に設定する

  int ret = lte_set_edrx_sync(&edrx);    // eDRX を設定する
  Serial.print("lte_set_edrx_sync result=");  Serial.println(ret);
  return ret;
}
```

# PSMについて
同様に、`lte_set_psm_sync()`関数や `lte_psm_setting`構造体が用意されていますので、こちらでPSMの設定をすることも可能のようです（試していない）。
詳細は [このへん](https://developer.sony.com/develop/spresense/developer-tools/api-reference/api-references-spresense-sdk/group__lte.html#gab727223112616d527c87a4dea4188a68) や [このへん](https://developer.sony.com/develop/spresense/developer-tools/api-reference/api-references-spresense-sdk/structlte__psm__setting.html) をご参照ください。