OmniAICreator/Qiita-1.07M huggingface dataset:
babylon.js の ArcRotateCamera でマウス操作とタッチ操作に両対応のボタンカスタマイズを簡易実装する方法

# 期待動作するおそらく最も簡単な実装方法

```js
// camera: babylon.js の ArcRotateCamera のインスタンス
// canvas: camera を attachControl した <canvas> 要素

// マウス操作(されそう)を検出したらボタンカスタマイズ: 左ボタンでの回転操作を無効化
canvas.onmouseenter = e => camera.inputs.attached.pointers.buttons = [1, 2];
// タッチ操作を検出したら操作を default 挙動相当へ戻す
canvas.ontouchstart = e => camera.inputs.attached.pointers.buttons = [0, 1, 2];
```

## 解説

`camera.inputs.attached.pointers.buttons` は `PointerEvent` が届いた際にどのボタンの操作を扱うか `PointerEvent.button` (`extends`元の`MouseEvent`から継承) に対応する値の群で設定。

- `PointerEvent`: https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent
  - `MouseEvent`: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
    - `.button`: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
- `ArcRotateCamera`: https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCamera
  - `.inputs`: https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCamera#inputs
  - `ArcRotateCameraInputsManager`: https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCameraInputsManager
    - `.attached`: https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCameraInputsManager#attached
- `ArcRotateCameraPointersInput`: https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCameraPointersInput
  - `.buttons`: https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCameraPointersInput#buttons

`mouseenter` イベントは canvas 上でマウスによるポインター操作(有効範囲内へマウスカーソルを移動しただけでも発生)を捕捉、`ontouchstart`はタッチ操作の反応領域に指が入った段階で発生するイベント。`onclick`や`onmousedown`ではこの手法のための検出としては遅すぎ、 babylon.js の ArcRotateCamera の回転挙動が「発生開始した後」に仕込みのトリックが有効化されてしまう。そうなると`onmouseup`相当で回転挙動が終了しなくなる。

- `mouseenter`: https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseenter_event
- `touchstart`: https://developer.mozilla.org/en-US/docs/Web/API/Element/touchstart_event

### 参考資料

- `ArcRotateCameraPointersInput` など `camera.inputs.attached` の標準実装群のソース
  - https://github.com/BabylonJS/Babylon.js/tree/master/packages/dev/core/src/Cameras/Inputs
    - https://github.com/BabylonJS/Babylon.js/blob/master/packages/dev/core/src/Cameras/Inputs/arcRotateCameraPointersInput.ts
- babylon.js API | Diving Deeper | Camera | Customizing Camera Inputs
  - https://doc.babylonjs.com/divingDeeper/cameras/customizingCameraInputs
大人の読解力を鍛える

https://www.amazon.co.jp/%E5%A4%A7%E4%BA%BA%E3%81%AE%E8%AA%AD%E8%A7%A3%E5%8A%9B%E3%82%92%E9%8D%9B%E3%81%88%E3%82%8B-%E5%B9%BB%E5%86%AC%E8%88%8E%E6%96%B0%E6%9B%B8-%E9%BD%8B%E8%97%A4-%E5%AD%9D/dp/4344985710/ref=asc_df_4344985710/?tag=jpgo-22&linkCode=df0&hvadid=342543494815&hvpos=&hvnetw=g&hvrand=550421292239353768&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009255&hvtargid=pla-826076527424&psc=1&th=1&psc=1

背景
最近読解力を鍛えたいと思い様々な本を読んでいますが、この本の著者が書いた書籍は面白い内容のものが多かったので気になりました。
内容を少し読むと、本だけではなく様々な媒体から本質を読み解くことに触れているようでしたので、読んでみたくなってしまい手に取るに至りました。

本書のテーマ
大人の読解力＝言葉や文章を正確に把握し、論理的に整理して読み取る能力。人のあり方や感情を理解する力、状況や場の空気を把握する力という感情理解のスキル。
これがどういうことか、具体例を交えながら説明してくれています。

個人的なポイント
1.大人の読解力の基本
「相手の伝えたいことの中心＝真意」これを捉える。まさに、バットの真芯でボールを捉え打ち返すこと。
本の一発目に、この例えが書かれていて、秀逸だなと感じ最高の本だなと思ってしまいました。
言葉は単語ではなく、文脈を捉えることでミートする。
まさしく、私がほしい能力です。

2.大事な能力
・要約力＝情報を受け取る側に完結にまとめて伝える力、要約する力
・語彙力＝言葉をたくさんしてってれば豊かな表現ができる。それが知性につながる。
・文脈力＝言葉は省略されたり、表現が曖昧になる。不完全な論理性の中で文脈の繋がりを考え、推測しながら話し手の真意を外さずに捉える。

3.行間を読む
書かれている文章だけではなく、その描写の裏に何があるのか。常に想像しながら読むことが行間を読むということ。

4.読解力を鍛えられるのは本だけじゃない
様々な例を上げていましたが、私が特に驚いたのは絵、歌詞、野球からも読解力を鍛えられるということです。

個人的に一番心に残ったポイント
私が抱えている課題の一つに「打ち合わせ中、相手の話していることの真意を理解する」というものがあります。
それを鍛えるためには、本を読むことが最適化と思っていました。
ですが、文章は読んで理解するのに時間がたっぷり取れますし、文章も論理建てて組み立てられていることが多いです。
しかし、打ち合わせとなるとリアルタイムなやり取り、且つ省略されてたり、倒置法になっていたりと文章とは全く違う状態なんだということに気付かされました。
それを鍛えるノウハウは書かれておらず、読解力を様々な場面で鍛える重要性を解かれていましたが、自分が抱えている課題の解決の道筋は見えてきた気がしました。

まとめ
著者は本だけでなく、どんなものに対しても向き合って分析することで真意を汲み取ることができる。とにかくどんなものに対しても、これはこうなんじゃないかという意見を持たれていて、本書を読み終えるときには、常に色々考えている方なんだなというのを感じました。

相手が何を伝えたいのかという真意を汲み取った上で、自分の意見を持つことができ、的確なアドバイスができる。
これができるだけで自身のバリューを生み出すことができると思います。
そして、これができる人はそんなに多くないということも実感しています。

他の本でアウトプットの方法やトレーニングすべき部分について学べることができましたが、本書では読解力をつける上での心構え的なことを学んだ気持ちです。
Python,Ruby,PHP,Java,JavaScript,Perlのファイル・ディレクトリ操作の比較 | プログラミング言語比較

<a href="https://qiita.com/yuki_kimoto/items/f9c2454e7f9130ddb003">Qiita > プログラミング言語の比較</a>

プログラミング言語Python,Ruby,PHP,Java,JavaScript,Perlのファイル・ディレクトリ操作の比較

# Python

https://qiita.com/supersaiakujin/items/12451cd2b8315fe7d054

# Ruby

https://qiita.com/prgseek/items/38f74d99b74baa3b42f7

# PHP

https://qiita.com/daichi87gi/items/111cd922991e4a18d1ef

# Java

https://qiita.com/suema0331/items/03330a663773204afc5f

# JavaScript

https://qiita.com/turmericN/items/28e8bc8fca07285ddffc

# Perl

https://perlzemi.com/blog/20161126148016.html
第09回 Customer系エンジニア座談会 を覗いて得た学び

## 第09回 Customer系エンジニア座談会

https://customer-x-engineer.connpass.com/event/257816/

で得た学びのメモです。Customer系エンジニア座談会とは... 

>顧客とプロダクトの間をつなぐような役割のエンジニアです。 主に次のような職種名で呼ばれています。
> -   Customer Reliability Engineer
> -   Customer Engineer
> -   Customer Success Engineer
> -   Customer Support Engineer

各社、各製品、各フェーズで色々な名前で呼ばれますね。お話を伺って得た知見、キーワードを記載します。

## メモ

- Customer Reliability Engineering とは
    - お客様の信頼性を把握しコントロールする技術

https://developer.hatenastaff.com/entry/2017/08/09/173607 

https://blog.autify.com/ja/from-csce-to-csm-and-cre

- カスタマーサクセスという技芸を工学に昇華させる
    - という点でカオスエンジニアリング本も読みたい
        - [O'Reilly Japan - カオスエンジニアリング](https://www.oreilly.co.jp/books/9784873119885/)
    - observability
    - accessibility
    - scalability

https://blog.autify.com/ja/autify-cs-tool-and-activities-1

https://blog.autify.com/ja/autify-cs-tool-and-activities-2


- CSMはエンジニアバックグラウンドがあるべき？
    - エンジニア向け製品と非エンジニア向け製品
    - プロダクトの特性、フェーズにもよりそう
        - よりコミュニケーションが重視されることもあるよね、と思う
        - CSの知見・活動が、プロダクトの機能になる、と思う
- サポート対象の切り分け
    - プレミアサポート対象か等というあるある
    - それを優しく切り分けるのはリアルな悩みである笑
- "unexpected churn" というのは良い指標
- 「カスタマーサクセス・プロフェッショナル」
    - [テクニカルソリューションのCSMが考慮すること- 「カスタマーサクセス・プロフェッショナル」 読書メモ - missasan's notebook](https://missasan.hatenablog.com/entry/the-customer-success-professionals-handbook)
- CREとは顧客の信頼性を向上させる、ではなく信頼性を把握しコントロールする技術


以上です～
BeautifulSoup4：「htmlのタグと属性が同じ複数の要素」から、その周辺の情報を使って特定の要素を抽出する

## やりたいこと

例えばhtmlファイルの中に次のような記述があったとする。

```html:sample.html
...
<h3>朝</h3>
<p class="greeting">おはよう</p>
<h3>昼</h3>
<p class="greeting">こんにちは</p>
<h3>夜</h3>
<p class="greeting">こんばんは</p>
...
```

この中から、「昼」を検索キーとして対応するp要素、``<p class="greeting">こんにちは</p>``を抽出したい。

## 解決策

Pythonのhtml解析ツール「BeautifulSoup4」を用いて、以下のように``<h3>昼</h3>``要素を抽出した後に、``find_next``関数で、条件を指定して検索すればOK。
ちなみに``find_previous``は対象要素よりも前の要素を検索する。

```python
from bs4 import BeautifulSoup

with open("sample.html", "r") as f:
  text = f.read()  
  soup = BeautifulSoup(text, features="lxml")

  # h3タグの要素を全て抽出
  # h3s = [<h3>朝</h3>, <h3>昼</h3>, <h3>夜</h3>] となる
  h3s = soup.find_all("h3")

  # テキストが昼の要素を抽出
  # h3 = [<h3>昼</h3>] となる
  h3 = list(filter(lambda x: x.text == "昼", h3s))

  # h3[0]よりも後の要素のうち、条件を満たすものを抽出
  # greeting_noon = <p class="greeting">こんにちは</p> となる
  greeting_noon = h3[0].find_next("p", attrs={"class": "greeting"})

  # h3[0]よりも前の要素のうち、条件を満たすものを抽出
  # greeting_morning = <p class="greeting">おはよう</p> となる
  greeting_morning = h3[0].find_previous("p", attrs={"class": "greeting"})
```

## 参考サイト

https://naruport.com/blog/2019/7/13/how-to-use-of-beautiful-soup-4/

↑本記事で扱ったfind_next(previous)以外にも、様々な実例が書かれていて参考になる。
画面の一部でUIHostingControllerを使っているとNavigationBarを隠したいのに隠れない問題の対応方法

下記のコードのようにナビゲーションバーを隠すためsetNavigationBarHiddenを記述しているがUIHostingControllerを使用しているとナビゲーションバーが隠れない。

```swift
class ThirdViewController: UIViewController {
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.setNavigationBarHidden(true, animated: false)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let hc = UIHostingController(rootView: SwiftUIView())
        self.addChild(hc)
        self.view.addSubview(hc.view)
        hc.didMove(toParent: self)

        hc.view.translatesAutoresizingMaskIntoConstraints = false
        hc.view.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        hc.view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }
}
```
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662300/b18dccd7-e3b0-c0b3-06df-82d3887a2865.png width="300">


対応方法としては下記のようなUIHostingControllerのカスタムクラスを作成すれば良いらしい。
```swift
class UIHostingControllerToHideNaviBar<Content: View>: UIHostingController<Content> {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
}
```
修正版
```swift
class ThirdViewController: UIViewController {
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.setNavigationBarHidden(true, animated: false)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let hc = UIHostingControllerToHideNaviBar(rootView: SwiftUIView()) //←作ったやつに変更
        self.addChild(hc)
        self.view.addSubview(hc.view)
        hc.didMove(toParent: self)

        hc.view.translatesAutoresizingMaskIntoConstraints = false
        hc.view.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        hc.view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }
}
```

そうすると隠れるようになった。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662300/0c3c59eb-9a3e-e5ef-9460-e458aaf09f66.png width="300">

完
木構造

# ２分木の種類
節が持つ```枝（ブランチ)の数（はの方向）が２本以下```のもの。

## AVL木（えーぶいえるき）
任意の節において、```左右の部分木の高さの差が１以下```のもの。
データ探索などに使われる。

## ヒープ
どの親子関係も、親＜子になっているが、２分探索木のように左右の部分木の順序はない。
最大値（最小値）が見つかれば良い時などに使う。

### 気づき
ヒープは説明を読んでもよくわからない。

# B木（多分木)
葉までの階層の深さが全て等しく、```一つの節が複数の子を持つ```多分木構造。
```データ量が多くなっても記憶効率、探索効率がよく```、階層型データベースなどで利用される。

# 出典　

https://gihyo.jp/book/2022/978-4-297-12375-8
【Flutter】ListView.builderで作成したRadio・RadioListTileで単一選択できない。複数選択できてしまうときの対処

今回の事象は、レアケースかもしれませんが
かなりドツボにはまったので、記録に残します。

### 発生した問題
ListView.builderで作成したラジオボタン全てが選択状態にできてしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2823638/bc5947ba-dac1-fe1a-bf07-ec1e958b2256.png)


アンケートのようなアプリを開発中、リストごとにラジオボタンを5個ほど配置。
大人しくWidgetを5個書けばこんなことにはなりませんが、どうしてもラジオボタンの個数を決め打ちにしたくなかったのと
他の方法が思いつかなかったため今回の方法をとりました。


アンケートの問いをListView.Builderを使って複数リストを作成、
その中に、更に複数のRadioをListView.Builderで作成。
その結果、いくらgroupValueを一意の値にしても、全てのRadioが選択出来る状態になってしまいました。


以下コードのgroupValueに設定しているselectedをクラス変数にしても、事象は同じく、何個でも選択出来る状態に。
※クラス変数にするということは、Radioボタンを幾つ作成しても、その中から一つしか選択できなくなるはず
```
// コードは「リスト」の中に作成しているRadioListTileのリスト
〜略〜
Container(
    height: choices.length * 45,
    child: ListView.builder(
        physics: const NeverScrollableScrollPhysics(),
        itemCount: choices.length + 1,
        itemBuilder: (context, index) {
          if (index == 0) {
            return Container();
          }
          return StatefulBuilder(
            builder: (context, setState) {
              return Row(
                children: [
                  Expanded(
                    child: Container(
                      height: 40,
                      child: RadioListTile<int>(
                        title: Text(
                          questionModel.choice[index].toString(),
                          style: TextStyle(fontSize: 14),),
                        value: index,
                        groupValue: selectedItem, // これをグループごとに一意に設定
                        onChanged: (value) {
                          setState(() {
                            selectedItem = value!;
                          });
                        },
                      ),
                    ),
                    〜略〜
```

### 解決方法
onChangeで適当なメソッドを呼び出し、その中でsetStateする
```

void test(){
    setState();
}

RadioListTile<int>(
〜略〜
    onChanged: (value) {
        selectedItem=value!;
        test();
    }

```


原因は断言できないため、ここでは記載しませんが
あくまで推測で、描画の対象かと考えています。
この辺は時間がある時に深く調査しようと考えています。

8時間悩んであっけなく解決した問題でした。。

まだ未熟なため、間違っている点があればご教示おねがいします。
Nuxt.jsで外部のURLからイメージを表示する(仮?)方法備忘録

# 前提条件

以下のサイトを参考に作ったが、エラーになった。（module.exportsに domain挿入）

https://chaika.hatenablog.com/entry/2021/07/20/083000


# したこと

以下の説明を参考に、srcにURLを入れるのではなく、loader引数にURLを返す関数を入れる。
引数でsrcを利用できるので利用した方がおそらく適切。(外部イメージ名がsrcと違っても動いたので例の表示はこれにしています)

https://nextjs.org/docs/api-reference/next/image#loader

```js:~~.js
<Image
    loader={()=>"https://example.com/image.png"}
    width="400"
    height="350"
    src="me.png"
    alt="no image" />
```

---
※ もっと適切な方法があるかもしれないので注意して利用してください。
基本情報技術者試験を2か月で取りに行く男の記録

## 知識も時間もない！だけど絶対取る
はじめまして。ただの学生です。
<br>遅ればせながらこの度22年度下期試験の対策を開始しましたので、備忘録も兼ねていくらか投稿していくことにしました。  
<br>プログラミング知識はほぼゼロ！なので主に午後試験の対策を書いていくことになると思います。
（ゼミでR、それ以外はC#やPythonを触ったことがある程度です。Progateの初学者コースだけやったみたいなイメージ。）
<br>出来るだけ毎日、学んだことを挙げていければいいなと思ってます。
<br>初投稿なので細かい話はナシにして、とりあえず使用文献を紹介します。
## **午前試験対策**
- イメージ&クレバー方式でよくわかる 栢木先生の基本情報技術者教室（技術評論社）
　∟おすすめ書籍としてよく上がっていたので購入。好きなのでいいと思う。
- 基本情報技術者過去問道場（[基本情報技術者試験ドットコム](https://www.fe-siken.com/fekakomon.php)）
　∟Webで手軽に演習できる！
## **午後試験対策**
- うかる！基本情報技術者 午後・アルゴリズム編（日本経済新聞出版）
　∟プログラミングのイメージがつきやすくなる！午前ぽさもあるので、並行して使う。
- 徹底攻略 基本情報技術者の午後対策 Python編（インプレス）
　<small>∟今回はPythonを用いての学習のため、まさにメイン教科書だろう。
***
以上の4つを使っていきます！午前は計算問題などちょっと面倒だな、苦手だなと個人的に思うところを載せるだけにします。
<br>暗記の方が重要そうだし。
<br>今日はこんなところで失礼します。ではまた～。
画像から深度を推定するMiDaS

# 画像から深度マップを取得したい

特別なカメラやセンサーやステレオ画像なしで、シンプルに一枚の画像から深度マップを得たい。

# Monocular Depth Estimation　で取得できる。
Monocular Depth Estimation機械学習モデルMiDaSで、単一画像から深度を取得できる。

https://github.com/isl-org/MiDaS

![pexels-cottonbro-6853517.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/5e64b551-b128-f130-0d4e-fd85c3488ce7.jpeg) ![r (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/cc212b86-376c-2d70-cd84-d93967fbb353.png)
モデルの初期化。

```python
import torch
model_type = "MiDaS_small"
midas = torch.hub.load("intel-isl/MiDaS", model_type)
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
midas.to(device)
midas.eval()
```

推論。

```python
img = cv2.imread("pexels-pixabay-164634.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

input_batch = transform(img).to(device)
with torch.no_grad():
    prediction = midas(input_batch)

    prediction = torch.nn.functional.interpolate(
        prediction.unsqueeze(1),
        size=img.shape[:2],
        mode="bicubic",
        align_corners=False,
    ).squeeze()

depth = prediction.cpu().numpy()

depth_min = depth.min()
depth_max = depth.max()

max_val = 255

if depth_max - depth_min > np.finfo("float").eps:
    out = max_val * (depth - depth_min) / (depth_max - depth_min)
else:
    out = np.zeros(depth.shape, dtype=depth.type)

cv2.imwrite(path + ".png", out.astype("uint8"))
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
git commitしてもlint-stageしても Unexpected Identifierと怒られる

## 簡単に結論

Node.jsのバージョンが古くてeslintが怒っていた

下記のコマンドでNode.jsをアップデートしたら解決しました！
```bash
sudo apt update && sudo apt install nodejs -y && sudo npm install n -g && sudo n stable && sudo apt purge -y nodejs npm && sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y
```

## 経緯

1. 開発途中でPCを買い替えたので、既にeslintやprettier、simple-git-hooks、lint-staged等の初期設定が終わっているGitレポジトリをクローンすることになりました
    <br/>

1. そんな訳で早速下記のコマンドを走らせて準備を終わらせる

    ```bash
    git clone https://github.com/foooooooo/hogehoge.git
    cd hogehoge
    npm ci && npx simple-git-hooks
    ```


    :::note info
    コマンドの簡単な解説
    - ```npm ci```
        - バージョンの縛りが緩いpackage.jsonを使ってパッケージをインストールする```npm i```若しくは```npm install```ではなく、パッケージのバージョンを細かく指定してあるpackage-lock.json を使ってパッケージをインストールする
    - ```npx simple-git-hooks```
        - package.jsonにsimple-git-hooksの設定がしてあるなら、その設定を元に /.git/hooks/ ディレクトリを作成し、設定通りの挙動が行われるようになる 
    - ```npx lint-staged```(後で出てくるコマンド)
        - package.jsonにlint-stagedの設定がしてあるなら、その設定を元にcommitする前のファイル、つまりはstageされているファイルに対して設定されたコマンドを実行する
        - 殆どの場合はeslintやprettier等のlinterやformatterを実行させる
    - ```npx eslint .```(後で出てくるコマンド)
        - eslintを現在地のディレクトリに対して実行する
        :::


    <br/>


3. 初期設定が終わったけれど、一応simple-git-hooksやlint-stagedの設定がちゃんと行われているか確認しておくか！

    ```bash
    npx lint-staged
    # => Unexpected Identifer というエラーが出る
    ```
    ?????????????????????????

    何故？
    これはlint-stagedがおかしいということ？

    

    ```bash
    git commit -m "commit test"
    # => Unexpected Identifer というエラーが出る
    ```
    **?????????????????????????**

    訳が分からないぞ
    そもそもエラー文が`Unexpected Identifer`、直訳して「予期しない識別子」だけで情報量が少なすぎる

    `Unexpected Identifer`というエラー文をsimple-git-hooksやlint-staged、eslintなどのワードと一緒に調べても解答っぽい情報に全く引っ掛からないし、どうすればいいんだ……!?

## 結論

**eslintが怒っていた**

```bash
npx eslint .
# =>typeerror: module.createrequire is not a function...というエラーが出る
```

調べてみると、2022/9/18現在の最新バージョンであるeslint8.23.1がサポートしているnodejsのバージョンは
**^12.22.0, ^14.17.0, or >=16.0.0** でした

[参考資料としてeslintのレポジトリ](https://github.com/eslint/eslint#installation-and-usage)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2402457/7d1aaee5-383e-6709-8fa5-460fae0fe968.png)

<br/>

一方、`apt install nodejs`でインストールされるnode.jsのバージョンは2022/9/18現在**10.19**

思いっきりサポート対象外!!!!!!!!!!!

そりゃあ怒られる!!!!
<br/>

そんな訳で下記のコマンドでNode.jsを最新のものに更新する [参考](https://qiita.com/seibe/items/36cef7df85fe2cefa3ea)
```bash
sudo apt update && sudo apt install nodejs -y && sudo npm install n -g && sudo n stable && sudo apt purge -y nodejs npm && sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y
```

これで上手くいきました!!!

## 参考資料
https://qiita.com/riversun/items/b7b67ec1772ecb0ba74a

https://qiita.com/seibe/items/36cef7df85fe2cefa3ea
Maximum call stack size exceeded Errorに綺麗にハマったのでgetter/setterと_についてを書く。

最近ちょっとJavascriptに触れていてgetter/setterをいじっていたら`Maximum call stack size exceeded Error`にハマったのだが、綺麗にハマりすぎたので記事にしようと思う。

## ハマってみる
まずはハマってみることが大切だ。
適当にインスタンスプロパティnumが10を超えたら文字列になる性質を付与してみる。

```javascript
class beStringUpper10{
	constructor(num){
		this.num = num;
	}
	set num(val){
		if (val > 10) this.num = String(val);
		else this.num = Number(val);
	}
}

let hoge = new beStringUpper10(0);
//数字だといいな
hoge.num = 1;
console.log(hoge.num)
//文字列だといいな
unko.num = 11;
console.log(hoge.num)

//Uncaught RangeError: Maximum call stack size exceeded

```
ええ！なんでっ!と驚く必要はない。
単に
```javascript
class beStringUpper10{
	constructor(num){
		this.num = num;
	}
    //2 numにアクセスしたので呼び出されたセットした関数が呼び出される。
    //5 numにアクセスしたので呼び出されたセットした関数が呼び出される。...
	set num(val){
                      //3 11以上は文字列に変換
                      //4 numにアクセスした。
		if (val > 10) this.num = String(val);
        //3 それ以外は数値に変換
        //4 numにアクセスした。
		else this.num = Number(val);
	}
}

let hoge = new beStringUpper10(0);
//1 hoge.numにアクセスした。
hoge.num = 1;
console.log(hoge.num)
hoge.num = 11;
console.log(hoge.num)

```
wow!これじゃあ無限ループになっちゃう！
コールスタックが悲鳴をあげても仕方ないな！

## じゃあ_を使ってみる。
```javascript
class beStringUpper10{
	constructor(num){
		this._num = num;
	}
	set num(val){
		if (val > 10) this._num = String(val);
		else this._num = Number(val);
	}
}

let hoge = new beStringUpper10(0);
hoge.num = 11;
console.log(typeof hoge._num);//string

```
むうこれはめんどくさい...

## getを使ってみる。
改造改造...

```javascript
class beStringUpper10{
	constructor(num){
		this._num = num;
	}
    get num(){
        return this._num;
    }
	set num(val){
		if (val > 10) this._num = String(val);
		else this._num = Number(val);
	}
}

let hoge = new beStringUpper10(0);
hoge.num = 11;
console.log(typeof hoge.num);//string
hoge.num = 1;
console.log(typeof hoge.num);//number
hoge.num = 13;
console.log(typeof hoge.num);//string

```

うむいい感じだ。

## 最後に
ではまたね~

## 参照
https://stackoverflow.com/questions/37502163/getter-setter-maximum-call-stack-size-exceeded-error
rails apiでの複数の値をmapで回してcreateアクションでDBへ保存しようとするとAbstractController::DoubleRenderErrorで苦しめられた話

はじめに
--
reactで配列を使って作成した値を、一気にrails apiに送ってcreateアクションで保存をしたいと考えていました。
ですが、AbstractController::DoubleRenderErrorを解消することに時間がかかったので、備忘録として残そうと思います。
深夜テンションで、雑に文章を書いちゃってる部分もあるかもしれないので、後で元気がある時に確認して必要があれば修正しようと思います。

どのような記述をしてエラーが起きたか
--

データやモデル名やカラム名は少しいじってますが、下記のような値がrails apiが来ているとします。

~~~
Parameters: {"_json"=>[
{"quiz_name"=>"問1", "quiz_status"=>"answered"},
{"quiz_name"=>"問2", "quiz_status"=>"answered"},
{"quiz_name"=>"問3", "quiz_status"=>"answered"}], 
"quiz"=>{}}
~~~

最初は下記のように記述をしていました。
自分の考えだと、mapで一周するごとにrenderでフロント側にjsonを返してくれるからそのデータを使ってあれこれやろうと考えていました。

~~~ruby
def create
    params.require(:_json).map do |param|
      quiz = Quiz.new(param.permit(:quiz_name, :quiz_status).to_h)
      if quiz.save
        render json: { status: 'SUCCESS', data: quiz }
      else
        render json: quiz.errors
        return
      end
    end
  end
~~~

すると、下記のようなエラーが出て、DBへの保存も途中で失敗しフロント側にデータが返ってきませんでした。
~~~
AbstractController::DoubleRenderError 
(Render and/or redirect were called multiple times in this action. 
Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, 
so if you want to exit an action after redirecting, 
you need to do something like "redirect_to(...) and return".):
~~~

renderを連続でしないでね、というエラーだと翻訳でしり、指示通りに and returnをrenderの後に入れるもそこでmapが終了して全てのデータが保存できませんでした。

renderは一回のアクションにつき一回のみだった
--
色々と記事を調べてみると"renderを2回してはいけない"という記事がたくさん出てきましたが、僕は"mapでしっかり１データづつ保存してるから連続してないじゃん！！"とネットの記事に心の中で反論していました。

ですが僕の勘違いでした。
1回のアクションで一度しか使ってはいけないということだったんですね。
2つデータがあれば、僕の記述だと1回のアクションで2回のrenderが発生してしっかり二重レンダリングをしていることになっていました。
エラーが出るのは当たり前だったようです。

なので配列を作ってデータを保存するたびにその配列に格納し、保存が終わった後に配列ごとreactへ返すように記述をしたところ、保存が成功してフロント側へjsonでデータを送れました。

~~~ruby
  def create
    quiz_hash = []
    params.require(:_json).map do |param|
      quiz_branch = Quiz.new(param.permit(:quiz_name, :quiz_status).to_h)
      if quiz.save
        quiz_hash.push(quiz)
      else
        render json: quiz.errors
        return
      end
    end
    render json: { status: 'SUCCESS', data: quiz_hash }
  end
~~~

このやり方が最適解ではないかと思いますが、昨日このエラーと格闘して、まだまだ知識不足の自分にとっては手強い相手であり、解決できた時は達成感がありました。
手を動かすのがやっぱり一番勉強になりますね。。

同じような箇所で詰まっている人は少ないかもしれませんが、誰かの助けになったら幸いです。
【Java】コンパイル時にpackage文に関するエラーが出た場合の対処法

## 環境
+ Microsoft Windows 10.0.22000.856
+ PowerShell 7.2.4
+ Java 18.0.2.1

## はじめに
Javaのpackage文を使用した際に、コンパイル（ `javac Main.java` ）で `エラー: シンボルを見つけられません` あるいは `error: cannot find symbol` のようなエラーが出た場合の対処法について説明する。

```:ディレクトリ構成
6-1/（カレントディレクトリ）
 ├ Kouhan.java（commentパッケージに所属する）
 ├ Main.java
 └ Zenhan.java（commentパッケージに所属する）
```
<details><summary>各ファイルの中身</summary>

[『スッキリわかるJava入門 第3版』](https://sukkiri.jp/books/sukkiri_java3)の練習問題6-1のコードを一部引用する。

```java:Main.java
import comment.Zenhan;

public class Main {
  public static void main(String[] args) throws Exception {
    Zenhan.doWarusa();
    Zenhan.doTogame();
    comment.Kouhan.callDeae();
    comment.Kouhan.showMondokoro();
  }
}
```

```java:Zenhan.java
package comment;

public class Zenhan {
  public static void doWarusa() {
    ...
  }
  public static void doTogame() {
    ...
  }
}
```

```java:Kouhan.java
package comment;

public class Kouhan {
  public static void callDeae() {
    ...
  }
  public static void showMondokoro() throws Exception {
    ...
  }
}
```

</details>

## 原因
**間違ったディレクトリ構成**がエラーの原因であった。パッケージに属したクラスファイルが読み込まれるには、**パッケージに対応した階層にフォルダを作成しクラスファイルを置く**必要がある。

```:正しいディレクトリ構成
6-1/（カレントディレクトリ）
 ├ comment/
 │  ├ Kouhan.java（commentパッケージに所属する）
 │  └ Zenhan.java（commentパッケージに所属する）
 └ Main.java
```

これで `javac Main.java` を実行すると問題なくコンパイルできる。
また、`java Main` で問題なく実行できる。

## 参考
https://style.potepan.com/articles/35841.html
【Git】記録

## Git
ファイルの変更履歴を記録・追跡するためのバージョン管理ツール

## 用語

##### リポジトリ
ファイルやディレクトリの状態や変更履歴が保存されるデータベース

##### ローカルリポジトリ
実際に作業を行うリポジトリ（自分のPC上で作られるリポジトリ）

##### リモートリポジトリ
ネットワーク先のリポジトリ（GitHub上で作られるリポジトリ）

##### ワークツリー
バージョン管理対象のファイルやディレクトリ

##### ステージングエリア / インデックス
ローカルリポジトリに登録するファイルやディレクトリのリスト

##### ステージング
ワークツリーの変更を加えたファイルをステージングエリアに追加すること (add)

##### コミット
Git上の1つ1つのバージョンのこと

##### コミットする
ステージングエリアのファイルをローカルリポジトリに登録すること (commit)

##### プッシュ
ローカルリポジトリに登録された情報をリモートリポジトリに追加すること(push)

##### クローン
リモートリポジトリをローカルリポジトリへコピーして保存すること(clone)

##### ブランチ
変更履歴を枝分かれさせる機能（複数人で開発する際に効果的）
デフォルトのブランチ名はmain(2020年10月以前はmaster)


## Git コマンド

##### 初期設定
```
$ git config --global user.name "XXXX"
$ git config --global user.email "XXXX@example.com"
```

##### 現在のフォルダ内にローカルリポジトリを作成し、ワークツリーとインデックスを用意する
```
$ cd [リポジトリを作成するディレクトリ]
$ git init
```

##### 新規追加や変更されたファイルを選択し、ステージさせる
```
# 全ファイル
$ git add .

# ファイルを指定
$ git add [ファイル名]

# ディレクトリを指定
$ git add [ディレクトリ名]
```

##### ステージされた変更をコミットする
```
$ git commit

$ git commit -m "メッセージ"
```

##### ローカルリポジトリにgithubに作成されたリモートリポジトリを登録する
```
$ git remote add リモートリポジトリ名 URL

# originというリモートリポジトリ名でURLのリモートリポジトリを登録
$ git remote add origin https://github.com/github-username/repository
```

##### ローカルリポジトリのブランチ名をmainに変更する
```
$ git branch -M main
```

##### 登録したリモートリポジトリへプッシュして、ローカルでのコミットを反映させる
```
$ git push origin main
```

##### ローカルにリポジトリを作成し、リモートにプッシュする
```
$ git init
$ git add .
$ git commit -m "XXXX"
$ git remote add origin https://github.com/XXXX/XXXXXX.git
$ git branch -M main
$ git push origin main
```

##### リモートからクローンする
```
$ git clone https://github.com/XXXX/XXXXXX.git
```

##### リモートから変更を取得する
```
$ git pull
　or
$ git fetch
$ git merge origin/main
```

##### ワークツリーとインデックスの状況をファイル単位で確認する
```
$ git status
```

##### ワークツリーとインデックスを比較して、その差分を表示する
```
$ git diff
```

##### 過去のコミット履歴を確認する
```
$ git log
```
【自分用メモ】Linux作業前にやっておくべきこと。

Linuxでいくつか整備したいことを記載する。

<h2> Teratermマクロについて</h2>

* Teratermログを設定するには下記のURL
https://www.j-oosk.com/teraterm/logging/114/
&h_%Y%m%d_%H%M%S.log

<h2> セキュリティの独自設定について</h2>

Teratermログイン時のパスワードログインは基本的に第三者からの不正アクセス（総当たり攻撃等）されても影響のないよう独自に多段階認証を実現する。

* ログイン時のパスワード入力は基本的にはめんどいので、鍵認証設定し、
鍵認証ログインするTeratermマクロを作成しておく。

* 踏み台サーバは鍵認証設定する。
踏み台サーバは総当たり攻撃を受けないよう、鍵認証設定をするとともに定期的な鍵のローテーションを構築する。

* 踏み台サーバを立てて、サーバの鍵認証時に扱う鍵に対してパスワードを独自に設ける。
（具体的内容は企業秘密だが、例えば・・・）
    * k8sサーバならパスワード入力画面を表示し、パスワードを入力したら、
アクセス権限AAAキーを使う。
    * データスクレイピング用サーバならパスワード入力画面を表示し、パスワードを入力したら、アクセス権限BBBキーを使う。
Redshift Serverlessにタグ付けする

2022年9月現在、Redshift ServerlessにはAWS CLIを使用してのみタグを付与できる。

## 事前準備
AWS CLIを最新バージョンにする。
※`redshift-serverless`はCLIのバージョンが古いと使えない。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

## タグを付与できるリソース
* 名前空間
* ワークグループ

## コマンド
タグ関連で使用可能なオペレーションは以下の3つ

* TagResource(タグを付与する)
```
aws redshift-serverless tag-resource --resource-arn 【名前空間 or ワークグループのarn】 --tags key="Name",value="test"
```

* UntagResource(タグを削除する)
```
aws redshift-serverless untag-resource --resource-arn 【名前空間 or ワークグループのarn】 --tag-keys Name
```

* ListTagsForResource(タグの一覧を表示する)
```
aws redshift-serverless list-tags-for-resource --resource-arn 【名前空間 or ワークグループのarn】
```

## 参考ページ
https://docs.aws.amazon.com/ja_jp/redshift/latest/mgmt/serverless-tagging-resources.html
ROS Noeticにcartographer_rosをインストールするメモ

# はじめに

https://google-cartographer-ros.readthedocs.io/en/latest/compilation.html

ROS Noeticに公式ドキュメント通りにcartographerをインストールしようとしたらエラーが出たのでインストール方法のメモ



# インストール

```bash
sudo apt-get update
sudo apt-get install -y python3-wstool python3-rosdep ninja-build stow
```


```bash
mkdir cartographer_ws
cd cartographer_ws
wstool init src
wstool merge -t src https://raw.githubusercontent.com/cartographer-project/cartographer_ros/master/cartographer_ros.rosinstall
wstool update -t src
```

```bash
sudo rosdep init
rosdep update
rosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} -y
```

ここで以下のようなエラーが出る

```bash
ERROR: the following packages/stacks could not have their rosdep keys resolved
to system dependencies:
cartographer: [libabsl-dev] defined as "not available" for OS version [focal]
```

解決方法
```bash
vim ./src/cartographer/package.xml 
```

/src/cartographer/package.xml を編集して46行目の libabsl-dev の行をコメントアウトまたは削除する

```yaml:/src/cartographer/package.xml
  <depend>libboost-iostreams-dev</depend>
  <depend>eigen</depend>
  <!--depend>libabsl-dev</depend-->
  <depend>libcairo2-dev</depend>
```

再度実行
あとはドキュメント通りビルドするだけ

```bash
rosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} -y
src/cartographer/scripts/install_abseil.sh
catkin_make_isolated --install --use-ninja
```

# おわりに
Melodicだとapt install でcartographer_rosがインストールできるらしい（ROS2も同様）

https://qiita.com/MMM-lab/items/14e94f9d41ccca4e1c61

またcatkin buildでbuildしたい方はこちらを参照

https://qiita.com/Decwest/items/ac1a701a2217dd05e1fb


# おまけ

Dockerfile内でcartographerをインストールするコマンド
sedコマンドでファイルを編集して46行目を削除

```txt:Dockerfile
# Install Cartographer
RUN mkdir -p /root/cartographer_ws/src
RUN apt-get update && apt-get install -y python3-wstool python3-rosdep ninja-build stow
RUN cd /root/cartographer_ws && wstool init src && \
wstool merge -t src https://raw.githubusercontent.com/cartographer-project/cartographer_ros/master/cartographer_ros.rosinstall && \
wstool update -t src 
RUN rosdep init && rosdep update 
RUN cd /root/cartographer_ws && sed -i '46d' /root/cartographer_ws/src/cartographer/package.xml && rosdep install --from-paths src --ignore-src --rosdistro=noetic -y
RUN cd /root/cartographer_ws && src/cartographer/scripts/install_abseil.sh 
RUN /bin/bash -c "cd /root/cartographer_ws &&  source /opt/ros/noetic/setup.bash &&  catkin_make_isolated --install --use-ninja -DPYTHON_EXECUTABLE=/usr/bin/python3"
```
# 参考

https://qiita.com/devemin/items/1723058cf3bac85aaa0b
Chrome拡張機能「requestly」の使い方|リダレクト設定

# 導入きっかけ
SAPのsnoteを表示する際に下記の2種類のページが表示されます。

>https://me.sap.com/notes/<note番号>
>https://launchpad.support.sap.com/#/notes/<note番号>

あまり違いがわからないですが、me.sap.comのドメインはインスタフェースは改善されているようです。
ただ、厄介なのがchromeで右クリック ->日本語翻訳が使えないところです。

launchpadの方は日本語翻訳ができるのでlaunchpadで毎回表示させるためにchromeのrequestly拡張機能追加してみました。

### 英語ではなく日本語のページを毎回表示したいといった方にも使えますよ。

## 拡張機能追加
https://chrome.google.com/webstore/detail/redirect-url-modify-heade/mdnleldcmiljblolnjhpnblkcekpdkpa

上記のリンクからchromeに追加してください。

追加すると、拡張機能とは思えないコンソール画面が表示されます。

下記のリンクからもコンソール表示すること可能です。
https://app.requestly.io/rules/my-rules


## リダイレクトの設定方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821335/5713dadf-d935-507f-b4d4-b578be328319.png)
ルール選択の際にredirect request ruleを選んでください。


選択/入力項目は下記の通りです。
```
URL
Wildcard
*://me.sap.com/notes/*
$1://launchpad.support.sap.com/#/notes/$2
```
右上のボタンで有効化ができます。save ruleもお忘れなく。


## リダイレクトしてみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821335/c35c7b26-6baf-a37c-0c02-0e5b0008190a.png)
同じ設定画面のしたにTest this ruleがありますので、そこにURLを追加するとリダイレクトチェックが行なえます。


### リダイレクト実行ログ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821335/288fd9e1-8553-54e2-d3e4-588fb3f329e2.png)

実行ログも確認できますよ。


### アカウント作らずに使用可能
アカウントを作らずに使用可能でした。どこにデータが格納されているのでしょうか、、

アカウント作らないとルール作成の制限がありますし、作成したルールも消えるかもしれないので作っておいたほうが無難です。

#### 余談
SAP関連の仕事している人、BASISの人はフォローお願いします。

https://qiita.com/96sapbasis
画像のグレースケール化とマスク処理

### はじめに
画像認識をする機械学習のモデルを自分で作ってみようと思い、その下準備として学習する画像を加工するスクリプトを書きました。

実施する内容は以下
・画像をグレースケールにして色の特徴を消す。
・画像上の画像認識に使用しない領域にマスク処理をする。

準備するもの
・マスクしたい箇所を黒で塗りつぶした画像(mask_file.jpg)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1359985/52226bcb-a0e0-dd7f-b4a8-9ab3eb5e2816.png" width=50%>

### やったこと

「C:\\XXXXXX\\XXXXXX\\」の下に加工したい画像を置いて、スクリプトを実行すると、
「C:\\YYYYYY\\YYYYYY\\」の下に加工後のファイルを出力します。
マスクファイルは「C:\\ZZZZZZ\\ZZZZZZ\\mask_file.jpg」に置きます。
パスは実行する環境に合わせて記載してください。

``` python
import cv2
import glob

input_dir = "C:\\XXXXXX\\XXXXXX\\*"
output_dir = "C:\\YYYYYY\\YYYYYY\\"
maskfile = "C:\\ZZZZZZ\\ZZZZZZ\\mask_file.jpg"

#ファイル名を取得
for path in glob.iglob(input_dir, recursive=True):
        
    try:
        img = cv2.imread(path)
        
        #グレースケール処理
        img_1 = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        
        #マスク処理
        maskimg = cv2.imread(maskfile)
        maskimg = cv2.cvtColor(maskimg, cv2.COLOR_RGB2GRAY)
        maskimg = cv2.resize(maskimg, img_1.shape[1::-1])
        img_2 = cv2.bitwise_and(img_1, maskimg)
        
        #加工後のファイルを保存
        output_path = output_dir + "mask_" + path.split("\\")[-1]       
        cv2.imwrite(output_path, img_2)
        
        print(output_path + " Finish!")
        
    except Exception as e:
        print("error! " + str(e))
```
このように画像を加工して出力されます。

※加工前
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1359985/2727ae33-0f28-08b1-57fa-110c253e574c.png" width=50%>

※加工後
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1359985/e7b65850-ed03-be58-760d-2fdfc265e1fe.png" width=50%>

### つまづいた所１
ファイルのパスを指定する際に日本語のファイルパスだとOpenCVでこんなエラーが出ます。
ファイルパスは英語にする必要があります。

``` 
error! 
OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-sn_xpupm\opencv\modules\imgproc\src\
color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'
```

### つまづいた所２
マスク画像をそのまま使おうとしたら配列のサイズが違ことでエラーになりました。

``` 
error! 
OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-sn_xpupm\opencv\modules\core\src\
arithm.cpp:214: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and type), 
nor 'array op scalar', nor 'scalar op array' in function 'cv::binary_op'
```

白黒の画像をグレーアウト処理を追加することで解決しました。
``` python
maskimg = cv2.cvtColor(maskimg, cv2.COLOR_RGB2GRAY) 
```
【背伸び初心者授業①】if文は横一列


背伸びしている初心者になろう！
本日はビックマックのようなif文をレタスだけにしていきます！


```
本日の内容①if文を1行に。
本日の内容②少し複雑なif文も1行に。
```
それではやっていきましょう！


## ① if文を1行に。

皆さんif文をどうやって書いていますか？
``` php:php
if($name == '木久扇') {
    return '黄色';
} else {
    return '黄色じゃない';
}
```
もし名前が「木久扇」だったら「黄色」を出力して、それ以外の名前だったら「黄色じゃない」と出力するようにしました。

このコードを1行で書くと...
```php:php
$result = ($name == '木久扇')? '黄色' : '黄色じゃない';
return $result;
```
2行になりましたね。でもこれでほぼ1行になりました！
これは世にいう`三項演算子`ですが、名前は覚えなくても生きていける気がします。
（私も先ほど調べました。）


## ② 少し複雑なif文も1行に。

なんだかいろんな条件で分けないといけない場合ありますよね。笑点もそうです。
木久扇師匠だけで笑点を成り立たせることは難しいでしょう。
なので司会の方を登場させます。

```php:php
if($name == '木久扇') {
    return '黄色';
} elseif($name == '昇太') {
    return 'ねずみ色';
} else {
    return '黄色、ねずみ色じゃない';
}
```
少し複雑になってコードを読むことが少し億劫になりませんでしたか？
このビックマックコードをチーズバーガーくらいスリムにしましょう。

```php:php
if($name == '木久扇') return '黄色';
if($name == '昇太') return 'ねずみ色';
return '黄色、ねずみ色じゃない';
```
とても認識もしやすくなりました！
これがチーズバーガーの力といったところでしょうか。
コードは座布団のように重ねていくのではなく、スリムにしていきたいですね！
馴染みのないView・モディファイアの機能まとめ[SwiftUI]

随時追加していきます
# View
## Divider()
区切り線を引く。
# モディファイア
## .offset()
viewの位置を指定する。
なお、その下に書いたモディファイアには位置指定は反映されない。

    .offset(x:10,y:10)
    .background(Color.orange) //これは位置移動しない
類似：.positon()
## .clipShape()
画像の形を定める。

    .clipShape(Circle()) //円の形
    .clipShape(Capsule()) //カプセル型の形
    .clipShape(Ellipse()) //楕円の形
類似：mark()
## .stroke()
図形の外縁を作る。

    .stroke(.white, lineWidth: 4)
## .overlay{}
Viewを重ね合わせる。

    .overlay {
                Circle().stroke(.white, lineWidth: 4)
            }
Cluster Creator Kit　のアップデートのする方法

●Unity、Cluster Creator Kitのアップデート手順の解説
https://note.com/cluster_official/n/n1781deed1e46

[Unity 2021.3.4f1](https://unity3d.com/get-unity/download/archive) をインストールしてください。

現在は、このバージョン出ないとアップロードできなかったりしますので気をつけてください。

準備ができたら次に色々何ができるのかをチェックしていきましょう
HTMLタグと要素と属性の違い

# 取り組んだこと・実践したこと
- ProgateのHTML&CSSを改めて終了
- Atom（テキストエディタ）を使用してHTMLを記述、ブラウザで擬似HPを表示させることに成功
- 開発者ツールを用いて、阿部寛公式HP、ナウル共和国HPのHTMLを参照
　→よくわからないタグ・要素を発見(meta , http-equiv)。調べる
　→http-equivはmetaタグの一つの要素である。Contentタイプを指定するを機能を持つ。
  　（Content-Type ≒ MIMEタイプ。前者は文字エンコードの指定も可能）
　→さらにインターネット通信の仕組みなども調べてみるも、知識が膨大すぎて沼る...
- ProgateのJSにも手を出してみる

# 所感と今後のタスク
わからない概念にぶつかると、ついつい調べてしまいます。
しかし、一つを理解したとしても、芋づる式にさらにわからない概念とぶつかります。
そうなるとそもそもの学習の手が止まり、効率が下がってしまうことに気づきました。
(http-equivが指定しているものが本当にContentタイプであるのか、結局この辺りは理解しきれていません)
なので、まずはProgateなどを活用して、手を動かす。0ベースの知識を30,40,50程度の理解度まで高めるという方式を取ろうと思います。
30レベルの理解度を90,100まで高めようとするのは後ほどで良いと判断しました。

なので、次回まではProgateなど用意されたコンテンツ内での学習に絞って勉強を進めようと思います。
また、JSはweb開発において必須であるとされるので、こちらを重点的に学んでいきます。


## 参考：タグ、要素と属性の違い
タグと要素が分かりづらいので、下記画像を引用し、理解を深めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819079/dff294a5-e3bf-1c30-d6b4-777315927add.png)
（引用https://lvl-lvl.com/info/2016/07/06/post-1006/）



以下は要素と属性の違いです。
画像におけるh1と/h1を一括りにしたものをタグと呼ぶのでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819079/bf1d09d4-c3ee-9c66-45ba-eddd50ef9983.png)
(引用：https://so-zou.jp/web-app/tech/html/specification/element-attribute.htm)
eachの入れ子についての備忘録

今日も学んだことを忘れない為にメモします

### 入れ子でeach分を使用する際の方法
以下のように、果物の名前と値段が入った配列があり
```
fruits_price = [["apple", [200, 250, 220],[150,200,300]], ["orange", [100, 120, 80],[400,400]], ["melon", [1200, 1500],[500,500,500]]]
```

以下のように果物の名前とそれぞれの合計額が出力されるコードを記述する
```
appleの合計金額は670円です
orangeの合計金額は300円です
melonの合計金額は2700円です
```

### 記述内容
```
fruits_price = [["apple", [200, 250, 220],[150,200,300]], ["orange", [100, 120, 80],[400,400]], ["melon", [1200, 1500],[500,500,500]]]

fruits_price.each do |fruit|
  sum = 0
  fruit[1].each do |price|
    sum += price
  end
  puts "#{fruit[0]}の合計金額は#{sum}円です"
end
```

### each分の内容
eachメソッドを使用して変数fruits_priceから[["apple", [200, 250, 220],[150,200,300]]を取り出してブロック変数fruitに代入する。

sum = 0は合計金額を入れるために記述。

添字1番目の合計金額が知りたいのでfruit[1]に対してeachメソッドを使用し（添字2番目の合計金額が知りたいならfruit[２]とする）ブロック変数priceに代入。

sum += priceで添字１番の値を一つずつ取り出しながら自己代入していく。
```
sum = 0
sum = 0 + 200 
sum = 200 + 250
sum = 450 + 220
sum = 670
```

"#{fruit[0]}の合計金額は#{sum}円です"のfruit[0]には果物の名前、sumには合計金額がそれぞれ出力される。



以上がeachの入れ子についての備忘録になります。
【初心者備忘録】関数を作るときは動詞から

いつも関数の命名に悩んでしまうのですが、今回はそのことではなく。


今までも無意識のうちにそうやってきてはいたのだけれど、いざ言われてみたら新鮮に感じたのでここに備忘録も兼ね、残します。
### 「関数を作るときは動詞から」

```
function creatMember() {

}
```


胸に刻みます。
ActiveStorage に保存した画像のサイズを取得する

ActiveStorage をセットアップ後、

```ruby
class User < ApplicationRecord
  has_one_attached :avatarend
end
```

のように、モデルを定義して、

```ruby
user.avatar.attach(params[:avatar])
```

のように、ファイルを添付すると、

```ruby
user.avatar.metadata[:width]
user.avatar.metadata[:height]
```

で、幅と高さが取れます。

# 必要なもの

- [libvips](https://github.com/libvips/libvips)
    - `ImageMagick` より `libvips` の方が早いそうなので
- [ruby-vips](https://github.com/libvips/ruby-vips)
    - 画像サイズをとるだけだとこれだけで十分
    - 画像のリサイズとかする場合には、[image_processing](https://github.com/janko/image_processing) も要りそう

# いつサイズが測られるのか？

ファイルアップロード時に解析されるそうです。
ただ、触ってみた感じ若干ラグがありそうなので、以下のように使う前に明に分析させた方が良さそう。

```ruby
user.avatar.analyze unless user.avatar.analyzed
```

# 参考

すべて、ここに書いてます！

https://railsguides.jp/active_storage_overview.html#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E8%A7%A3%E6%9E%90%E3%81%99%E3%82%8B
CloudFormationでポリシーを作成するとパラメータの末尾に:rootがついてしまう

# はじめに

久しぶりにCloudFormationを使ってIaCに挑戦していたところ、作成したいリソース通りにならないという問題が発生したためまとめます

おそらく他の記事にもなかったため、つまずくと時間がかかるかと思いますので誰かの役に立てば嬉しいです

# 問題

S3のポリシーをCloudFormationで以下のように作成しました

```yml:s3.yml
  S3BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket:
        Ref: S3Bucket
      PolicyDocument:
        Statement:
          - Action:
              - "s3:ListBucket"
            Effect: "Allow"
            Resource:
              Fn::Sub: "arn:aws:s3:::${BucketName}"
            Principal:
              AWS: !Ref CodeBuildRole
```

そして、AWSで作成したS3のポリシーを確認すると以下のようになっていました

```
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "767555320:root" # なぜかrootがついている
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::kitlab-test-s3"
        }
    ]
}
```

`767555320`はダミーでパラメータに設定した値です
そのあとになぜか「:root」という文字が付与されていました

# 解決方法

これはパラメータとして渡している値が問題でした
`Principal`には`ARN`を渡さないといけないので、もしARNの形式でない文字列が渡されていると省略されているであろう`:root`を自動的に付与する仕組みのようでした

なので以下のコードでCLIを叩いてS3を作成するようにしたところうまくいくようになりました

```
$ aws cloudformation create-stack \
--stack-name s3-test \
--template-body file://./cloudformation/s3.yml \
--parameters \
ParameterKey=CodeBuildRole,ParameterValue=arn:aws:iam::7675555555:role/service-role/sample
(以下省略)
```

```
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::7675555555:role/service-role/sample"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::s3-test"
        }
    ]
}
```

# おわりに

この仕様が調べた感じではどこにも載っていなかったので解決までに時間がかかりました
ダミーの値でリソース作成しないほうがよさそうです
【Nginx Proxy Manager】まだNginxやLet's Encryptの設定をCUIで頑張ってるの？

[Nginx Proxy Manager](https://nginxproxymanager.com/)というOSSを紹介します。これはNginxのリバースプロキシの設定やLet's Encryptの設定をブラウザからいい感じのGUIでとても簡単に行うことができるソフトです。ホスト名やプロキシ先を入力しポチポチボタンを押していくだけでHTTPSに対応したバーチャルホストのサイトを追加できます。

# 機能
✅ 以下の項目をブラウザの管理画面から管理可能
- ホスト名ベースのリバースプロキシ
- パスベースのリバースプロキシ
- ホスト名ベースのHTTPリダイレクト
- TCP/UDP プロキシ
- Let's Encryptを使ったTLS化
    - `http://`から`https://`へのリダイレクトや[HSTS](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Strict-Transport-Security)の設定も可能
- HTTPのBasic認証やIPアドレスを用いたアクセス制御
- GUIに設定がない場合、カスタムのNginxの設定をテキストでGUI上から追加できる
- 設定等の変更ログを見れる

✅ その他の特徴
- 公式にDockerイメージあり

❌ できないこと
- サイトのコンテンツのホスト（あくまでプロキシしかできない）
- GUIを使ってのHTTPヘッダーの追加
    - カスタムのNginxの設定をテキストで書く機能で追加することは可能

# 使用イメージ
使用感を伝えるためにセットアップの手順を大雑把に示します。詳しい使い方は
[公式サイト](https://nginxproxymanager.com/)を参照するか、実際にやってみればわかります。画面を立ち上げてしまえばドキュメントを読まなくても使い方がわかるのがGUIのいいところですね。

## 1. インストール
Dockerを使えます。以下の`docker-compose.yaml`ファイルを作成。

```yml:docker-compose.yaml
version: "3"
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
```

以下のコマンドで起動。

```console
$ docker compose up -d
```

## 2. 管理画面へアクセス
ブラウザで81番ポートにアクセスすると管理画面が開きます。初回起動時は以下のメールアドレスとパスワードを入力してログイン、その後メールアドレスとパスワードを変えるように求められるので変えます。

```
Email:    admin@example.com
Password: changeme
```

すると以下のような画面になります（「1 Proxy Hosts」になっているのは撮影の都合で本来は「0 Proxy Hosts」です。）。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/269d8bb3-a130-dd48-2628-32c30a8a46d1.png)

## 3. リバースプロキシ設定
リバースプロキシを設定してみます。80番（HTTP）または443番（HTTPS）ポートで待ち受けたリクエストをホスト名等に応じてプロキシします。

1. 上部のメニューを「Hosts」、「Proxy Hosts」の順にクリック。
2. 「Add Proxy Host」をクリックすると以下のようなダイアログが出るので、ここで対象のホスト名、プロキシ先等を指定できます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/cde0e1b0-ef83-6b50-e31c-401a23c3b5d1.png)

3. ダイアログ上部のタブで「Custom Location」を選択するとパスベースでプロキシ先を決められます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/acf0a294-5375-d4d9-0c2b-28a6c95d2056.png)

4. 同じくタブで「SSL」を選択するとLet's Encryptを使ったTLS化の設定ができます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/7d142116-582a-b981-7b5c-3074174bcfae.png)

5. 下部の「Save」ボタンを押すとプロキシ先が追加され、このDockerコンテナの80または443番ポートにアクセスすると設定に応じてプロキシされます。TLSの設定をしていた場合は自動的にLet's Encryptで証明書を取得しウェブサーバーに設定してくれます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/8f2ed9f3-ba79-3f39-a60e-d096f4e7274d.png)

複数サイトある場合は上の手順を繰り返して何個でもサイトを追加できます。

## 4. 他にも色々できるよ
HTTPのBasic認証やIPアドレスを用いたアクセス制御、カスタムのNginx設定などもGUIから簡単にできます。

# あとがき
CUIでやっていた面倒なNginxやLet's Encryptの設定をGUIで簡単に行えるので便利です。GUIのデザインもいい感じなので、趣味用や実験用に色々なセルフホストのウェブアプリを立てたくなりますね。
AWS License Manager とは

## 勉強前イメージ

ライセンス管理するやつ？
でもどんな？

## 調査

### AWS License Manager とは

ソフトウェアライセンスを管理するサービスで、ライセンスを管理することでライセンス違反を防ぐことができます。
MicrosoftやOracle、IBMなど提供するソフトウェアのライセンスをAWSとオンプレを一元管理することができます。

ソフトウェアを利用する際はライセンスに則った方法で使用する必要がありますが
いろんなソフトウェアを利用していると管理が難しくなったりすることがあり、ライセンス違反を行ってしまうと思わぬ損害が発生する可能性があります。
その時に AWS License Manager を利用することで一元管理を行いライセンス違反を防ぎます。
また使用していないライセンス等あれば移行する際に減らしたりしてコスト削減にもなります。

また、License Manager自体の利用には費用はかかりません。

## 勉強後イメージ

なんとなく思うようなライセンスだった。
ただ、自分で設定した○○アプリケーションのライセンスも自由に設定できると思ったけどそんなもんではなかったか。

## 参考

- [AWS License Manager とは？](https://www.acrovision.jp/service/aws/?p=2518)
Next.js (typescript) で S3 にファイルをアップロードする API を作る

## 色々面倒だった

React.js で画像をアップロードしたかったが、S3 のクレデンシャル情報は隠匿したかったので、アップロード自体は、サーバサイド（API）で行った。

やってみたら結構面倒臭かった。


## 環境

- React.js: 18.0.0
- Next.js: 12.1.6
- formidable: 2.0.1

React.js 側は axios で Next.js で実装した API を呼ぶ。
Next.js 側で受け取ってたら S3 にアップロードする。


## React 側

まず、File タイプを POST する場合、```"Content-Type": "multipart/form-data"``` でないと送れない。```json``` 形式だと送れない。

例えば、リクエストパラメータとして、```file: File```, ```type: string``` を送りたい場合、


```typescript
axios.post('/api/upload', {
    file: somefile,
    path: 'dir/'
  }, {
    headers: {
      'Content-Type': 'multipart/form-data',
    }
  });
```

などとしても送れそうだけど、送れない。FormData に append して送る。

```typescript
const params = new FormData();
params.append('file', somefile);
params.append('path', 'dir/');
axios.post('/api/upload', 
    params,
  {
    headers: {
      'Content-Type': 'multipart/form-data',
    }
  }
```


## Next 側

https://nextjs.org/docs/api-routes/request-helpers#custom-config

にあるように、まず、

```typescript
export const config = {
  api: {
    bodyParser: false,
  },
};
```

こうしてあげる必要がある。
なお、s3 にアップロードするのに必要な package は、```aws-sdk```, ```formidable```, ```fs``` なので、```@type/aws-sdk```, ```@types/formidable``` と共にインストールしておく。

```typescript
const form = formidable();
form.parse(req, async (err, fields, files: any) => {
  if (...) {
    // 必要なエラー処理
  }
  try {
    // S3 にアップロードする処理
  } catch (err) {
    // S3 アップロードに失敗した時の処理
  }
}
```

流れはこんな感じ。

React 側で送った file と path を POST しているが、```file``` は、```files.file``` に、FILE タイプ以外の ```path``` は、```fields.path``` に入る。file を hoge で送れば、files.hoge。



S3 に put する Body は、fs で。

```typescript
s3.putObject({
  ACL: 'public-read',
  Bucket: process.env.S3_BUCKET,
  Key: `${fields.path}${files.file.originalFilename}`,
  ContentType: files.file.minetype,
  Body: fs.createReadStream(files.file.filepath),
});
```

```files: any``` などとしておかないと、formidable の ```originalFilename``` とか ```filepath``` などのプロパティにアクセスしようとした時 Type Error になる。取得できるけど、build できない。any じゃなくて、厳密に ```files: formidable.Files``` としたいところだが、うまくいかない。



なお、File をアップロードするだけの API であれば、response は 201 が良いかと。


おしまい。
vscode+wslでpython/blackの有効化

# 前提

- vscode+wsl連携済みであること
- wslでpython3.8以上がインストールされていること(blackの動作要件)

# 結論

- vscodeがwslと連携した状態にする
    - vscode左下の接続の表示が、WSL: Ubuntuとなっている状態
    - なっていない場合、左下の接続マークをクリックし、wslでフォルダを開き直す
- vscodeにpython拡張機能(microsoft製)をインストール
- vscodeにblack拡張機能(microsoft製)をインストール
- setting.jsonに以下設定

```
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true
    }
```

# 不要なもの

- wsl側のpythonが利用されるのでwindows側にpythonはインストール不要
- wsl側にblackのインストールは不要
    - vscodeのblack拡張機能は、vscodeのパッケージ上にblackをインストールしてくれる

# トラブルシューティング

- なんか動かない気がしたときに、以下あたりを試していた
    - wsl側のblackのアンインストール
    - vscodeでblackをアンインストール/インストール
    - vscodeの再起動
- 適当にインデントをずらしてctrl+sをかけて動いてない気がしたんだけど、blackが対応しない部分のインデントをずらしてしまってたようなので、実はトラシューの途中で動いてたかもしれない感
    - 事前にblackの動作知ってると効率的そう(それか複数のパターンでインデントわざと間違えておくなど)

# 余談

- wsl, ローカルでちゃちゃっとLinuxが動いて最高なんだけど(Windows側にあれこれGUIでいれる必要がないし)、vscode+wslでパッケージが動かないとかwsl関連したトラブル起きると解決に一苦労
- 今回の場合も、windows+vscode+python+blackくらいまでは情報探しやすいが、wslが加わると探しづらいし、情報が少ないし、Linuxのトラシューが追加されて大変