OmniAICreator/Qiita-1.07M huggingface dataset:
2023年、CtoCプロダクトの改善、ぶっちゃけ失敗したよって話

この記事は [株式会社うるる（ULURU） Advent Calendar 2023 の8日目](https://qiita.com/advent-calendar/2023/uluru)の記事です。

# はじめに
こんにちは、出張撮影サービスOurPhotoというサービスの開発マネージャーをしているdoueと申します。

私もそろそろ30歳になるのですが、次第に一年が過ぎるのが早く感じてきた年頃です。。。

今年もたくさんプロダクト改善に励んできましたが、失敗(もしくは失敗かわからない)した施策も多かったな〜
と、反省を込めて、振り返り記事を書こうと思います。

## サービスの前提
![スクリーンショット 2023-12-08 22.35.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73081/279ff783-047d-9a29-8d42-8e5efdc3fed4.png)

OurPhotoでは
「写真を撮ってもらいたい人」がフォトグラファーを選び、写真を撮影してもらう
というCtoCのサービスを提供しています。

特に七五三やお宮参りといった、お子様の記念日などで多くのユーザーに使っていただいています。

# 一年前：プロダクトの注力ポイントの再整理
約一年前、チームのマネージャー以上が集まり、「プロダクトを今後、どうしていくか」というテーマで合宿をし、各チームの目標設定(KPI)を行いました。

実際に開発チームでは、ざっくり以下のような課題に対する目標を設定しました。

* 依頼をしたけど、成約しなかった
* 成約したけど諸事情で撮影が行われなかった
* 依頼をしたい(もしくは悩んでいる)のに、フォトグラファーを選べなかった

こういった、依頼周りのユーザーの課題を解決していくことになります。

# この一年間で実際にやった施策

* SEO関連ページのコンテンツの見直し&CLSの改善
* 各種導線の改善や入れ替えを行い、ユーザーがCVにいきやすいように誘導
* メニューやCTAボタンの文言変更を行い、ユーザーがCVにいきやすいように誘導
* 購買意欲を促進するためのメールを増やしたり、シンプルテキストメールをHTMLメールに変えリッチなデザインに
* ユーザーにとって分かりにくい箇所のデザイン変更
* フォトグラファー向けの既存機能をリニューアル、機能追加
* 現状、収集できないデータを集めるための機能追加

ざっくり、カテゴライズすると上記のようなものになります。

※ユーザーの依頼周りのみを並べましたが、上記以外にもCS対応や、別プロジェクトの開発なども行なっています

# 効果的な施策が少なかった
こうして、実際にリリースされた施策を並べてみると
開発工数が少ない施策が大半(体感で9割くらい)を占めており、尚且つあまり成果が出ていないものが多いことに気づきました。

これにはいくつかの理由があり
* エンジニアが少なく、大きな工数をかけれなかった
* 目標（≒依頼の増加につながる施策）に対してポジティブな施策を優先していた
* 一方で、走り始めたばかりで確かな光明が見えなかったため、「小さなことでもたくさんトライしよう！」と決めていた
* 施策立案が追いつかず、すぐ仕様が作れるものを優先させながら開発チームが走っていた

そんな状態の中、チームが走っていたため
抜本的にユーザー体験を改善し、かつ目標にもポジティブな成果を上げるための施策の実行数が少なくなってしまっていました。
（＝場当たり的にできることばかりが優先されてしまった）

もっといえば
**UIを少し変えたところで、ユーザーは思ったほど喜んでくれない**し
工数をかけられないからといって、(自分が)優先順位付に日和っていたんだろうと思います。

ユーザーペインに対する根本的な課題であれば
開発が難しくても、しっかりと根本対処するべきだったわけなのです。

実際に、上記の施策の中でも、根本解決のために時間を使って練り上げた施策は
ユーザーからも良い評価が得られていると実感しています。

# 優先順位付けが超難しい
とはいっても、施策の優先順位を決めるような立場の皆さんは
日々、スピーディな意思決定を要求されるため
高い精度で優先順位を決めていくのは難しいと思います。
ぶっちゃけ、プロダクトマネージャーの勘とセンスでやることも多いのではないでしょうか？（もちろんROIを意識しながら）

現実的には、日々いろんなタスクが降ってきます。
* バグの発見と改修
* CS対応で依頼される改修や、調査依頼
* キャンペーンなどの開発対応
* この画面わかりづらい、どうしても直したい（という社内からの意見）

全て大事なことなので、置き去りにはできません。。。

# 選択と集中が必要だった
日々のタスクに忙殺されかけたとしても、プロダクトを本質的に改善するための時間も必ず確保していかないといけないです。

そのための時間が足りないならば、小さな問題は取捨選択しなければならなかったし
業務効率が悪ければ、業務改善もしないといけないんだと気づきました。
また、時間だけではなく、プロダクトの改善をするためには、とてつもない労力も必要です。
チーム内のいろんなメンバーに触れ、ユーザーにも会いに行ったり
ありとあらゆる手段を講じてしっかりと改善に向け、足を進めていかなければいけません。

**"今"やらなくて良いことは、勇気をもって捨てるべきだし、"今"集中しないといけないことを決めなければいけなかったのです。**

# もっと広い視野も必要
当然ながら
事業運営の理解、事業ドメインの理解や、プロダクトを取り巻くステークホルダーの理解...
それらも必要になります。

プロダクトには、その周りの至る所に課題があります。
それらを俯瞰して理解する力、知識、巻き込み力も必要だと感じました。

そういったものを全て総合して、最終的に優先順位にできれば一番良いのだと感じました。

# 最後に
いかがでしたでしょうか。
今回僕は、新米として一年間、プロダクトマネージャーという役割を持って自由に動かせてもらいましたが
蓋を開ければ自分はまだまだ至らないことだらけでした。
そんな気持ちでチームにも大変申し訳ない気持ちもあり
自戒を込めたつもりで、この記事を書いてみました。

少しでも「プロダクトをもっと良くしたい！」と思っているみなさんのためにもなれば幸いです。

p.s
この記事を書き終わって、明日から頑張ろう！と思いました
***
次回は3日後の、@hokutohagi 氏による記事をお楽しみにお待ちください！
【SwiftUI】自身(View)が親Viewのどこに位置しているかを取得する（iOS17）

# はじめに
タイトルでちゃんと伝わっているかわからないので記事の内容を見てください笑
(多分伝わってない)

# 解説
今回重要なのは`CoordinateSpaceProtocol`です。
これがiOS17で追加されました。

Viewのサイズや位置などの情報を座標空間に変換して、その空間に名前を付けておけるっぽい？です。
その座標空間情報を使って、呼び出し側のViewが座標空間のどの位置にいるのかを取得するのかな

詳しいことはよくわかりませんが、使ってみるとどのような動きができるのかよくわかります。

以下のサンプルは`VStack`に`container`という名前をつけて`VSTack`内の`Text`で表示しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a34e4cd3-0222-746d-3c44-96a1cf6d9c56.png" width="50%">

`Text`が`container`という名前の座標空間のどこに位置しているかを取得できていることがわかります。

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            GeometryReader { geometryProxy in
                let x = geometryProxy.frame(in: .named("container")).origin.x
                let y = geometryProxy.frame(in: .named("container")).origin.y
                Text("x: \(x), y: \(y)").background(.red)
            }
            .padding()
        }
        .coordinateSpace(.named("container"))
    }
}
```

### ScrollView内の複数コンテンツの位置をそれぞれ取得したい
それぞれのコンテンツを`GeometryReader`を囲むと取得することができました。
`GeometryReader`はサイズを指定しないと広がってしまうので等間隔で配置されてます

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/dd032be4-4930-74f8-4466-61c5e4b9a2da.png" width="50%">

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            GeometryReader { geometryProxy in
                let x = geometryProxy.frame(in: .named("container")).origin.x
                let y = geometryProxy.frame(in: .named("container")).origin.y
                Text("x: \(x), y: \(y)").background(.red)
            }
            .padding()
            
            GeometryReader { geometryProxy in
                let x = geometryProxy.frame(in: .named("container")).origin.x
                let y = geometryProxy.frame(in: .named("container")).origin.y
                Text("x: \(x), y: \(y)").background(.red)
            }
            .padding()
            
            GeometryReader { geometryProxy in
                let x = geometryProxy.frame(in: .named("container")).origin.x
                let y = geometryProxy.frame(in: .named("container")).origin.y
                Text("x: \(x), y: \(y)").background(.red)
            }
            .padding()
        }
    }
}
```

`GeometryReader`を上に持ってきてそれぞれ座標を取得しようとしても正しく取得できません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2a8e0dcf-8750-b5fe-4eb7-cad36effdfdf.png" width="50%">

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { geometryProxy in
            VStack {
                let x = geometryProxy.frame(in: .named("container")).origin.x
                let y = geometryProxy.frame(in: .named("container")).origin.y
                
                Text("x: \(x), y: \(y)").background(.red)
                
                Text("x: \(x), y: \(y)").background(.red)
                
                Text("x: \(x), y: \(y)").background(.red)
            }
            .padding()
        }
    }
}
```

# おわり
これはめっちゃ便利なのでは？

# 公式ドキュメント
https://developer.apple.com/documentation/SwiftUI/CoordinateSpaceProtocol
【目指せカンファレンス登壇】プロポーザルに何を書けば良いかわからない人のためのコツ

## はじめに
この記事は[misskey.dev ユーザー Advent Calendar 2023](https://adventar.org/calendars/9688)への投稿となります。

ここ1年ちょっとで3つの大きめなカンファレンスに登壇しました。  
登壇にあたりプロポーザルを書くときに気をつけたことを共有します  
本題だけ読みたい場合は[ここまでスキップ](#プロポーザルの記載内容)してください。

## TL;DR
- 聞いて欲しいこと/人を明確にする
- 実体験を話すことがわかるとなお良い
- 出す分にはタダなのでどんどん出そう

## 直近登壇したイベント
- [JJUG CCC 2022 Fall](https://ccc2022fall.java-users.jp/)
- [Kaigi on Rails 2023](https://kaigionrails.org/2023/)
- [JJUG CCC 2023 Fall](https://ccc2023fall.java-users.jp/)

**採択率：100%（3/3）**

## プロポーザルとは
カンファレンスでの発表を希望する人が主催者に提出するドキュメントです。
このドキュメントをもとに主催者側は発表者を選別します。

## プロポーザルの記載内容
ここからは実際に記載していく内容を提示します。

### 注意点
あくまで主観です。
主催者側からフォーマットや必須事項が提示されていることもあります。主催者側のフォーマットには必ず従いましょう。

### 基本的に記載する要素
- レベル感（前提知識）
- 聞いて欲しい人
- 目次
- 自分の経験を混ぜて話すセクション
- 参考ドキュメント

### レベル感（前提知識）
カンファレンスの参加者のレベルは千差万別です。
プロポーザルで書いた内容はそのままセッション詳細となるため、前提知識がどのくらい必要かは記載しておきます。
想像上の主催者側のお気持ち：カンファレンス内でレベル感はバラけさせたいので情報あると助かる

### 聞いて欲しい人
レベル感とやや被ります。
言い換えれば「このセッションで学べること」を明確にする箇所です。
（例）〇〇について詳しく知りたい人、〇〇の導入で詰まった人
想像上の主催者側のお気持ち：2トラック以上あると同じ時間に似た内容は避けたいので情報あると助かる

### 目次
具体的にどういう構成で何を話すか提示します。
プロポーザルを出す段階では曖昧な部分もあるかと思いますが、できるだけ具体的に書きたいところです。
想像上の主催者側のお気持ち：構成と話すこと、話さないことがわかって助かる

### 自分の経験を混ぜて話すセクション
通りやすくなるような気がするおまじない要素です。
「自分はこう使った結果どうなった」、「実際に〇〇を試してこう感じた」等の主語が自分になるところを組み込んでみてください。
すべてが新規性のあるセッションになる魔法です。
想像上の主催者側のお気持ち：本などで学べない観点があって助かる

### 参考ドキュメント
正直、プロポーザルを見る人は前述の目次だけ見ても全容の把握は難しいです。
例えば、「ブログに書いた内容を補足込みで話すセッション」であればブログのリンクやセッションの内容を構成する上で元となったものがあれば提示しておくと良いです。
一気に内容の解像度が上がります。
想像上の主催者側のお気持ち：詳細にまとまった内容あって話す内容が明確になって助かる

## あったら良い要素
そのほか書いている上であると便利だなと思った項目です。
- 採用したほうが良い理由

### 採用したほうが良い理由
例えば直近あったセキュリティインシデントに関連するセッションや新機能関連のセッションであれば、採用したほうが良い理由として、記載したほうが良いです。
つまるところ「〇〇という理由で関心が高まっている話題ですよ」というアピールです。

## 終わりに
ここまでの内容を見てわかるかと思いますが、プロポーザルを出した時点で話す内容は大方決まります。
むしろプロポーザルを書きながら決めていくことが多いです。

「想定する聴講者を考え、レベルをあわせながら伝えたいことを構成していく」
それがプロポーザルということです。（怪文書）

また、別の考え方として、自分がセッションを聞くときに「こんなことが書いてあると助かる」「ミスマッチを減らせそう」ということを書いておけば良いです。

いろいろ考えて書かなきゃいけないように記事にしてしまいましたが、出す分には自由ですし、この記載内容は絶対ではありません。
特定の人だけにしか見られないですし、軽い気持ちで皆さんもカンファレンス登壇を目指してどんどんプロポーザルを出してもらえると技術コミュニティが盛り上がっていくのではないかと思います。
MicroPython ドキュメンテーション和訳の進捗状況

# はじめに

[2018年のクリスマスイブに投稿した記事](https://qiita.com/inachi/items/83c31c588556b6990a2a)にて[私家版和訳](https://micropython-docs-ja.readthedocs.io/ja/latest/index.html)を公開しました。以後もだらだらと進めていて、未だ完訳に至っていないませんが、進捗状況について書いておきます。

# ライブラリリファレンス

* [Python 標準ライブラリとマイクロライブラリ](https://micropython-docs-ja.readthedocs.io/ja/latest/library/index.html#python-standard-libraries-and-micro-libraries)については、ひととおり訳を終え、最新にも追従できている状況です。
* [MicroPython 固有のライブラリ](https://micropython-docs-ja.readthedocs.io/ja/latest/library/index.html#micropython-specific-libraries)については、次のもの以外は訳を終えていて、最新にも追従できている状況です。
    * WM8960 -- 現状、私があまりこれに関心がないので、後回しになりがちです
* [ポート固有のライブラリ](https://micropython-docs-ja.readthedocs.io/ja/latest/library/index.html#port-specific-libraries)については、次のもの以外は訳を終えていて、最新にも追従できている状況です。
    * pyboard の CAN, USB_HID, USB_VCP クラス -- そのうちに
    * WiPy 固有のライブラリ　 -- よっぽどのモチベーションが湧かない限り、手つけないでしょう

# 言語リファレンス

* [MicroPython 言語と処理系](https://micropython-docs-ja.readthedocs.io/ja/latest/reference/index.html)については、次のもの以外は訳を終えていて、最新にも追従できている状況です。
    * ARMのThumb2インラインアセンブラ -- めんどうで手つけてない
    * pyboard.py　-- mpremote がある現状では、ほぼ意味のない章であるので手つけないでしょう
* [MicroPythonとCPythonの違い](https://micropython-docs-ja.readthedocs.io/ja/latest/genrst/index.html)については、個々のCPythonバージョンとの違い以外は訳しています。
* [MicroPython の内部](https://micropython-docs-ja.readthedocs.io/ja/latest/develop/index.html)については、ひととおり訳を終え、最新にも追従できている状況です。

# クイックリファレンス

* [pyboard 用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/pyboard/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [ESP8266 用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/esp8266/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [ESP32 用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/esp32/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [RP2 用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/rp2/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [i.MXRT ファミリー用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/mimxrt/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [Quick reference for the WiPy](https://micropython-docs-ja.readthedocs.io/ja/latest/wipy/quickref.html)については、よっぽどのモチベーションが湧かない限り、手つけないでしょう
* [UNIX および Windows ポートのクイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/unix/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [Zephyr ポートのクイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/zephyr/quickref.html)については、つい最近、訳を終えました。
* [Renesas RA 用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/renesas-ra/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。
* [SAMD21/SAMD51 ファミリー用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/samd/quickref.html)については、ひととおり訳を終え、最新にも追従できている状況です。

# おわりに

誤訳を見つけたら [GitHub](https://github.com/MinoruInachi/micropython/tree/doc-ja) の issues に報告してください。
gh ( GitHub CLI ) を Ubuntu にインストール

gh を使おうとしてコマンドを叩こうとしたら、


```
$ gh release list
コマンド 'gh' が見つかりません。次の方法でインストールできます:
sudo snap install gh       # version 2.6.0-15-g1a10fd5a, or
sudo apt  install gh       # version 2.4.0+dfsg1-2
sudo apt  install gitsome  # version 0.8.0+ds-6ubuntu1
他のバージョンについては 'snap info gh' を確認してください。
```

となった。

どれがいいかな?


gh をインストール

# 環境

- Ubuntu22.04
- チェック日 2023/12/8
  - 問題発生と追記：2023/12/9 


# github 公式


https://github.com/cli/cli/blob/trunk/docs/install_linux.md
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a12e8b01-eed8-88b0-22a1-e6b36eb6b443.png)

 によると、
 github によるオフィシャルパッケージレポジトリがあるらしい。
そして、そこからリンクされている release を見ると、 2.40.0 だった。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3fc80fde-52e6-c762-6938-3c69801d51a9.png)

Ubuntu パッケージは 2.4.0 だけど、あれ? snap は 2.6.0 ですね。

# Ubuntu パッケージをインストール

:::note warn 

2023/12/9 このやりかただと問題が発生しました。

「github公式パッケージをインストール」の項目を参照ください

:::


Ubuntu パッケージでも、バージョンが遅れてなかったので Ubuntu apt パッケージを使うことにしました。
```
$ sudo apt install gh
```
でインストールしました。

# github公式パッケージをインストール

Ubuntuパッケージを使っていたら、 release edit コマンドが使えない。
```
$ gh release edit pre0.3 --notes abcd
unknown flag: --notes

Usage:  gh release <command> [flags]

Available commands:
  create
  delete
  download
  list
  upload
  view
```

snap 版を使ったら
```
$ /snap/bin/gh release edit
unknown command "edit" for "gh release"

Usage:  gh release <command> [flags]

Available commands:
  create
  delete
  delete-asset
  download
  list
  upload
  view
```

 あれれー?

 ということで github 版をインストールしました。ubuntu パッケージ版、snap 版をアンインストールしてから上記のサイトの通り行います。

```
$ type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
$ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
```
コマンドを叩いてみる
```
$ gh release edit pre0.3 --notes abcd
https://github.com/nanbuwks/GeigerMap/releases/tag/pre0.3
```
うまくいきました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/54268396-cecb-98a4-d62a-8d8062759047.png)

公式バージョンは 2.40.0 でした。
原因はバージョンが古いということではないようです。

``` 
$ gh --version
gh version 2.40.0 (2023-12-07)
https://github.com/cli/cli/releases/tag/v2.40.0
```
reportlabでPDFを正しく合成できない！！！

この記事は，[Qiita全国学生対抗戦 Advent Calendar 2023 #3](https://qiita.com/advent-calendar/2023/student)13日目の記事です．
12日目の昨日は@sekky_grさんの[AutoHotkeyでXbox Game Barを常駐させるスクリプトを作った](https://qiita.com/sekky_gr/items/d936bebd63be2e284ad5)でした．

私が2日を溶かした，謎の不具合についてここで書いておこうと思います．

:::note info
初めての記事なので読みづらいと思います．
どうかご容赦を...
:::

# 宣伝！
私が部長を務める工学部のblog，「まっつーのコードライブラリ」にも同じ記事を掲載しています！
ぜひこちらから覗いてみてください！

https://nisho.tech/reportlab%e3%81%a7pdf%e3%82%92%e6%ad%a3%e3%81%97%e3%81%8f%e5%90%88%e6%88%90%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84%ef%bc%81%ef%bc%81%ef%bc%81/

# 出席停止の報告書に自動記入するweb app
本校では，コロナ関連(e.g. ワクチン接種, 自身の感染)の際には報告書を提出することになっています．この報告書，指定のテンプレがPDFなので軽く加筆するだけなのにスマホだけだとちょっとめんどくさいんですよね．
そこで，僕はこれをweb appで合成するようにしてみんなに~~使ってもらってチヤホヤされたいと~~楽をさせてあげたいと思ったわけです．

# なんかおかしいのがでてくる！！！
基本構成としては，
- web サーバ: Flask
- 記述する内容のみのpdfをreportlabで作成
- あとからテンプレと↑のpdfをpypdfで合成
みたいな感じにしました．Python使って色々やるのは初めてだったので不安でしたが，まあなんとかなるくらいの気持ちで行きましたね．
ところが，いざ動かしてみるとなんだかテンプレのpdfから90°回転した向きで合成されています．(問題作はすべて廃棄してしまったのでスクショもないっす....)
色々さがしてもなかなか治らぬこの問題，思わぬところに問題がありました．

# 結論
これは結局，**テンプレートのpdfに問題**がありました．このpdfはどうもスキャンしたもののようなのですが，
1. スキャナーで取り込む
1. そのpdfが横向きであることを取り込んだ人が確認
1. 何らかの編集ソフトで縦向きに変更し，アップロード
↑この過程で，表示上の向きとデータ上の向きが変わった？ようです．正体はよくわかりません．ただ，Adobeの仮想プリンターで出力したら，なぜか直りました．~~僕の2日間...~~
:::note info
だれか専門家の方教えてほしいです．
こんなこと起こるんでしょうか．
:::

## 最後に
結局，いい感じのホストがなかったので公開してないです...．
個人情報も含まれるのでローカルで処理するように改めてから，うまいこと公開したいですね．

駄文でしたが，最後まで読んでいただきありがとうございます！
14日目の明日は，@kurimochiさんの「Ubuntu 24.04LTS 開発速報2023年末版!!!!!! 第3回 フレーバーの新機能」です！
お楽しみに！
Web公開されているPower BIレポート集

[Power BIアドベントカレンダー 2023](https://qiita.com/advent-calendar/2023/powerbi)のシリーズ3を埋めなくてはいけない気がしたが、[それは正しかった](https://qiita.com/k_maki/items/4d762a79701cdcd300a4#comment-a40f6312d1b3cc4a755d)らしい。人生で初めて自分にニュータイプ特性を感じた（キュピーン！）。

https://qiita.com/advent-calendar/2023/powerbi


本投稿は、Power BIってすごいんだよと偉い人を説得したり、自身のレポート作成のヒントにしたりで役立ちそうなレポートを集めたもの。Power BI Desktopのインストール不要で見れるもの中心。

偉い人の説得も重要だけど、波が来たときのための準備は必要（JPPC2023でのタイガーさん発言より）。良いものを参考に、自分のレベル アップを目指そう！


# 実運用中のもの
意外と少ない。一般企業のものが無いのはなぜだ？

## デジタル庁、東京都、世田谷区
省庁や自治体のPower BIレポート公開が熱い　←MVP石川さんの投稿より

https://qiita.com/ishiayaya/items/1d25107c835ac9877066

## 東京都（追加）
都財政の見える化ボード

https://www.zaimu.metro.tokyo.lg.jp/zaisei/dashboard.html

「未来の東京」戦略　政策ダッシュボード

https://www.seisakukikaku.metro.tokyo.lg.jp/basic-plan/choki-plan/dashboard

## さいたま市
データ分析ツール集

https://www.city.saitama.jp/006/013/010/index.html

## 渋谷区
CITY DASHBOARD 渋谷区をデータで見る 

https://shibuya-data.jp/citydashboard/

## 財）スマート シティ インスティテュート
地域幸福度(Well-Being) 指標 ダッシュボード

https://www.sci-japan.or.jp/LWCI/index.html#about03

# サンプル
## MVP清水さん
Power BI 王子のレポート集

https://qiita.com/yugoes1021/items/e1ab631d0b6942508844

## MVP石川さん
いしかわのPower BIレポート集

https://qiita.com/ishiayaya/items/b91990bacddbedd07058

## ZEAL社
だれでもトイレのバリアフリー情報をPowerBIで可視化

https://www.zdh.co.jp/bi-online/opendata-20190901/

都道府県・市区町村のすがた

https://www.zdh.co.jp/bi-online/opendata-20190928/

## くらまね（Colorkrew社）
Power BI 導入支援・構築・コンサルティングのサンプル集

https://kuramane.colorkrew.com/service/power_bi/

## Power BI セミナー（一円マネジメント社？）
Power BIの活用事例

http://powerbiseminar.com/power-bi-%e3%82%bb%e3%83%9f%e3%83%8a%e3%83%bc/tokyobasic/#Power_BI-7


## Microsoftのコミュニティーサイト
Power BI forums > Galleries　←英語です

https://community.fabric.microsoft.com/t5/Themes-Gallery/bd-p/ThemesGallery

# その他
## Microsoft Learn
Power BI のサンプルを入手する　←Web公開されているわけではないけど

https://learn.microsoft.com/ja-jp/power-bi/create-reports/sample-datasets


## 神戸市
神戸市と日本マイクロソフトが包括連携協定を締結　←なおダッシュボードはTableau製（どうしてこうなった？）

https://news.microsoft.com/ja-jp/2020/06/04/200604-comprehensive-cooperation-agreement/
JPPC2023 Japan Power Platform Conference 2023 アプリ & サイト開発 (Application)

# JPPC2023 Japan Power Platform Conference 2023 
12/7 -8 の2日間にわたって開催されたJPPC2023に
AP09 カスタムページ・モダンコマンドバーで登壇させていただきました！


https://powerplatformconf.connpass.com/event/294851/

# 自分の登壇した記事は以下自ブログの方にも書きましたー！
よろしくお願いいたします。

https://youseibubu.com/apps/jppc2023_ap09/

※12/10 追記
# JPPC2023上に資料が集まっています！
→動画の公開は近日中とのことです！
ひとまずはめっちゃタメになる登壇資料をぜひ皆さんご確認くださいー！

https://powerplatformconf.connpass.com/event/294851/presentation/


# 以下ドクセル上のアプリケーション系の資料抜粋リンクです！
以下はドクセルに上がっていたAPセッション、Power Apps系の資料をご紹介します。
（Power Automate系、BI系のセッションは他でご紹介があると思うので割愛しております）
※12/9 岡田さんと向井さんのスライドを追加させていただきました

https://www.docswell.com/s/ai_yamasaki/5Q8QRY-2023-12-07-150349#p22

https://www.docswell.com/s/tanapandalove/KEN7EE-2023-12-07-174940#p34

https://www.docswell.com/s/NaoyaOkada/K8GD1X-2023-12-07-dynamics

https://www.docswell.com/s/rockfun/Z98DWL-2023-12-08-143735

https://www.docswell.com/s/TAKASHI_MASUMORI/5YW6EE-2023-12-08-114811

https://www.docswell.com/s/KumikoMukai_jp/KGX4GJ-JPPC_RB06

https://www.docswell.com/s/fworlddocs/57VDG7-2023-12-08-105902

https://www.docswell.com/s/yougears-lab/KNR2JV-20231208

https://www.docswell.com/s/yousei/5VVE6J-2023-12-08-125936

https://www.docswell.com/s/geekfujiwara/ZGX4LJ-jppc23-ai-builder-gpt-document-ocr

https://www.docswell.com/s/korune/ZP93MQ-PowerPlatform-ALM

https://www.docswell.com/s/KodamaJn/5W1YVQ-2023-12-08-173333


という、ドクセルを検索しただけの記事ですが、アプリ & サイト開発 (Application)以外に
Keynote, ランチセッション, スナックタイム と、RB自動化, ボット, RPA (Automation)　と、
データ・分析 & その他 (Analysis & Others)の４つに分かれた各セッションがあり、
それぞれ資料が上がっている（またはこの後追加される）と思うので是非そちらも併せて確認くださいー。
goでredis

# Goでredis
アドベントカレンダー8日目です。
redisを扱います。
## 環境を作る
```yml
version: '3'
services:
  golang:
    build: .
    tty: true
    volumes:
      - ./:/app/
    ports:
      - "1323:1323"
  mysql:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: golang
      MYSQL_USER: golang
      MYSQL_PASSWORD: golang
    restart: always
    ports:
      - "3310:3306"
    volumes:
      - ./mysql:/var/lib/mysql
  redis:
    image: "redis:latest"
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"
```

コンテナを起動
```bash
docker-compose up -d
```

### 接続確認
```bash
$ docker-compose exec redis sh
# redis-cli
127.0.0.1:6379>
```
よさそうです。

## goからredisを操作する
ライブラリは`go-redis`を使います。
https://github.com/redis/go-redis


プログラム本文
```bash
docker-compose exec golang go get github.com/go-redis/redis
```

```bash
mkdir app/day8/ && touch app/day8/main.go
```

```golang
package main

import (
	"fmt"

	"github.com/go-redis/redis"
)

type RedisAdapter struct {
	client *redis.Client
}

func NewRedisAdapter() *RedisAdapter {
	client := redis.NewClient(&redis.Options{
		Addr:     "redis:6379", // コンテナの名前:ポート番号
		Password: "",
		DB:       0,
	})

	_, err := client.Ping().Result()
	if err != nil {
		panic(err)
	}

	return &RedisAdapter{
		client: client,
	}
}

func (r *RedisAdapter) Set(key string, value string) error {
	err := r.client.Set(key, value, 0).Err()
	if err != nil {
		return err
	}
	return nil
}

func (r *RedisAdapter) Get(key string) (string, error) {
	val, err := r.client.Get(key).Result()
	if err != nil {
		return "", err
	}
	return val, nil
}

func main() {
	redisAdapter := NewRedisAdapter()

	err := redisAdapter.Set("key", "valueです")
	if err != nil {
		fmt.Println("Error setting value:", err)
	}

	value, err := redisAdapter.Get("key")
	if err != nil {
		fmt.Println("Error getting value:", err)
	} else {
		fmt.Println("Value:", value)
	}
}
```

プログラムを実行してみる
```bash
root@8f93343dfdb9:/app# go run app/day8/main.go
Value: valueです
```

`redis-cli`からも確認

```bash
$ docker-compose exec redis sh
# redis-cli
127.0.0.1:6379> keys *
1) "key"
127.0.0.1:6379> get key
"value\xe3\x81\xa7\xe3\x81\x99"
127.0.0.1:6379>
```
よさそうです。

## 最後に
これまで、httpサーバー、json、mysql等を扱ってきました。
明日は、これらを組み合わせることでwebアプリをガッツリ作ってみます。
SCSSからCSSネスティングに切り替えたい人に贈る3つの罠

今年も残すところあと1月を切り、CSSもこの1年でさらに進化を遂げましたね。

CSSは普段、SCSSを使ってコーディングしている方も多いますが、
CSSの進化により、SCSS不要論も今年チラチラ見られるようになりました。

本当にSCSSがなくても問題ないのか、新しいCSSネストについて調べてみました。

## CSSネストの基本
まずはCSSネストがなんなのかというおさらいをしておきましょう。

2つのクラスparentとchildがあり、parentより子の階層にchildクラスが含まれているときだけスタイルづけしたい時、普通のCSSだとこのように書きます。
``` css
.parent {
  min-height: 100dvh;
  width: 100%;
}
.parent .child {
  background: white;
}
```

二度、parentクラスの記述があり、面倒ですね。
それを、このように書いて、parentとchildの関係性をわかりやすくし、記述量を減らせるのがCSSネストになります。

``` css
.parent {
  min-height: 100dvh;
  width: 100%;

  .child {
    background: white;
  }
}
```

## CSSネストの罠
そんな便利なCSSネストですが、今までSCSSでのネスト構造に慣れていた人が
少し混乱してしまうかもしれない罠ポイントがあります。

### 詳細度の罠
CSSでのネストは傍目にはSCSSでのネストと同じように見えるのですが、
複数個の親要素を同時に記載した場合、動作が異なります。

例えば、あるクラスparent1やID codeの子要素になった時のtextクラスにスタイルを指定したい時、このようにネストで記述します。

``` css
.parent1, #code {
  font-size: 1.0rem;

  .text {
   color: green;
  }
}
```

``` html
<div class="parent1">
  <p class="text"></p>
</div>
```
SCSSの場合だと、 `.parent1 .text`と`#code .text`とそれぞれのセレクタをCSSに生成しますが、CSSの場合は`:is(.parent1, #code) .text`と同じように解釈します。

`:is()`は最近出てきた新しい擬似クラスです。
これは複数のセレクタをまとめて定義するときに便利なのですが、:is()の詳細度は、（）でまとめたセレクタの中で一番高い詳細度となります。

つまり、上の例CSSネストの時のセレクタ`:is(.parent1, #code) .text`では、詳細度は「1,1,0」となります。
SCSSの場合は、「0,2,0」となるので、SCSSと同じつもりでコーディングしたときにうまくクラスが当たらなくなる場合があります。


### &の役割が少し違う罠

CSSのクラスをBEMでつけたりすると、クラス名は結構長くなりがちです。

``` css
.contact {
  &__wrapper {}
  &__button {
    &--type1 {}
  }
}

```
SCSSのネストの場合、このように`&`を使ってクラス名の重複を避けて記述することができますが、CSSのネストでは`&`にテキストの参照する機能はないため、このような記述はできません。

ですので、CSSでは真面目にクラス名を記述することになります。

``` css
.contact {
 .contact__wrapper {}
 .contact__button {}
 .contact__button--type1 {}
}

```


### 記号始まりでないとダメな罠
CSSのネストと認識されるには下記の記号がセレクタの前にある必要があります。

`& . # : + > ~ [ @`

このため、h1やspanなどの要素型セレクタをネストする際はこのように `&`: ネストセレクタを使って記述する必要があります。

``` css
.button {
  & span {}
}
```

:::note info
ただし、ごく最近のブラウザでは、要素型セレクタに`&`がなくてもネストとして認識されるようになるとのことです！

chrome 120以降, safari 17.2以降, Firefox 117以降
:::


また、このように擬似クラスは、&なしでCSSネストとして認識されます。

``` css
.button {
  :hover {
    opacity: 0.8;
  }
}
```

しかし、この場合、 `.button *:hover`と解釈され、buttonクラスの子孫要素の全てがhoverされた時のスタイルを定義することになってしまいます。
もし、buttonクラスの、hover擬似クラスを定義したい場合は、 `&`: ネストセレクタを使ってこのように記載します。SCSSと同じですね。

``` css
.button {
  &:hover {
    opacity: 0.8;
  }
}
```

## 終わりに
SCSSネストからCSSネストに切り替える場合、そのまま記述を移し替えた場合
引っかかりそうな罠を3つ紹介しました。

2023年12月初旬現在、罠となってはしまいますが、どんどん仕様も変わっているのでいつの日かそのまま移行できる日も来るかもしれませんね。


---
## 参考

https://drafts.csswg.org/css-nesting/

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting

https://caniuse.com/css-nesting
file

<!--
2023/11/22
-->
[picoCTF][Forensics][extensions]

## Writeup
* ファイルを確認したら、拡張子が違う。
拡張子を修正。
![screenshot 18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/f362c821-fb35-9430-b2a8-da5360867eb8.png)
<br>

* 画像を確認。
![screenshot 19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/b0f03e21-d8f6-f606-0f76-8ab6b155fc0f.png)
<br>

* 以上です。
開発生産性カンファレンスに参加した

## はじめに
　2023年11月28日に汐留で開催された 「開発生産性の未来：世界と日本の最前線事例から培うFour Keys向上〜ハイブリッドカンファレンス〜] の感想を以下にまとめる。
## 開発生産性の未来：世界と日本の最前線事例から培うFour Keys向上〜ハイブリッドカンファレンス〜
　「Findy Team+ Award 2023」受賞企業の中から、多様なテーマで、"開発生産性向上を実現した具体的な事例"を集め、エンジニア組織づくりや、開発生産性や開発者体験の向上に向けた最先端のベストプラクティスが得られるカンファレンスである。
 
https://findy.connpass.com/event/298196/
## 感想
　まず「開発生産性」という言葉について、
 本カンファレンスに参加するまではぼーんやりと「まあ、開発の生産性（スピードとか質とか、）」くらいの理解でしかなかった。
 ただ、様々な企業やチームの開発生産性の定義を聞き、なんとなく「開発生産性」という言葉における解像度は上がった。また、開発生産性は企業やチーム、さらには経営層、マネージャー層、エンジニア層といったレイヤー毎で異なり、定量的に定義していくことが多いということを学んだ。

　その中でも私の立場的に最も近しく感じた開発生産性の定義は、株式会社モリサワさんの公演の中にあった「プルリクの数」である。
また、その公演の中で出た「ハックをするのは自由」という言葉が個人的にかなり印象的だった。

、、、。どういうことか、少し詳しく説明する。株式会社モリサワさんのプロダクトチームの中にある職能型チームでは、プルリク数をKPIとして設定している。そしてこのKPIの目安は「1人1日1プルリク」だそう。つまり、このKPIのプルリク数をハックしたかったらご自由にどうぞ、というスタンスを株式会社モリサワさんはとっているということだ。

「え、それってKPIとして成り立つの、、」と最初は困惑した。
確かに「1人1日1プルリク」としてKPIを設定することで、達成に向けた指針も立てやすいし、達成しているか否かも誰の目から見ても一目瞭然でわかる。

ただ、ハックが可能であることを考えると、作ったものの量やスピードばかりにフォーカスして、実際に生み出した価値とか、顧客の満足度への関心が薄れてしまうのではないかと思った。
（ちなみにこのように、組織がアウトカムではなくアウトプットで成功を計測しようとして行き詰まる状況を、「ビルドトラップ」というそう。）

　これに対し株式会社モリサワさんの答えはこうだ。
 「プルリク数を増やすには課題を分割する必要があり、結果的にレビューアーの負担も減るというメリットがある。また、この施策を行った結果、非効率で意味のないプルリクが増えることはなかった。」

　「たーしかに。」と思った。
 
　「1人1日1プルリク」というKPIがあったらどうにかして1日で終わる量にスプリットしようという癖がつくし、日を跨がないので効率的、モリサワさんがおっしゃる通りレビューの負担が減る、結果的に生産性向上に寄与している。
 私も実際の現場で実感することがあるので納得したし、開発生産性の向上に繋がるのは理解した。
 
 　ただ、やはりそれだけだと本質的なアウトカムに繋がるのか、と少し疑問は残る。
そこで私が思うのは、やはりチームメンバー1人1人の意識が重要になってくるのだと思う。

　株式会社ZOZOさんの公演ではこのようなことを仰っていた。
「開発生産性を上げることは目的ではなく、ユーザーに届ける価値を大きくすることの目標である。」

結局このマインドをチームのメンバー1人1人が常に意識していることが肝なのかなと感じたし、自分の中ではかなり合点がいった。

## おわりに
　本カンファレンスへの参加を通じて、率直な意見を言うと、エンジニア歴1年の私からすると、組織のあり方、開発生産性の捉え方、みたいな話が大半で、自分が実践するには少し早いかなー、と感じたというのが率直な感想ではある。
 ただその中でも、上に述べたような、開発生産性を意識しすぎてユーザーの満足度や感動への意識が疎かになる、というのは、最近ようやく少しJavaが書けるようになってきて、コードを書くのに精一杯な私からすると、次のステップへ進むために重要なことなのかなと感じる。
ロボットのようにPOからの要件通りにチケットを切って、デプロイしていくだけでなく、果たしてユーザーは何に関心があるのか、何に感動するのか、ということを意識しながらサービスを作っていく必要があると感じた。
そうすることでビジネスサイドの思考を持った、POと深い議論を交わせる、より強いエンジニアになれる気がする。頑張ろう。
Unified Logging

* Forensicsに使用できそうなので、メモ

## Unified Log
* デバッグとパフォーマンス分析のためにアプリからテレメトリーをキャプチャします。

## 手順　
* `Terminal`で以下を実行する。
Montereyは「5」のようです。
ディレクトリ名はなんでも良さげ。
~~~
mkdir log
cp -r /private/var/db/diagnostics/ log
cp -r /private/var/db/uuidtext/ log
/usr/libexec/PlistBuddy -c "Add:OSArchiveVersion integer 5" log/info.plist
mv log log.logarchive
~~~

* 作成した`info.plist`の内容。
`vim`などで作成しても問題なし。
同じディレクトリに保存。
~~~xml:info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>OSArchiveVersion</key>
	<integer>5</integer>
</dict>
</plist>
~~~
* `log.logarchive`をダブルクリックで確認可能。
![screenshot 31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/9b08fa9b-378e-6e25-82cf-6809b38ba14b.png)

## log showコマンド
* ログの見方は分かっていないので、とりあえず、参考のコマンドをメモ。
`--info`か`--debug`がないと、デフォルトのログレベルが対象になる。
`--archive FileName`で対象のlogarchiveファイルを指定すること。
`--predicate`で出力をフィルターできる。
<br>

* ログから`sudo`を含むものを出力
~~~
log show --archive log.logarchive --predicate 'process == "sudo"'
~~~
* プロセスを指定して出力
~~~
log show --archive log.logarchive --predicate 'processID == 26220'
~~~
* `sudo`コマンドの実行履歴を出力
~~~
log show --archive log.logarchive --predicate 'process == "sudo" and eventMessage contains "COMMAND="'
~~~
* リモート接続だろうか。
~~~
log show --archive log.logarchive --predicate 'process == "sudo" and eventMessage contains "TTY="'
~~~
* リモートで`su`や`sudo`を実行した履歴の出力だろうか。
~~~
log show --archive log.logarchive --predicate '(process == "su" or process == "sudo") and eventMessage contains "tty"'
~~~
* `kernel`と`Snadbox`を含むエントリーを出力。
~~~
log show --archive log.logarchive --predicate 'processImagePath contains "kernel" and senderImagePath contains "Sandbox" and eventMessage contains "file-read-xattr"'
~~~
* `Microsoft`を含むエントリーを出力。
~~~
log show --archive log.logarchive --predicate 'processImagePath contains "kernel" and senderImagePath contains "Sandbox" and eventMessage contains "file-read-xattr" and eventMessage contains "Microsoft"'
~~~
* スクリーンロック
~~~
log show --archive log.logarchive --predicate 'eventMessage contains "com.apple.sessionagent.screenIs"'
~~~
* ログイン
~~~
log show --archive log.logarchive --predicate 'processImagePath contains "loginwindow" and eventMessage contains "com.apple.sessionDidLogin"'
~~~

## 参考サイト

https://developer.apple.com/documentation/os/logging

https://www.mandiant.com/resources/blog/reviewing-macos-unified-logs

https://www.mac4n6.com/blog/2020/4/19/introducing-analysis-of-apple-unified-logs-quarantine-edition-entry-0
サブクエリ（副問い合わせ）基礎　〜相関サブクエリ編〜

## はじめに
サブクエリとは簡単にいうとSQL文の中にSQL文を書くことです。
サブクエリは複雑な問い合わせをしたい時に役立ちます。

サブクエリの使い方には大まかに以下三つが挙げられます。
- スカラー・サブクエリ
- 複数行サブクエリ
- 相関サブクエリ

シリーズものとして、本記事では**相関サブクエリ**について記述します。
「はじめに」は同シリーズすべて同じ内容です。一読された方は読み飛ばしてください。

### 備考
この記事ではMySQLを使った書き方をします。

### サブクエリの使い道
サブクエリの用途は色々ありますが、主な用途は「柔軟なSQLクエリを作成するため」です。
サブクエリの中にサブクエリを書くこともできネストを作成できます。また、記述できる場所はSELECT句でもGROUP BY句でもHAVING句でもどこでも書くことができ、非常に柔軟性に富んでいます。

しかし、あまりにもネストが深くなると、パフォーマンスに影響が出る他、読みづらいスパゲッティクエリとなってしまうため、注意が必要です。

## 相関サブクエリ
相関サブクエリは、外側のSQLと内側のSQL（サブクエリ）が「相関」して動くサブクエリです。以下に具体的な例を示します。

「従業員」と「部署」のテーブルを考えます。
各部署で最高給与を得ている従業員のリストを取得したい場合、次のようなクエリになります。

```sql
SELECT 従業員名, 給与, 部署ID
FROM 従業員 AS E1
WHERE 給与 = (
    SELECT MAX(給与)
    FROM 従業員 AS E2
    WHERE E1.部署ID = E2.部署ID -- ここが重要
);
```

内側のサブクエリ（E2）は、外側のクエリ（E1）の部署IDと一致するレコードを参照しています。このWHERE句は内部サブクエリの**部署IDの集合**に対する条件です。

相関サブクエリはテーブル全体ではなく、テーブルの一部のレコード集合に限定した比較をしたい場合に使います。


## まとめ
サブクエリの相関サブクエリについて解説しました。

### おまけ
スカラーサブクエリ、複数行サブクエリ、相関サブクエリに関する詳細をまとめます。


| 種類          | 説明 | 主に使う構文                                                                                                   | 使用例                                                                                      |
|-------------|-------------|-------------|-------------|
| スカラー・サブクエリ  | 単一の値（1行1列）を返します。SELECT文の中で単一の値を返す必要がある場所で使われます。  |         AVG , 演算子（>,<,=）        | `SELECT * FROM テーブル WHERE 列 = (SELECT AVG(列) FROM テーブル WHERE 条件);`             |
| 複数行サブクエリ  | 一つ以上の行を返すことができます。  |       IN,ANY,ALL,演算子（>,<,=）            | `SELECT * FROM テーブル WHERE 列 IN (SELECT 列 FROM テーブル WHERE 条件);`                |
| 相関サブクエリ  | 外側のクエリと「相関」している内側のクエリです。外側のクエリの各行に対して内側のクエリが実行され、外側の列を参照できます。| IN, EXISTS ,演算子（>,<,=）      | `SELECT * FROM テーブルA WHERE EXISTS (SELECT * FROM テーブルB WHERE テーブルB.列 = テーブルA.列);` |




### 参考
https://www.seshop.com/product/detail/19054

https://medium.com/@mariacolby3/sql-data-interview-series-subqueries-in-sql-32d88e9ab760

https://medium.com/future-pub/beginners-guide-to-the-sql-subquery-unleashing-the-hidden-power-of-nested-queries-ecd8d81f4e49
SynologyのNASのワンタイムパスワードが突破できないときの対処法

## 先に結論

私の状況では、NASをオフライン（PCと直結）で使用しており、NASがNTPサーバーに接続できない事で時刻のずれを訂正できず、正確なOTPが生成できない→認証ができないという状況でした。
そのため、NASにSSHで接続し、以下のコマンドで強制的に時間を書き換えることでNAS側のOTPの挙動を元に戻し、正常に認証出来るようになりました

```shell
sudo date -s "2023-12-08T20:44:20+09:00"
```

------

結論だけで完結してる気がして、これ以上書くモチベーションが上がらないので終わります。
使用したコマンドだけ備忘録的に残しておきます。

```shell
$ ssh user@synology-nas

# NASの時刻を確認
$ date
Fri Dec  8 20:45:33 JST 2023

# NASの時刻を現在時刻に手動で書き換え
$ sudo date -s "2023-12-08T20:44:20+09:00"
Fri Dec  8 20:44:20 JST 2023
```
助手はChatGPT

chatGPTを使ってみての個人的な感想です

## 1. 個人開発とChatGPT

### 1.1 chatGPTで広がる可能性

#### 1.1.1 プログラミングへのハードルが下がる

今やchatGPTがあれば「Hello World」程度は手取り足取り教えてもらえます
自分が最初にプログラミングを始めたときはコード１行目のエラーに対処できなくて挫折してしまいましたが*1「プログラミング」へのハードルは格段に下がっているといえるのではないでしょうか。

*1 C言語ですがおそらく環境構築でパスが通ってなかったとかそのレベルです

#### 1.1.2 新しい言語やフレームワークへのハードルが下がる

先のトピックと重なる部分もありますが、特にある程度プログラミングに触れている人がほかの言語やフレームワークに手を出すときに例えば「〇〇をPythonとC#で実装して」などと頼めば、chatGPTが２つの言語の実装の違いまで教えてくれるはずです。
言語そのものの理解（言語の大切にしている考え方）に直結するかどうかは微妙ですが、その言語の基本的な文法であったりifやforの構文を勉強する手間はある程度省くことがないでしょうか

他にも複数のライブラりでコードを比較してもらってその中から１つを選ぶ、何てこともより手軽にできます

#### 1.1.3 気軽に質問できる

これまでは、コーディングで分からないことや詰まったことがあればTeratailやDiscordのコミュニティで質問して有識者の方に教えてもらうや自分の身の回りの人に教えてもらうことが主だったと思いますが、特にインターネット上の質問は質問者として提示する情報が不足していて指摘していただいたり自分の質問に回答がつかなかったりするため「これは自分で解決できないのか」「質問するほどのことなのか」と**自分の中で**考えてしまい質問に踏み切れない、なんて経験をお持ちの方も多いのではないでしょうか。

※自分が回答者になるときの考えとしてはどんなに基本的な質問でも質問したほうがいいと思っています。回答者としてもしばらくその言語やフレームワーク、環境に触れていないかったときに思い出したり基本的な内容の確認ができるため自分としても勉強になるからです
ただ、質問者になるときはすごく投稿前に気にして解決せずに放置...なんてこともよくあります

#### 1.1.4 豊富なアイディアを出してくれる

正確な情報を必要な場合にchatGPTが適さないと対照的にアイディア出しや手段を考える場合には頼れる助手になってくれます
例えば、「この実装をいくつかの方法で説明してください」とか「〇〇から連想される単語を考えてください」などなど

### 1.2 それでも

先の通り、自分の開発ではchatGPTの恩恵を授かっています
しかし自分は、chatGPTに頼りっぱなしの開発の是非については否定的です

#### 1.2.1 chatGPTを信じるなかれ

chatGPTは多くのパラメーターで学習しています、GPT4の精度がかなり高いという話も聞きます
しかし、あくまでchatGPTが持っているのは学習時にインターネット上にある情報であったり質問時にインターネット上にある**多くの**情報です

特にバージョンアップがあったり、脆弱性が見つかったりと日々変化している環境でchatGPTがくれる情報は必ずしも正確とは限りません

個人的に特に顕著だと感じるのはVue.js関係のコードを書いてもらうときにvue3を指定しているにも関わらず、vue3で非推奨のコードが出てきたり、そもそもvue3で使えない構文が混ざっていたりします

#### 1.2.2 エラーは自分で解決したほうがいい

エラーを解決することは自己解決能力を向上させる優れた手段です。
エラー文や出力を読み、どうやって検索すれば知りたいことが出てくるのか、前に似たようなエラーに出会ったときにどのように解決したかという経験はエンジニアとして重要ではないでしょうか

chatGPTでのエラー解決に頼りすぎるとかえってエラー解消までにかかる時間がかかる場合もあります

※chatGPTでエラーを解決することを否定したいわけではありません
調べても出てこないようなエラーだったり、エラー文をかみ砕いてもらうためには有用だと思います

個人的な経験としてエラーやバグを経験することで将来的に迅速に対応できるようになるとは思います

#### 1.2.3 公式ドキュメントを読んで引き出しを増やそう

どんなにchatGPTが便利だろうと、copilotが便利だろうと公式ドキュメントには目を通すべきだと思います
結局どんなにツールが進化しても最新で正確で詳細な情報が得られるのは公式ドキュメントだけです
他にも、公式ドキュメントを眺めていると自分の知らなかった構文や機能に出会えます
そのプロジェクトでは使わなかったとしても将来的に別のプロジェクトで「そういえばあのライブラリでこんなことできたな」といったような引き出しがあれば実装の幅が格段に広がります

## 2. chatGPTに入力する情報には気を付けよう

**まさかチャットGPTにそのままコード貼り付けていませんか？**

まれに「クレデンシャル直書き」「トークンコピペしたまま」なんてことがありますがchatGPTにコピペする前にコードは必ず秘匿すべき情報が含まれていないか確認しましょう

コピペする前に「このコードをGithubのパブリックリポジトリに張り付けても大丈夫かどうか」を考えることをお勧めします


## 3. chatGPTを使うときに気を付けること

### 3.1 コードの検証

ここまででも書いているようにchatGPTの生成するコードには誤りや非推奨の構文が使用されていることがあります
生成されたコードは必ず自分で確認しましょう

また、チームで決められているコーディングの方針に沿っているかどうかも確認しておきましょう

### 4. 結論

chatGPTに任せるべきこと、自分でやるべきことを模索しながらchatGPTを自分専属の助手として有効活用することで作業効率を爆上げしましょう！
サブクエリ（副問い合わせ）基礎　〜複数行サブクエリ編〜


## はじめに
サブクエリとは簡単にいうとSQL文の中にSQL文を書くことです。
サブクエリは複雑な問い合わせをしたい時に役立ちます。

サブクエリの使い方には大まかに以下三つが挙げられます。
- スカラー・サブクエリ
- 複数行サブクエリ
- 相関サブクエリ

シリーズものとして、本記事では**複数行サブクエリ**について記述します。
「はじめに」は同シリーズすべて同じ内容です。一読された方は読み飛ばしてください。

### 備考
この記事ではMySQLを使った書き方をします。

### サブクエリの使い道
サブクエリの用途は色々ありますが、主な用途は「柔軟なSQLクエリを作成するため」です。
サブクエリの中にサブクエリを書くこともできネストを作成できます。また、記述できる場所はSELECT句でもGROUP BY句でもHAVING句でもどこでも書くことができ、非常に柔軟性に富んでいます。

しかし、あまりにもネストが深くなると、パフォーマンスに影響が出る他、読みづらいスパゲッティクエリとなってしまうため、注意が必要です。


## 複数行サブクエリ

たとえば、会社の上司から、「過去1か月間で、なにかしら注文してくれた、すべての顧客を検索したい」と命じられたとき。
以下のようなクエリになります。

```sql
SELECT
    *
FROM
    customers　--　顧客テーブル
WHERE
    -- なにかしら注文してくれた顧客を絞り込む
    customer_id IN(
        SELECT DISTINCT
            customer_id
        FROM
            orders
        WHERE
            order_date >= DATE_ADD(now(), INTERVAL -1 MONTH) -- 注文日が１ヶ月前からの注文を絞り込む
    )
;
```

この例では、サブクエリは、注文日が過去1か月以内であるすべての顧客IDを「`orders`」テーブルから取得します。次に、外側のクエリは、顧客IDがサブクエリによって返されたIDの1つと一致する、すべての列を「`customers`」テーブルから取得します。



## まとめ
サブクエリの複数行サブクエリについて解説しました。

### おまけ
スカラーサブクエリ、複数行サブクエリ、相関サブクエリに関する詳細をまとめます。


| 種類          | 説明 | 主に使う構文                                                                                                   | 使用例                                                                                      |
|-------------|-------------|-------------|-------------|
| スカラー・サブクエリ  | 単一の値（1行1列）を返します。SELECT文の中で単一の値を返す必要がある場所で使われます。  |         AVG , 演算子（>,<,=）        | `SELECT * FROM テーブル WHERE 列 = (SELECT AVG(列) FROM テーブル WHERE 条件);`             |
| 複数行サブクエリ  | 一つ以上の行を返すことができます。  |       IN,ANY,ALL,演算子（>,<,=）            | `SELECT * FROM テーブル WHERE 列 IN (SELECT 列 FROM テーブル WHERE 条件);`                |
| 相関サブクエリ  | 外側のクエリと「相関」している内側のクエリです。外側のクエリの各行に対して内側のクエリが実行され、外側の列を参照できます。| IN, EXISTS ,演算子（>,<,=）      | `SELECT * FROM テーブルA WHERE EXISTS (SELECT * FROM テーブルB WHERE テーブルB.列 = テーブルA.列);` |




### 参考
https://www.seshop.com/product/detail/19054

https://medium.com/@mariacolby3/sql-data-interview-series-subqueries-in-sql-32d88e9ab760

https://medium.com/future-pub/beginners-guide-to-the-sql-subquery-unleashing-the-hidden-power-of-nested-queries-ecd8d81f4e49
サブクエリ（副問い合わせ）基礎　〜スカラー・サブクエリ編〜

## はじめに
サブクエリとは簡単にいうとSQL文の中にSQL文を書くことです。
サブクエリは複雑な問い合わせをしたい時に役立ちます。

サブクエリの使い方には大まかに以下三つが挙げられます。
- スカラー・サブクエリ
- 複数行サブクエリ
- 相関サブクエリ

シリーズものとして、本記事では**スカラー・サブクエリ**について記述します。
「はじめに」は同シリーズすべて同じ内容です。一読された方は読み飛ばしてください。

### 備考
この記事ではMySQLを使った書き方をします。

### サブクエリの使い道
サブクエリの用途は色々ありますが、主な用途は「柔軟なSQLクエリを作成するため」です。
サブクエリの中にサブクエリを書くこともできネストを作成できます。また、記述できる場所はSELECT句でもGROUP BY句でもHAVING句でもどこでも書くことができ、非常に柔軟性に富んでいます。

しかし、あまりにもネストが深くなると、パフォーマンスに影響が出る他、読みづらいスパゲッティクエリとなってしまうため、注意が必要です。

## スカラー・サブクエリ
スカラサブクエリは**必ず１行１列だけの戻り値を返す**という制約をつけたサブクエリのことです。「スカラ」は「単一の」という意味です。

例えば、会社の上司から「全従業員の平均給与よりも高い給与を支払っている従業員の詳細を取得して」と命じられた時、
以下のようなクエリになります。

```sql
SELECT *
FROM employee 
WHERE salary > (SELECT AVG(salary) FROM employee)
```

このように、比較演算子（>, <, =）を使いたい時に、スカラー・サブクエリを使うのが有効です。

## まとめ
サブクエリのスカラー・サブクエリについて解説しました。

### おまけ
スカラーサブクエリ、複数行サブクエリ、相関サブクエリに関する詳細をまとめます。


| 種類          | 説明 | 主に使う構文                                                                                                   | 使用例                                                                                      |
|-------------|-------------|-------------|-------------|
| スカラー・サブクエリ  | 単一の値（1行1列）を返します。SELECT文の中で単一の値を返す必要がある場所で使われます。  |         AVG , 演算子（>,<,=）        | `SELECT * FROM テーブル WHERE 列 = (SELECT AVG(列) FROM テーブル WHERE 条件);`             |
| 複数行サブクエリ  | 一つ以上の行を返すことができます。  |       IN,ANY,ALL,演算子（>,<,=）            | `SELECT * FROM テーブル WHERE 列 IN (SELECT 列 FROM テーブル WHERE 条件);`                |
| 相関サブクエリ  | 外側のクエリと「相関」している内側のクエリです。外側のクエリの各行に対して内側のクエリが実行され、外側の列を参照できます。| IN, EXISTS ,演算子（>,<,=）      | `SELECT * FROM テーブルA WHERE EXISTS (SELECT * FROM テーブルB WHERE テーブルB.列 = テーブルA.列);` |




### 参考
https://www.seshop.com/product/detail/19054

https://medium.com/@mariacolby3/sql-data-interview-series-subqueries-in-sql-32d88e9ab760

https://medium.com/future-pub/beginners-guide-to-the-sql-subquery-unleashing-the-hidden-power-of-nested-queries-ecd8d81f4e49
EmacsでNew Relic

# はじめに
この記事は[New Relic Advent Calendar 2023](https://qiita.com/advent-calendar/2023/newrelic)の15日目の記事です。
みんな大好きEmacsでNew Relicを使うとどうなるかを検証してみようと思います。

# 今回使うパッケージ
2年前で更新が止まっちゃってますが、こんなEmacsパッケージを見つけました。
[emacs-newrelic](https://github.com/maciejsmolinski/emacs-newrelic/tree/main)
そのまんまですね。

# まずはインストール
もちろんMeplaとかにあるわけでもないので、~/.emacs.dにGitHubからcloneしておきました。

## インストール構成
```
$ tree emacs-newrelic/
emacs-newrelic/
├── README.md
├── newrelic-api.el
└── newrelic.el
```

init.elに次の内容を追加します。
```init.el
;; emacs-newrelic
(add-to-list 'load-path' "~/.emacs.d/emacs-newrelic")
(require 'newrelic)
(setq newrelic-api-key "<YOUR-API-KEY>")
```

私はNew Relicのアカウントを切り替えることがよくあるのですが、今回はお試し用なので、1つのAPI Keyだけ設定することとしました。

次から実際に使って行ってみます。

# アカウントの切り替え
```emacs-lisp:mini-buffer
M-x newrelic-set-active-account
```
マスターアカウント内にサブアカウントがいっぱいあって探すのが大変というときは、TABキーで一覧が出せるので便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356164/196e2554-8e5b-598e-6ec7-82f88d406466.png)


# NRQLを実行してみる
```emacs-lisp:mini-buffer
M-x newrelic-nrql-eval-line
```
どこか適当なBufferでNRQLを書いて実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356164/02c8209a-634b-80b5-a341-ae6973db75fe.png)
画像として取得されました。

続けて実行すると、同じBufferの上に結果が挿入されていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356164/c8f81d1e-465d-046d-21c9-03049f300753.png)

#その他のNRQL用関数
```emacs-lisp:minibuffer
M-x newrelic-nrql-eval
```
これはMini-bufferに直接NRQLを入力して実行させます。

```emacs-lisp:mini-buffer
M-x newrelic-nrql-eval-region
```
NRQLを複数行で書きたい場合はこの関数がおすすめです。
regionを元にNRQLを実行してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356164/f0076973-8b7b-ce21-d448-b709a6c9db57.png)

# ダッシュボード一覧の取得
```emacs-lisp:mini-buffer
M-x newrelic-dashboards
```
これは指定したダッシュボードをブラウザで開いてくれるだけのものですが、
アカウントの切り替えの時と同じように、TABキーでダッシュボード一覧を取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356164/2a739e8b-cbc7-1a40-ed58-d74021839201.png)

# まとめ
Emacsを使うと、こんなこともできちゃいますという紹介でした。
このパッケージもっと機能追加してもいいのかなとは思いましたが、New RelicはNRQLで色んなことできちゃうので、しばらくはこれで遊んでみようと思います。
goの基本的な文法をまとめてみた

goを勉強中なので、javaScriptと比較しながら基本的な文法をまとめてみました。

<h3>基本的なループ</h3>

```
【javaScript】
for (let i = 0; i < 10; i++) {
    console.log(i);
}

【go】
for i := 0; i < 10; i++ {
    fmt.Println(i)
}
```

<h3>条件分岐</h3>

```
【javaScript】
if (x > 0) {
    console.log("xは正です");
} else if (x < 0) {
    console.log("xは負です");
} else {
    console.log("xは0です");
}

【go】
if x > 0 {
    fmt.Println("xは正です")
} else if x < 0 {
    fmt.Println("xは負です")
} else {
    fmt.Println("xは0です")
}
```

```
【javaScript】
switch (x) {
    case 1:
        console.log("xは1です");
        break;
    case 2:
        console.log("xは2です");
        break;
    default:
        console.log("xは1でも2でもありません");
}

【go】
switch x {
case 1:
    fmt.Println("xは1です")
case 2:
    fmt.Println("xは2です")
default:
    fmt.Println("xは1でも2でもありません")
}
```

<h3>配列に格納された文字を連結する</h3>

```
【javaScript】
let str = ''
let array = [
    "val1",
    "val2",
    "val3",
    "val4"
]
for (val in array) {
    str += val;
}

【go】
package main

import (
    "fmt"
    "strings"
)

func main() {
    var str strings.Builder
    array := []string{
        "val1",
        "val2",
        "val3",
        "val4",
    }
    for _, val := range array {
        str.WriteString(val)
    }
    fmt.Println(str.String())
}
```

<h3>配列に格納された文字を、空の配列を定義した変数の中へ格納する</h3>

```
【javaScript】
let newarr = []
let array = [
    "val1",
    "val2",
    "val3",
    "val4"
]
for (val in array) {
    newarr.push(val)
}

【go】
package main

import "fmt"

func main() {
    array := []string{
        "val1",
        "val2",
        "val3",
        "val4",
    }
    newarr := make([]string, 0, len(array))
    for _, val := range array {
        newarr = append(newarr, val)
    }
    fmt.Println(newarr)
}
```

<h3>オブジェクトに格納されたキーと値を文字列連結する</h3>

```
【javaScript】
let str = ''
let obj = {
    "name": "yuya",
    "address": "tokyo",
    "age": "31"
}
for (key in obj) {
    str += `${key}: ${obj[key]}, `
}

【go】
package main

import (
    "fmt"
    "strings"
)

func main() {
    var str strings.Builder
    obj := map[string]string{
        "name":    "yuya",
        "address": "tokyo",
        "age":     "31",
    }
    for key, value := range obj {
        str.WriteString(fmt.Sprintf("%s: %s, ", key, value))
    }
    fmt.Println(str.String())
}
```
【17日目】Web環境(ベータ版)に提出してみた

この記事は筆者オンリーの[Advent Calendar 2023](https://qiita.com/advent-calendar/2023/aichallenge_racing_for_mas)2日目の記事です。  

この間自動運転AIチャレンジのWeb環境(ベータ版)のテスター募集があったため応募しソースコード一式を提出してみました。

# 採点ルールについて
[こちら](https://automotiveaichallenge.github.io/aichallenge2023-racing/rule/index.html)に掲載されていますのでご一読ください。

# オンライン提出方法
[こちら](https://github.com/AutomotiveAIChallenge/aichallenge2023-racing/blob/main/documentation/docfx_project/online/index.md)に掲載されています。
この通りにやって、オンライン環境にアップロードして終わりです。

# オンライン提出したら
https://www.youtube.com/watch?v=kRUbEEF2gmI&t=1s

上のyoutubeにまとめが載っています。一度視聴していただくとよりわかりやすいと思います。
グッドボタンを押していただけると幸いです！
Markdown Preview Enhancedのプレビューで改行・空行・行頭の字下げを表示する【VSCode】

# 《目標》
デフォルトの設定では表示されない改行・空行・行頭の字下げをプレビュー画面に表示されるように設定します。

## 設定前
![スクリーンショット 2023-12-07 20.19.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627098/13d78238-29bd-1421-ab48-6f1ce32a3bbe.png)

## 設定後
![スクリーンショット 2023-12-07 20.21.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627098/cea08d60-ae2d-feb1-bd98-1c694525008e.png)

# 《環境》
Visual Studio Codeに以下の拡張機能を追加。
・Markdown Preview Enhanced v0.8.10

# 《方法》
## ● 改行
設定からMarkdown Preview Enhancedの「Break On Single New Line」をtrueに変更する。
 
:::note warn
上記の設定で改行されない場合は、Markdown Preview Enhancedの「Use Pandoc Parser」をfalseにしてください
:::

## ● 空行と行頭の字下げ
### 手順① Visual Studio Codeのコマンドパレット（［F1］キー）で以下のコマンドを実行。
```
Markdown Preview Enhanced: Extend Parser
```

実行すると、parser.jsというファイルが開かれます。

### 手順② parser.jsを以下のように変更する。
```onWillParseMarkdown```内に以下のコードを追加します。追加したコードで空行や行頭の字下げを文字実体参照に置き換えています。
``` js:parser.jsに追加したコード
    //空行
    markdown = markdown.replace(/^$/gm, '&nbsp;');
    //行頭の字下げ
    markdown = markdown.replace(/^(　)/gm, '&emsp;');
```

　変更後の```parser.js```は以下のようになります。
``` js:変更後のparser.js
({
  // Please visit the URL below for more information:
  // https://shd101wyy.github.io/markdown-preview-enhanced/#/extend-parser

  onWillParseMarkdown: async function (markdown) {
    //空行
    markdown = markdown.replace(/^$/gm, '&nbsp;');
    //行頭の字下げ
    markdown = markdown.replace(/^(　)/gm, '&emsp;');
    return markdown;
  },

  onDidParseMarkdown: async function (html) {
    return html;
  },
})
```
 :::note warn
Markdown Preview Enhancedのバージョンによって、ファイルの内容が異なることがあります。```onWillParseMarkdown```内にコードを追加してください。
:::

# 《参考》

https://shd101wyy.github.io/markdown-preview-enhanced/#/extend-parser

https://trap.jp/post/1791/
これは何ファイル？？？

最近、ファイルの拡張子(tar.gz)に騙され、苦戦したので下記3種類のファイルの見分け方をまとめておこうと思います！
・text1.tar.gz(tar.gzの姿を装った空のテキストファイル)
・text2.tar.gz(tar.gzの姿を装ったtarファイル)
・text3.tar.gz(本物のtar.gzファイル)
姿かたちを偽っていたテキストファイルの正体を見破った経験と喜びのせいで先入観のようなものを抱いてしまい、``text2.tar.gz``がtarファイルであったと判別するまでかなりの時間を要してしまいました( ﾉД`)ｼｸｼｸ…

今回、正体を暴くまでに使用したのはLinuxの
①tarコマンド
②fileコマンド
③勘


**手っ取り早いのはなんといっても勘！**

中身がわけのわからない文字の羅列はtar.gzファイルであるはず。
数列がtarファイル。
空のテキストファイルでも圧縮すると何かしらの文字が生成されるので、中身が空の時点でテキストファイルで決定です。
~~~~teraterm
//空のテキストファイルはファイルサイズが0
~$ du -h text1.tar.gz
0       text1.tar.gz
~~~~~~~~~~
## 【本題】
最強は②のfileコマンドです。
ですが、そこにたどり着くまでの道のりを紹介します。

tar.gzファイルの解凍は「tar -zxvf ファイル名」でできますが、オプションの意味を理解していませんでした。調べるとオプション'z'は圧縮形式がgzip形式のものを指し、違う圧縮形式のファイルを解凍しようとすると下記のようなエラーになります。
~~~~teraterm
~$ ls
text1.tar.gz  text2.tar.gz  text3.tar.gz

~$tar -zxvf text2.tar.gz
gzip: stdin: unexpected end of file
tar: Child returned status 1
tar: Error is not recoverable: exiting now
~~~~~~~~~~

オプション「z」を外し、実行してみると解凍できます。
これにより``text2.tar.gz``はtar.gzファイルではなかったことがわかります。
(``text1.tar.gz``を同じように実行すると「これはtarアーカイブではないようです」と出力されます)
~~~~teraterm
~$ tar -xvf text2.tar.gz
text2.txt
~~~~~~~~~~
ここで``text2.tar.gz``をtarファイルと断定してしまっていいのかわからなかったため、fileコマンドを活用しました。ここで一気に各ファイルがどの形式なのかを確認します。
~~~~teraterm
~$ file text1.tar.gz
text1.tar.gz: empty　//ただの空ファイルであることがわかります

~$ file text2.tar.gz
text2.tar.gz: POSIX tar archive (GNU) //拡張tarフォーマット(tarファイル？)のことを指す

~$ file text3.tar.gz
//gzip形式で圧縮されていることを指す
text3.tar.gz: gzip compressed data, from Unix, original size modulo 2^32 167772200

//オプション'z'を含むコマンドで解凍できることを確認
~$ tar -zxvf text3.tar.gz
text3.txt
~~~~~~~~~~
tarコマンド×オプション'z'で解凍できたため、``text3.tar.gz``が拡張子通りのファイルであったことがわかりました。
【Unity XR】XR Grab Interactableで掴む位置を変更する

## 遮眼子が掴めない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638306/ba98121d-eecf-9936-ddfe-9cd3b72acc49.png)

なんとなくUnityを使って視力検査をしようと思い、上の画像のようなシーンを作ってみた。
うん、**遮眼子ぎゃくぅ！**。
とりあえず、遮眼子を持てるようにしてみたのだが、持つ位置がおかしいし、向きも逆になっている(´；ω；`)

尚、Unityは2022.3.7f1を使っている。

## 掴めるようにする
掴む対象のオブジェクト（今回は遮眼子）にXR Grab Interactableを追加し、Smooth Position、Smooth Rotationにチェックを入れると、掴めるようになる。しかし、これだけだと前述のようにおかしな位置を握りしめることになった。

## 解決方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638306/08d820f7-9f23-b224-5351-74f750fccce1.png)
空オブジェクト（AttachPoint）をローカル座標で掴みたい位置に設定し、これをXR Grab InteractableのAttachPointに設定すると、想定している持ち方ができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638306/45162dcb-d702-9eeb-6f54-eaf28b03ae15.png)

## 完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638306/400adbb1-3d0d-9c80-9899-8a530c61c9a5.png)
無事に遮眼子を手で持って視力検査ができるようになった。VRで視力検査をする意味は特にない...