OmniAICreator/Qiita-1.07M huggingface dataset:
PySimpleGUI　気になったこと

## 疑問点
[sg.Text()]とsg.popup()は何が違うのか。

## 出力結果
```ruby:PySimpleGUI
import PySimpleGUI as sg

layout = [[sg.Text("こんにちは")]]

window = sg.Window("test", layout, size = (300, 150))

window.read()
```
```ruby:PySimpleGUI
import PySimpleGUI as sg

sg.popup("こんにちは")
```

双方ともに同じ画面を出力する。

## 動画
https://www.youtube.com/watch?v=hdjDYGXbVws

この動画はsg.Textを使用している。



https://www.youtube.com/watch?v=a3AeM1GZNTk&list=PLqC1Lik2CUiiNhSuk5UdWpHmBKPEryrSo


この動画ではsg.popupを取り扱っている。

## 仮説
sg.Textはlayoutは必要だが、sg.popupは**不要**である。さらにウィンドウを表示させるために必要なsg.Windowやwindow.readも**不要**なため、簡易的なプログラム(数行程度)を作成する時に使うのでは...?
公式のクックブックや有志のブログなどで情報を集め、私なりの答えを見つけていきたい。
turbo_streamファイルの置き場所の検討

# はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー16日目です。

引き続きTurboを学習していて、ふと気になったことがありました。

それは、`○○.turbo_stream.erb`ファイルの置き場です。

### ○○.turbo_stream.erbとは？
Turbo Streamを使って非同期通信を行う際、更新する要素の情報を書いておくファイルです。

例えば、コメント一覧とコメントの総数を非同期で更新したい場合を考えます。

以下のようなコメントを一覧表示しているviewがあるとします。

```erb:index.html.erb
<!-- app/views/comments/index.html.erb -->

<div id="comments_count">
  <%= pluralize(Comment.count, 'comment') %>
</div>

<div id="comments_list">
  <%= render @comments %>
</div>
```

このとき、以下のように`create.turbo_stream.erb`というファイルを用意します。

```erb:app/views/comments/create.turbo_stream.erb
<%= turbo_stream.append "comments_list", partial: "comments/comment", locals: { comment: @comment } %>
<%= turbo_stream.update "comments_count", Comment.count %>
```

すると、`comments_list`および`comments_count`の値を非同期で更新できるようになる、というものです。

### ○○.turbo_stream.erbファイルの置き場問題

これを見たとき、`create.html.erb`とファイルの置き場所がかぶるので別の場所に置いておけないかと思いました。同様の例にmailerのerbファイルがありますが、あれはどちらか消してしまうのであまり違和感を感じません。

ただその場合、通常のerbファイル(○○.html.erb)はそのままの場所に置いておきたいので、turbo_streamファイルの方だけを別に置く形になりそうです。

# ○○.turbo_stream.erbファイルの置き場候補

Turbo Streamsのファイルを別のフォルダにまとめて分けたい場合、Railsのビューパスの設定をカスタマイズすることになります。その場合、以下の方法が考えられます。

**コントローラーレベルでのパスのカスタマイズ**
**カスタムレンダラーの作成**

## コントローラレベルでのビューパスのカスタマイズ
各コントローラで、レスポンスのフォーマットに応じてビューパスをカスタマイズすることができます。例えば、FugasControllerのhogeアクションでTurbo Streamのビューパスを設定するには：

```ruby:controllerでの例
class FugasController < ApplicationController
  def hoge
    respond_to do |format|
      format.turbo_stream { render turbo_stream: "turbo_streams/hoge" }
      # 他のフォーマットに対するレスポンスもここに記述
    end
  end
end
```
この例では、app/views/turbo_streams/hoge.turbo_stream.erbに対応するビューファイルを使用するように指定しています。

## カスタムレンダラーの作成
カスタムレンダラーを作成することで、特定のフォーマット（例えばTurbo Streams）に対して表示するビューを決めるロジックを変更できます。

```ruby:custom_turbo_stream_renderer.rb
# lib/custom_turbo_stream_renderer.rb
module CustomTurboStreamRenderer
  def render(options = nil, extra_options = {}, &block)
    if options.is_a?(Hash) && options[:turbo_stream].present?
      options[:template] = "turbo_streams/#{options[:turbo_stream]}"
    end
    super(options, extra_options, &block)
  end
end

### コントローラーでこのモジュールをインクルード
```ruby:コントローラーでの例
class FugasController < ApplicationController
  include CustomTurboStreamRenderer
  # ...
end
```

この例では、turbo_streamオプションが指定された場合に、turbo_streamsディレクトリをビューパスとして使用するようにカスタマイズしています。

# 終わりに
調べてみて感じたのは、これらの手段はあまり使わない方が良い、ということです。
例えば複数のリソースが同じアクションでturbo_streamを利用する場合ファイル名が衝突しますし、Railsの規約から逸脱すると、将来的なメンテナンスやRailsのバージョンアップグレード時に問題が生じる危険もあるためです。

1つ目のやり方であればまだ検討の余地がありそうですが、よほど大量のstreamを使って混乱が生じそうな設計以外では使うメリットよりデメリットの方が大きくなってしまいそうです。
bmm150-compassライブラリ導入ガイド

## bmm150-compassライブラリについて
[bmm150-compass](https://github.com/tichise/bmm150-compass)はM5Stack社が公開してる地磁気センサーBMM150用ライブラリ m5stack/M5_BMM150 をより簡単に使用できるようにするために開発したライブラリです。bmm150-compassは、Arduino開発者にとってより扱いやすいラッパーとして設計されました。この記事では、bmm150-compassライブラリの導入方法と基本的な使い方を紹介します。

## ライブラリの特徴
- 簡易化された初期化: BMM150センサーのセットアップと初期化が簡単に。
- 直感的なデータ読み取り: X, Y, Z軸の地磁気データを簡単に取得。
- PlatformIOとの統合: PlatformIOでダウンロードして使用可能。

## 導入方法
PlatformIOライブラリマネージャーの利用: PlatformIO IDEを開き、ライブラリマネージャーからbmm150-compassを検索し、インストールします。

`platformio.ini`ファイルの設定: 以下の設定をプロジェクトのplatformio.iniファイルに追加します。

```
lib_deps =
    https://github.com/tichise/bmm150-compass.git
```

ライブラリのインポート: Arduinoスケッチで`#include <BMM150Compass.h>`を使用してライブラリをインポートします。

詳細な手順はこちらにまとまってます。
[tichise/BMM150Compass: About This wrapper is designed to simplify…](https://registry.platformio.org/libraries/tichise/BMM150Compass)

## 基本的な使い方
```
#include <Arduino.h>
#include <BMM150Compass.h>

// SDAとSCLのピン番号を定義（あなたのハードウェア設定に合わせて変更してください）
#define PIN_SDA 13
#define PIN_SCL 15

// BMM150Compassのインスタンスを作成
BMM150Compass compass;

void setup()
{
  Wire.begin(PIN_SDA, PIN_SCL);

  delay(3000);
  USBSerial.println("Starting BMM150 Compass example...");

  // シリアル通信の初期化
  USBSerial.begin(115200);

  compass = BMM150Compass();

  // センサーの初期化
  if (compass.initialize() != BMM150_OK)
  {
    USBSerial.println("BMM150 initialization failed!");
    while (1)
      ; // 初期化に失敗した場合は無限ループ
  }

  USBSerial.println("BMM150 initialized successfully.");

  // オフセットの読み込み
  compass.offset_load();

  // キャリブレーションの実行（10秒間）
  USBSerial.println("Starting calibration...");
  compass.calibrate(10000);
  USBSerial.println("Calibration complete.");
}

void loop()
{
  int16_t raw_data[3];

  // 磁気センサーの値を取得するメソッド
  compass.getXYZ(raw_data);
  
  // 以降の処理はBMM150を積んだ開発ボードでも、ボードによって異なります。XYZ軸の扱いが違うので、ご自身の環境に合わせて適宜書き直してください。

  // 度数での方位角を取得するメソッド（0から360度の範囲）
  double headingDegrees360 = compass.getHeadingDegrees360();
  
  // Grove Degital Compass v2はv1と比べて180度ずれてるので、180度回転させる
  headingDegrees360 += 180; // 角度を180°時計回りに回転
  if (headingDegrees360 < 0)
  {
    headingDegrees360 += 360; // 負の値を修正
  }
  headingDegrees360 = fmod(headingDegrees360, 360); // 360°を超える値を修正

  // 結果をシリアルポートに出力
  USBSerial.print("Heading: ");
  USBSerial.print(headingDegrees360);
  USBSerial.println(" degrees");

  // ループの遅延（1秒ごとに更新）
  delay(1000);
}
```

この簡単な例では、地磁気センサーからX, Y, Z軸のデータを読み取り、シリアルモニターに表示しています。

`bmm150-compass`ライブラリを使用することで、Arduinoユーザーは地磁気センサーBMM150の機能を最大限に活用し、独自のプロジェクトに簡単に統合することができます。このライブラリは、地磁気センサーの使用をよりアクセシブルにし、Arduinoコミュニティに貢献することを目指しています。
主に使用される4つのHTTPメソッドについて

## HTTPメソッドとCRUD操作
HTTP（Hypertext Transfer Protocol）は、ウェブ上でデータをやり取りするための通信プロトコルです。

CRUDはHTTP通信を介してデータをやり取りする際の操作であり

・データの生成（Create : POST/PUT）
・読み取り（Read : GET）
・更新（Update : PUT）
・削除（Delete : DELETE）

の四つの種類が主に使用されます。

## GETメソッド
GETメソッドはリソースの取得に使用されます。
クエリパラメータをURLに組み込み、サーバーに情報をリクエストします。
ブラウザでウェブページを開くとき等に使用されます。

## POSTメソッド
POSTメソッドはクライアントからサーバーにデータを送信するときに使用されるメソッドです。
GETはURLの長さに制限があるのに対し、POSTはデータの送信量に制限がありません。
フォームの送信や記事の投稿等に利用されます。

## PUTメソッド
PUTメソッドはリソースの更新、作成を行うためのメソッドです。
既存アカウントや記事の更新等に利用されます。

## DELETEメソッド
DELETEメソッドはリソースの削除に使用されるメソッドです。
リクエストによって指定されたリソースが削除されます。
既存アカウントや記事の削除等に利用されます。
Appleにおけるdeprecatedを考察する

# Apple APIの話です。
専門性もなく、所感を綴るのみであり、誰かの知的財産になり得るものではありません。
雑多なメモです。
しかし事実と異なる点があれば指摘くれると嬉しいです。

## deprecatedってなんなの？
まず読み方がわかんないよ。
一応、デプリケイティッドと読んでます。
意味は廃止です。
depreがガラクタといった意味があるのではないでしょうか？
プラネテスという漫画で宇宙に漂う宇宙ゴミをデプリと称していました。ゆえに、de/precatedではなく、depre/catedと分解して解釈するのが、わたしの推論です。
根拠は先程のプラネテスのみです。

## なんでAPI、deprecatedにしてしまうん？
節子みたいな表題になってしまったが、Appleはなんでせっかく作ったAPIをdeprecatedにしてしまうんでしょうね？
いや、もっとええもん出来たからやろとか、前のやつは、いろんな法律の兼ね合いで使ったらあかんなったからやろとか色々あるとは思うんですよね。
しかしですよ。
なぜそれにiOSエンジニアは戦々恐々とするのでしょうか？
そちらこそ問題なんですよ。
面白いですよね。
たった一つの会社の言いなりになって、ものづくりに励むんですよ。
弱者と称されるにふさわしい働き方です。

## このAPIは、どうして動くの？
そんななか、不思議なAPIに出会いました。
deprecatedとリリースノートで処刑予告されたのに、動くんです。
ゾンビでしょうか？いえ、APIです。
節子、それおはぎや無い、おはじきでもない、APIや。
清太のツッコミは、上流家庭の御子息ということもあって、弱いっすね。

## 動かないAPIと動くAPIは何が違うの？
動かないやつは、処刑される日が明記されています。
こっちが処刑されたやつです。
13で導入したけど16では動かないって書いてます。
`@available(iOS, introduced: 13.0, deprecated: 16.0, renamed: "UISceneSession.Role.windowExternalDisplayNonInteractive")`
こっちは、オルタナティブな処刑ですね。
実際には無罪放免とちゃうんか？

`@available(iOS, introduced: 2.0, deprecated: 100000, message: "Use nw_connection_t or nw_listener_t in Network framework instead")`
いえ、文字通りに解釈するとiOS100000のときに廃止されますね。
結構先ですね。私の曾孫かやしゃ孫に伝えたとしても、顛末を知りたい私の気持ちを引き継いでくれる人は見つかりっこないでしょうね。
でも、めんどくさいときはこういう文脈を使えばいいんだと思うと、後学になりますね。

## どうして削除したりするの？
そういえば、iOS17リリースくらいのタイミングで削除されたAPIもありました。
こういうドキュメントは残すもんじゃないのかと思いましたが、
NewsStandは失敗したから黒歴史みたいなもんなんですかね。
消してましたね。
検索しても見つけられないしURLしたりしてもNotFoundでした。

## 突然、deprecatedに遭遇した与太話
よくも見つけたなというdeprecatedを1件見つけたことがあります。
自分でもこれはよくやったなと思います。
自分のどこまでもどこまでも調べる粘着質な性格が功を奏したと思います。しかし、保険の保険のような検査のためのフラグだったので、チームの中では褒めてもらえませんでした。


## まとめ
Vision関連のAPIも面白かったです。
まとめる気もないなんて、雑記の中でも雑魚すぎるだろこれ。
「説得する」ということについて

この記事はZOZO アドベントカレンダー　Series1 18日目の記事になります。

# はじめに

組織を変えたい！講習や勉強会、イベントで知ったプラクティスや技術を採用したい、提案したいって意識が高い人ほどありますよね。

しかし、それを上司に説明して、ではやろう！とはならない、一笑に付されることも多いでしょう。

いくら説明しても理解してもらえない、なぜやらないのか？やる気がないのではないか？そんな愚痴を他に漏らすことなんて経験ある方もいるでしょう。

やがてそれは、失望へと変わり仕事のモチベーションを落としたり転職を考えたりするかもしれません。

[「問いかけの作法」](https://www.amazon.co.jp/dp/B09LH1NKGV)という本ではそれを *「孤軍奮闘の悪循環」* と呼んでいます。

![スクリーンショット 2023-12-17 22.16.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/1091cff7-0a63-f936-e120-510c7a415e91.png)
※引用　[問いかけの作法　安斎勇樹 著](https://www.amazon.co.jp/dp/B09LH1NKGV)

「説得し」動いてくれると「期待する」。多くはこれができると思いこんで失敗し、そして勝手に失望し身動きが取れなったり衝突するのだと思います。

こういうとき、自分に取れる行動は以下の3つです。

1. 諦める
2. 勝手にやる
3. 相手が自分自身で心の底からやりたいと思ってもらう

# 自分に取れる行動　1. 諦める

1については「孤軍奮闘の悪循環」の結果、失望し諦めることです。これ以上説明することはないでしょう。

# 自分に取れる行動　2. 勝手にやる

2については、自分でまずはやってみるということです。問題があり、組織を変えたいという思い、このプラクティスや技術が役に立つという思いに気がついているのはまず自分だけということに気がついてください。
なので、まずは気がついている一人から始めることです。（参考：[「組織を芯からアジャイルにする」](https://www.amazon.co.jp/dp/B0B68VMJVZ)）

それってやったもの勝ち？と思われるかもしれません。そうです。やったもの勝ちなのです。それで怒られるかもしれません。ただそれを恐れるのであれば１の諦めるを選択するのが良いでしょう。
失敗したとしても一人でやっていることであれば損害もほとんどないでしょう。むしろ得られる「経験」「気づき」のほうが大きいと思います。その経験や気付きは他の仲間を増やすきっかけになるやもしれません。
もういちど言いますが、「問題があり、組織を変えたいという思い、このプラクティスや技術が役に立つという思いに気がついているのはまず自分だけ」なのです。まずは一人ではじめましょう。

# 自分に取れる行動　3. 相手が自分自身で心の底からやりたいと思ってもらう

３については、「こうしたほうがいい」「これを採用したほうがいい」と「説得」するのではなく、まずは「何が問題なのか？」を相手が自身で気がついてもらうということです。
つまり、「問い」を変えるということ。
ただし、説得してだめだった相手に自身で気がついてもらうのは非常に難しいことは理解する必要があります。
「今のプロジェクトでは何が問題だと感じていますか？」・・・そのように直で聞いてもおそらく無駄です。そもそもそれを自覚していたら提案は通るはずだからです。

必要なのは「問い方」。
たとえば、
「今のプロジェクトのやり方を一つだけ変えるとしたら？」「今のプロジェクトを１０点満点で表現するとしたら？」「プロジェクトのこれまでではなく、今週１週間だけに絞って振り返ってみると？」など返しやすい「問い」をしてみると良いでしょう。
上司だけではなく、他のメンバーも巻き込むといいでしょう。

上司やメンバーは何も理解していないのではないのです。ただやらないのでも、やる気がないのでもないのです。ただそれに答えるだけの「問い」がなかったために、気がつくきっかけがなかっただけなのです。

良い問いかけをするもう一つの効果として、チームが活性化し、チームのポテンシャルが発揮されるというのがあります。もしかしたら自分の思惑とは別の結論に達するかもしれません。それはそれで自分自身の想像を超えたチームの成長と捉えることができるでしょう。

![スクリーンショット 2023-12-17 22.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/d49e1460-e129-8d48-28b0-a617ce0621ad.png)
※引用　[問いかけの作法　安斎勇樹 著](https://www.amazon.co.jp/dp/B09LH1NKGV)

話は代わりますが、Scrumではスプリントを短く区切り（１週間、数週間など）、スプリントの終わりには毎回振り返りを行います。それはそれで一つの良い「問い方」であります。数ヶ月、数年を振り返っても良い意見は返ってこないでしょう。問いの範囲・期間を絞ることで良い気づき・アイデアを引き出すことを期待したプラクティスというわけです。

[Scrumガイド](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)ではScrumの価値基準のひとつに「尊敬」を挙げています（他に「集中」「確約」「公開」「勇気」があります）。
上図で良い問いかけが「信頼」につながるのがわかるかと思うのですが、それがお互いに「尊敬」し合うチームになっていくというのもよくわかりますよね。

さあ！組織を変えたい、講習や勉強会、イベントで知ったプラクティスや技術を採用したい、提案したいあなたに向けて、できることを３択に絞りました。あなたならどれを選びますか？また他の選択肢があればぜひ教えてください。

この記事があなたにとって「良い問い」になっていることを願っています。
マナビDXに学生/社会人の両方として参加して思うこと

# はじめに
こんにちは、マナビDXクエスト参加者の**ヒナタ**です！
昨年に続き、今年もマナビDXクエストに参加しています。
普段はデータサイエンティストとして働いています。

このマナビDXクエストの詳細は下記リンク[^1]や他の参加者[^2]が詳しく書いてくださっているので、本稿では割愛します。
ちなみに余談ですが、昨日の<font color="Gold">***M_Murata***</font>さんの記事[^3]で私は初登場しています。

https://dxq.manabi-dx.ipa.go.jp/




昨年は就職活動を終えた大学4年生として、今年は社会人1年目として、
それぞれ異なる視点から学んだことを共有しようと思います。
マナビDXに参加を検討している学生、新社会人の方々への参加の後押しになれば幸いです。


## 目次

**1.** 学生目線でのマナビDXクエスト
**2.** 社会人目線でのマナビDXクエスト
**3.** *学生*と*社会人*としての差 

# 1.学生目線でのマナビDXクエスト
この章では、マナビDXクエスト参加1年目を時系列に沿って振り返ります。
## エントリーのきっかけ
大学3年生の時、就活中にインターンで出会った学生がデータ分析経験としてマナビDXを挙げていたことがきっかけでした。

私は当時、大学での研究や企業での長期インターンを通じたデータ分析、DXプロジェクトに関わっていましたが、マナビDXクエストのような**体系的に1からデータ分析、DX**を行う経験や、**自社以外の企業のDXを進める**といった経験がなかったため　マナビDXクエストを魅力に思い、参加を決意しました。
## 参加してみて
就職活動も終わり、データサイエンティストとしての就職が決まっていたこともあり、2022年度のマナビDXクエストに参加し、DXプロジェクトの進め方を学びました。
その過程で、前述の<font color="Gold">***M_Murata***</font>さんをはじめ、既に社会でとても活躍されている方々と協力して企業へのDXに関わることのできる機会を得ました。

その過程で、
**1.自分の出来ること**
**2.自分のやりたいこと**
**3.相手の求めること**
の3点の擦り合わせがとても重要に感じました。

DXやデータ分析に興味のある方の多くはそれ自体がそもそも好きな人が多いと思います。
これは否定しません、<font color="DimGray">***エイキ***</font>さんの書かれていたように趣味がビジネスに繋がることは素晴らしいと思います。[^4]
一方で私が未熟だったからこその苦い経験として、
自分たちでは興味がある分析ばかりしていても、相手からしたらピンと来なかったり、必要ないなぁと思われていると感じることがありました。

自分の考えと、相手（評価者）の考えの差異を意識する必要性にその際に気づきました。
まだまだそれを完璧には実践できていませんが、社会人になる前に、これに気づけたことがマナビDXクエストに参加してのなによりの収穫でした。
特にこの意識は経験豊富な素晴らしい社会人の方々と一緒に同じ目線からプロジェクトを進めたことからこそ気づけたものだと考えます。

# 2.社会人目線でのマナビDXクエスト
この章では、マナビDXクエスト参加2年目の振り返りというよりは社会人になった後からの振り返りを記しますが、本稿での _言いたいこと_ は1章がメインでした。
社会人目線のお話は諸先輩方が書いてくださると思うので、ここでは簡単に触れます。

## マナビDXクエスト参加へのモチベーション

参加者からはさまざまな理由を聞きました。
+ DX関連経験を積むこと (→ DX関連キャリアへの転身)
+ リスキリング
+ 様々な業界の人との交流
+ ~~社会サービスの最大限利用（?)~~

私は**DX関連経験を積むこと**を目的として参加しました。
本業とは別のデータを扱ったり、別の方と関わることで自分の経験や能力の幅を広めようとしました。
その結果、分析の知見が増えました。
**+** でとてもうれしいことに、マナビDXクエストを通しての友人が増えました。
社会人になってから同業他社や志の近い友人が新しくできることはありがたいです。


# 3.*学生*と*社会人*としての差 
## 私の思う差
**学生と社会人としての差**は数多くありますが、私はその1つに**評価されることへの意識の差**があると思います。
社会人になる過程での面接や仕事の成否など定量的な点数はつかないものの、相手が居て、自身の成果に対しての良しあしを判断している人がいます。
そうした対象を意識して、何が求められているかを想像して叶えることが社会人として大事であり、マナビDXクエストを通して学ぶことが出来ました。
学生の際にもペーパーテストや普段の生活でそうした機会があるかとは思いますが、社会人として何年もそれらを体感している経験豊富な人達と同じ立場からこれを経験できる場というのは貴重です。

# まとめ
マナビDXクエストでは業務経験を詰めたり、友達作りができます！
ぜひ参加して、楽しみましょう！！



明日はkmtさんの別視点からのマナビDX2年生記事ですので、そちらも見てみてください。

[^1]: マナビDXクエストの公式ホームページ
[^2]: https://qiita.com/advent-calendar/2023/manabi-dx-quest2023
[^3]: https://qiita.com/M_Murata_ds/items/10f8bc5a6a4c5aa0b7da
[^4]: https://qiita.com/eikidesu/items/206a859f0418907ce9b0
Jetpack Composeやってみる

本記事は[Life is Tech! Advent Calendar2023](https://qiita.com/advent-calendar/2023/life-is-tech)の18日目の記事です！
やっほおおおおおお！！関東Minecraft&Unityコースのメンター、ことりだよ🐣

最近、マイクラやUnity以外に、実はAndroidの開発もしてるんだよね👀
Kotlinでコード書いてたらこの前、Minecraftコースのはるっぺに「ことりん、Jetpack Composeって知ってる？やってみるとおもろいよ！」って言われたの！！

### 何それ、、、👀！！！

気になったので調べてみた👀

## Jetpack Composeって何？
[Developer.Android.com](https://developer.android.com/jetpack/compose?hl=ja) によるとJetpack Composeというのは、
「ネイティブ UI をビルドする際に推奨される Android の最新ツールキット。Android での UI 開発を簡素化し、加速します。少ないコード、パワフルなツール、直感的な Kotlin API を使用してアプリをすぐに動かすことができます。」とのこと。

Life is Tech!での教科書はUIをxmlで、機能面のプログラムをKotlinで書いていく手法をとっていますが、どうやらこのJetpack Composeは、UIもKotlinでかけてしまうという...！！

早速やってみよう！
今回は、Jetpack Compose を使用する最初の一歩 [Composeの基本](https://developer.android.com/courses/pathways/jetpack-compose-for-android-developers-1?hl=ja#article-https://developer.android.com/jetpack/compose/tutorial)「スターターのためのチュートリアル」というものを使って開発していくよ！

![スクリーンショット 2023-12-17 16.45.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820157/d823571c-730f-eaf2-9572-cae35f7cfe4c.png)
Empty Activityを選択して、開発スタート！！

まずはテキスト要素を追加していきます！

``` Kotlin:MainActivity
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard(Message("Android", "Kotori"))

            OriginalAppsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting("Android")
                }
            }
        }
    }
}

data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message) {
    Column {
        Text(text = msg.author)
        Text(text = msg.body)
    }
}

@Preview
@Composable
fun PreviewMessageCard(){
    MessageCard(
    msg = Message("やっほー！", "ことりがKotlinを開発しているよ！")
    )
}



@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "開発 $name!",
        modifier = Modifier
            .background(Color.Red)
            .padding(5.dp)
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    OriginalAppsTheme {
        Greeting("楽しい")
    }
}
```

チュートリアルに従って、こんな感じで書いてみました！
xmlとはちょっと違った書き方で、Modifierのところのbackgroundの色設定やpaddingがHTML/CSSのような感じがして面白い！と感じました！！
実際にpreviewしたものがこちら！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2820157/86ca1b9f-6b54-2caf-917d-f785e7036a98.png)

### すごいね👀


## まとめ
HTML/CSSの要素が入っていて、xmlも楽しいけどこっちも楽しいって思えたよ！！
色々まだわからないことが多いから、この後もやってみるよー！！


見てくれてありがとう！！
また次のキャンプでね〜〜！！🐣
MIXI Bug Shooting Challengeへ参加してきました！

## 参加までの経緯

以前はdiscordのbot開発を趣味でやっていましたが、勢い余って最近はWeb開発もしています。（私個人として）怠りがちな、サービスの不具合修正に対する戦略がテーマとなっており面白そうだったので参加しました。

## 概要

### やったこと

ユーザーからの不具合問い合わせの文章を読み、

1. ログを抽出して分析
2. 原因を推定・記録
3. カスタマーサポートへ調査結果を報告
4. 必要があればコードを修正してPR
5. 同様のバグを今後起こさないための解決策を考える

ということをしました。主にバックエンドでの操作が多かったです。

### 仕様した技術

- Big Query
- Next.js
- Go
- PostgreSQL

### スケジュール

11:00 ~ 12:00 講義
12:00 ~ 13:00 昼食
13:00 ~ 14:00 環境構築
14:00 ~ 18:00 実践
18:00 ~ 19:30 懇親会


### 内容について

午前の講義では不具合対応の流れや、そもそもなぜ不具合対応が必要なのかについて学びました。さらに、システム構成の解説もあり、Clean Architectureという関心事を分離させるための戦略についての学習もしました。初学者にもやさしく、スライドや解説がとても分かりやすかったです。

昼は本ワークショップに参加している他の学生さんやMIXIのエンジニアさんたちと一緒に昼食をとりました。牛タン弁当が美味しかったです笑。エンジニアさんとの会話では、社内の雰囲気や仕事の様子、扱う技術の話など沢山できて楽しかったです。会話のなかでは自分の知らないことも沢山あり自分の未熟さを思い知ると同時に、便利な技術も教えてもらえてとても勉強になりました。個人的にモンストが好きで8年くらいやっているのですが、モンストに関わった技術的な話も聞けて大満足です笑。

午後はいよいよワークショップに取り組みました。形式は2人のペアワークで、3(+extraで1)つの問題をそれぞれ制限時間内に取り組みました。ログとって分析、調査結果をまとめる、バグを修正するっていう作業は意外に時間かかるので、二人でうまく分担することが大事だなって思いました。どこまでわかってどこが分からないか、何を知りたいか、どうすれば解決しそうだとかを思いついたらさっさと共有することがポイントです。(自分から見て)3問中, 2問はほぼ正答,　最後の1問は原因を特定できたものの、実装ができずアイデアのみを答え終了となりました。最後の問題は、自分のGoへの知識の浅さが原因となっていたので悔しかったです。問題が実務でも起こりうるテーマになっていて実践的な経験が得られました。1問ごとに得られた知識や教訓が多くとても有益でした。取り組み時間の間は常にエンジニアさんが巡回してみていてくださり、分からない部分は丁寧に教えてもらえました。また、よりよい解答（つまり不具合調査に対するベターなアプローチ）をするにはどうするかを私たちに問いかける形式で導いてくださり、バグ調査に限らずエンジニアリングする上での考え方も知ることができました。

最後は優勝チームの表彰 & 懇親会がありました。私たちのチームは優勝できませんでしたが、今後のモチベーションアップにつながったので良かったです。懇親会では昼と同様にエンジニアさんや他のメンバーと話しました。勤勉で博識な他の方々と触れられ良い刺激になりました。個人開発だと自分で調べたことしか得られませんが、人と話すと自ずと一人では出会わなかっただろう技術や考え方のキッカケを得られるのはお得ですよね笑。


## 感想

初めてのワークショップ参加でしたが、MIXIさんの手厚いサポートにより贅沢な環境で楽しく学ぶことができました。こういうイベントは勉強することの他に、モチベーションの向上や他の人と情報交換できたりと良いこと尽くめなのでまた機会あれば参加したいです。最後になりましたが、本イベントを企画・運営してくださったMIXIの方々には感謝申し上げます。
Pythonの仮想環境どれ使うべきか[初心者]

### 1. はじめに
Pythonの仮想環境管理するために複数の選択ありますよね。conda, Virtualenv, venv, pipenv, poetry…
なぜ使うかと言うと、

- 依存関係の衝突回避：異なるプロジェクト間でのライブラリの衝突を防ぐ
- クリーンな開発環境の確保：必要なパッケージのみをインストールし、環境を整理する
- プロジェクトの再現性向上：他の開発者が同じ環境を簡単にセットアップできる
- デプロイメントの簡素化：開発環境と本番環境の違いを最小限に抑える
- 開発者がプロジェクトの依存関係をより簡単に管理し、コードの品質とプロジェクトの安定性を向上させる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/d93cafc8-e94a-9cc2-9405-2cd3ca551a7e.png)

:::note
よくわからない方へ：小難しいことを書きましたが、ローカル環境にいろんなアプリ・プロジェクト作るとライブラリのバージョンとか、よくわからない競合があって予想しないようなエラーにあって大変になることあります。1つ1つのアプリを新品のPCに入れる感覚で作れたら、そんなエラーないよねってことで、擬似的に綺麗な新品の環境作るのが仮想環境だと思えばいいと思います。
:::

## 2. 仮想環境ツールの比較

Pythonのプロジェクト管理において、仮想環境は開発効率とコードの品質を保つ上で欠かせない要素です。ここでは、Pythonの仮想環境を管理するための主要なツールを比較します。

### Conda
- **適用分野**: Condaは、特にデータサイエンスや機械学習プロジェクトに。Python以外の言語のパッケージも管理できるため、複雑なデータ分析環境のセットアップに強み
- **特徴**: 複数のプラットフォームに対応し、非Pythonの依存関係も扱えます。ただし、他のツールに比べるとやや重たいから私は嫌い
- 商用は有料らしい。個人は無料

### Virtualenvとvenv
- **Virtualenv**
  - **概要**: サードパーティ製のツールで、Python 2を含む古いバージョンのPythonにも対応
  - **特徴**: 複数のプロジェクト間で依存関係を隔離し、独立した開発環境を作れる

- **venv**
  - **概要**: Python 3.3以降に標準で組み込まれた仮想環境ツール
  - **特徴**: 標準機能であるため、Python 3を使用するプロジェクトにおいては最も基本的な選択肢

### Pipenv
- **目的**: 仮想環境の管理と依存関係の解決を一元化し、シンプルで使いやすい。私は好き
- **利点**: `Pipfile`と`Pipfile.lock`を使用して依存関係を明確にし、プロジェクトごとの環境を簡単にセットアップできます。また、セキュリティの脆弱性をチェックする機能もある

昔記事書いたので使い方は良ければ見てください。

https://qiita.com/Bashi50/items/7eff0a2ba66cd0604447

### Poetry
- **機能**: 依存関係の管理だけでなく、パッケージの作成と公開もある
- **比較**: Pipenvと比較して、Poetryはより複雑な依存関係を扱うことができ、パッケージングと公開のプロセスが統合されてる。これにより、ライブラリの開発者にとってはいいらしい

### PipenvとPoetry
PipenvとPoetryの違いがわからん！となりそうですね。

### Pipenv

主に開発ワークフローの簡素化を目指しており、特にアプリケーション開発者向け
1. **依存関係の管理**：依存関係の管理には`Pipfile`と`Pipfile.lock`を使用し、これは従来の`pip`の`requirements.txt`ファイルを置き換えてるかんじ
2. **仮想環境の管理**：プロジェクトのための仮想環境を自動的に作成し管理
3. **パッケージのインストール**：パッケージをインストールし、自動的に`Pipfile`に追加される
4. **ワークフロー**：アプリケーション開発のためのシンプルで明確なワークフローを重視し、依存関係と環境を管理するための簡単なコマンド使える

### Poetry
アプリケーションとライブラリの開発者の両方使える。パッケージングと配布に重点を置いています。

1. **依存関係の管理**：依存関係の管理には`pyproject.toml`を使用し、これはPEP 518で指定されたファイル形式で、ロジェクトのパッケージングとビルドに関する包括的なツールを目指している
2. **仮想環境の管理**：Pipenvと同様に仮想環境を管理。依存関係の解決をより洗練された方法になってる
3. **パッケージのインストールとビルド**：依存関係の管理だけでなく、ライブラリとアプリケーションのビルド、パッケージング、公開を容易かつ一貫性のあるものにできる
4. **依存関係の解決**：Pipenvと比べてより強力な依存関係リゾルバーを持ち、複雑な依存関係のツリーをより良く扱うことができる
5. **ワークフロー**：プロジェクトの作成から依存関係の管理、パッケージング、公開に至るまで、プロジェクト管理のより全体的なアプローチ

### 主要な違い
はっきり言って使い勝手は似てます。Poetryの方が多機能というべきでしょうか。

- **設定ファイル**：Pipenvは`Pipfile`と`Pipfile.lock`を使用し、Poetryは`pyproject.toml`と`poetry.lock`を使用。`pyproject.toml`はプロジェクト設定の統一を目指す新しいアプローチ
- **依存関係の解決**：Poetryはより進んだ依存関係リゾルバーを持ってる
- **パッケージングと公開**：PoetryはライブラリのパッケージングとPyPIへの公開のための組み込みサポートを提供し、ライブラリ開発者にとってより適した選択肢
- **シンプルさと包括性**：Pipenvは基本的なアプリケーション開発においてよりシンプルで直接的と見なされることが多い一方で、Poetryはアプリケーションとライブラリの両方のライフサイクルをカバーするより包括的なソリューションを提供

### どれつかえばいい？
丸投げ感ありますがプロジェクトの要件や個人の好みによって適切なものを選択したらいいです。
Condaは複雑なデータサイエンスプロジェクトに、PipenvとPoetryはより一般的なPython開発に適しており、venvは最近のプロジェクトならまずどこでもデフォルトで入ってるからその点で結構利点あり。

#### PoetryとPipenvどっちつかう？
ライブラリの管理が重要！って場合やライブラリ開発したいって言うならPoetry
普通のアプリ作るならPipenvって感じでいいのではないでしょうか。Pipenvの方がシンプルで、アプリ作る上ではそれほど問題ないので。

私は、勉強や趣味で簡単なアプリ作ったりする時は`Pipenv`使います。一番新しいのはPoetryなのでそっちでもいいと思います。
【Go言語】エラーを扱う

Go言語の**エラー処理の特徴**と、一般的な**エラーハンドリングの方法**について説明する

### エラーは値
Goのエラーは`error`型のインターフェースを満たした単なる値として扱われる。
`error`型は`int`型などと同様にGoのランタイムに組み込まれている型で、インターフェースとして定義されている。
`nil`値でエラーがないことを表す。

```go
type error interface {
    Error() string
}
```


errors.New()関数を使ってエラーを作成することが一般的。
```go
func New(text string) error {
    return &errorString{text}
}

type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}
```

### panic()は使わない

Goには`panic()`関数が存在し、プログラムを強制的に終了させることができるが、通常はエラー値での処理が推奨されている。


### エラーハンドリング

Goの一般的なエラーハンドリングは、関数から返される末尾の戻り値として`error`型を定義する。

```go
func ReadFile(name string) ([]byte, error) {
    // ...
}
```
エラーが発生したかどうかは、戻り値の`error`型が`nil`かどうかで判断する。

**ガード節**を使用して、早期にエラーを処理し、ネストを浅く保つことが一般的。

```go
f, err := os.Open("important.txt")
if err != nil {
    // エラーハンドリング
}
// ...
```


### 他言語との違い

* Goのエラーハンドリングは他言語の例外処理と異なり、**戻り値を確認してハンドリングするスタイル**
Javaなどでは例外機構があり、`try、catch、finally`を使用するが、Goでは`error`値でエラーを表現し、**呼び出し側で処理**


## 参考
https://www.oreilly.co.jp/books/9784873119694/
PlanetScaleでフェイルオーバー中のダウンタイムがごく稀に長いときがある

この記事はMySQL Advent Calendar 2023 22日目の記事です。

# はじめに
個人サービスでPlanetScaleを利用しているのですが、ある日突然以下のエラーが発生しました

```
primary is not serving, there is a reparent operation in progress
```

このエラーによって、DBが2時間程利用出来ない事態に陥りました。エラーの内容からプライマリサービスが機能していない以外に原因がわからなかったので対処した内容をまとめます。

# エラーが起きたときの状態

読み取り行数が56億と少し多いサービスとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/e3a20a72-10a5-d4c0-ce7c-0ca8b8c4d3e3.png)

異様な数字に見えますが、以下のリンクにて「Rows read is a measure of the work that the database engine does,」と書いてあり、単純な読み取り行数ではないため負荷状況はQuery Insightsから確認する必要があります。

https://planetscale.com/docs/concepts/billing#understanding-rows-read


# 原因はVitessらしい

結論から言うとPlanetScaleが利用しているVitessというアーキテクチャによりエラーであり、バッファサイズが足りない場合に発生するようです。MySQLが出しているエラーではありません。詳しくは以下に記載してあります。

https://vitess.io/docs/16.0/reference/features/vtgate-buffering/#primary-not-serving

Vitess（ヴィテス）とはYouTubeの開発チームがMySQLのスケーラビリティの課題を解決するため作ったデータベースソリューションであり、PlanetScaleの特徴であるノンブロッキングマイグレーションなどの機能はVitessが提供している機能の1つとなります。

# 復旧

フェイルオーバー中なので待てばいずれ復旧するのですが、何個か対処できることがあるので記載します。

## 辛抱強く待つ

一番シンプルな方法です。私の場合は2時間止まっていたので待てませんでしたが余裕があれば辛抱強く待つことでいずれ完了します。正直なところ、私はすごく焦ってしまい[msccccさん](https://twitter.com/mscccc)というPlanet Scaleの中の人にメンションを飛ばして改善策を聞きました。早急なご返信と丁寧な回答いただきすごく助かりました:pray_tone1:

## バックアップから復旧する

バックアップからブランチを作成し、プライマリブランチを切り替える方法です。私はこの方法を利用しました。バックアップは1Gで0.023ドルなのでケチらずに細かく取るのもリスクヘッジにはなるかと思いました。

# 改善策

今後、フェイルオーバー中のエラーが発生する確率を下げるための改善策です。

## プランを上げる

一番シンプルな方法です。Scaler Proからメモリサイズを選択できます。どのプランにあげればよいかわからない場合はサポートに問い合わせると教えてくれます。さらにどのクエリに負荷が掛かっているか、何をしたらコストが下げられるかなどアドバイスしてくれます。ちなみにPS-40を推奨されましたが平凡なサラリーマンにひと月119ドルはきつい...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/cf9e7916-39b7-bb0f-072e-4819285ad1b9.png)

## クエリを見直す

負荷が高いクエリを見直すことでバッファサイズを軽減することができます。Query Insightsで読み取り行数など確認出来るので負荷が高いクエリを調べることができます。ここでは適切なインデックスが貼られているかなどに注視してもよいでしょう。

なんとダッシュボードからEXPLAINを実行できます！`EXPLAIN`を実行するには該当の行を選択しshow explain planを選択すると実行できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/80056898-e25b-f58e-4bb3-f2d32ba0b97d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/cd3095d8-64da-6657-2685-9f904fe652d5.png)


## 不要なクエリを削除する

当然ですが、利用する必要のないクエリがないか見直しましょう。私の場合はここが原因でした。効率的なクエリや適切なインデックスにばかり意識が行ってしまい、肝心な不要な呼び出しがあることに気がつくのが遅くなりました。一番先に確認しても良い観点かもしれません。

# まとめ

上記の改善により56億readから11億readまで改善しバッファサイズの減少、パフォーマンスの改善が出来ました。まさかフェイルオーバー中にエラーが発生して復旧が遅くなるなんてことは想定していなかったため驚きました。適切なDB設計が出来ていないことや単純なミスが要因となってしまったのであまり遭遇することはないかもしれませんが困っている方のお役になればと思い書きました。PlanetScaleは比較的リーズナブルとはいえそれなりのコストがかかりますので、まずはクエリやサービスに問題がないかチェックした方が幸せになるかもしれません。

# 参考

https://github.com/vitessio/vitess/issues/9908
https://github.com/vitessio/vitess/issues/6206
Amazon Connect 日本の携帯電話発信制限解除

ジャーニーマン( @beajourneyman )です。

今回は「[セゾン情報システムズ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/sisco)」のシーズン2の17日目の記事になります。せっかくシーズン2が立ち上がったのに枠が埋まっていなかったので、ライトなテーマではありますが追加エントリーしました。

# 今回のテーマ「Amazon Connect の日本の携帯電話発信制限解除」
前回は Amazon Connect の電話番号取得についてまとめました。今回は一部の国/地域で必要になる発信制限の解除について簡単にまとめます。以下エントリーの続編になります。

https://qiita.com/beajourneyman/items/d385bf9e139048630038

ご注意：本エントリーは日本の携帯電話向けを対象とし、Amazon Connectのコンソールは基本的に「日本語」を選択しております。また、サポートケースを直接起票できない他社提供の請求代行を使っている環境での手順となります。

# 日本の携帯電話発信制限について

日本の携帯電話への発信はデフォルトでは制限されています。電話番号取得が終わったタイミングで、試しに発信するとエラーがでます。

https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/country-code-allow-list.html

> 次のプレフィックスに続く日本の携帯電話番号は、デフォルトでは許可されていません。
+8170、8180、8190
このような日本の携帯電話番号に発信するには、サービスクォータ引き上げリクエストを送信する必要があります。

電話番号取得の際のように、AWSサポートへ別の上限緩和申請が必要になります。

# ChatGPTに制限されている理由を聞いてみた

これだけでは、シンプルすぎるので、gpt-4に「なぜ Amazon connect では日本の携帯電話の発信がデフォルトでは制限されているのですか？」を聞いてみました。

>Amazon Connect で日本の携帯電話への発信がデフォルトで制限されている理由は、主に次の3つです。
>
>1. **コスト**: 日本の携帯電話への通話料金が高い場合があるため、誤って高額の電話料金が発生しないようにデフォルトで制限がかけられています。
>
>2. **規制および法律の遵守**: 日本における電気通信事業やデータプライバシーに関する法律や規制の遵守のため、制限が設けられています。これは、事業者や使用者が不適切な目的や方法でサービスを利用することを防ぐことを目的としています。
>
>3. **悪意のある行為の防止**: 不正な利用が発生しないように、デフォルトで制限が設定されています。これにより、スパムやフィッシング、いたずらなど、悪意のある行為を抑止することができます。
>
>ただし、この制限は Amazon Connect の設定変更によって解除することが可能です。適切な認証情報などが提供されることにより、日本の携帯電話への発信が可能となります。これによって、Amazon Connect を適切に使用する場合には、制約を受けることなくサービスを利用することができます。

さすがです。きちんと上限緩和申請について触れているあたり、アシスタントとして優秀ですね。2.と3.は想像通りでしたが、理由の1.は意外でした。発信者側のコストに対するガードレール的な側面なんでしょうか。

# 日本の携帯電話発信制限緩和申請

では上限緩和申請をしていきます。こちらは、電話番号取得時のような証明するための申請書類は必要ありません。通常の上限緩和申請と同様の申請を行います。以下にテンプレートを掲載します。

> ＜ビジネスへの影響詳細＞
お客様の業務改善を行うため新たにロボットコール(IVR)導入を推進しており、デリバリーの遅れが業務改善の立ち遅れに繋がる。
>
>＜件名＞
日本の携帯電話番号(+8170,+8180,+8190)への発信制限の解除のご依頼
>
>＜説明＞
Amazon Connectにてロボットコールを行うため、
日本の携帯電話番号(+8170,+8180,+8190)への発信制限の解除のリクエストをいたします。
>
>利用目的：日本の携帯電話向けロボットコールシステムの開発・テスト・本番稼働のため
>利用頻度：テスト架電を行う頻度(テスト実施期間中は1日にnn回程度)、本番架電では1日に最大nn件程度
>
>AWSアカウントID：
>
>ConnectインスタンスARN：
arn:
>

具体的な架電見込みを添えると、実際の運用イメージをお伝えできるので要件整理段階で非機能要件として、ボリュームを確認しておくと良いでしょう。こちらは一斉架電の性能面でも考慮する数字になります。

今回、「料金無料通話番号(トールフリー番号)」「ローカル交換キャリア番号の DID (直通ダイヤル)」をそれぞれの日本の携帯電話発信制限解除を申請し、どちらも翌営業日には制限解除の連絡をいただき発信できるようになりました。リードタイムとして適正かは分かりませんが、実績値として添えておきます。ご参考になれば幸いです。

以上です。
.onionドメインにTorブラウザを使わずにアクセスする方法


# はじめに

この記事は、Qiita Advent Calendar 17日目の記事です。
以下の記事より、すべての記事をご覧になれます。

https://qiita.com/0_terarin_0/items/0f367210e2465f7772c9

# 筆者について

- 現在高校２年生
- 水泳部マネージャー
- 生徒会長
- とある団体の代表

# 本編

.onionドメインにTorブラウザ以外から接続（全通信をTorネットワーク経由で行う方法）について、備忘録がてら載せておきます。（いつもの記事に比べたらめちゃめちゃ軽めの記事です。）なお、環境はMacですが、同様の手順を踏めばWindowsでもできると思いますのでぜひ。

まず、Homebrew経由でTorをインストールします。

```zsh:shell
brew update
brew upgrade
brew install tor
```

これで、Tor自体の設定は完了です。続いて、MacにおけるSOCKSプロキシの設定方法です。

![Screenshot 2023-12-17 at 22.44.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/31d0d512-0543-c793-9535-f9ba3241fec4.png)

デフォルトでは127.0.0.1:9050が接続先となります。したがって、その通りに設定したら終了です。

## 動作を確認してみる

実際にアクセスしてみましょう。下記にDuckDuckGoのオニオンドメインにアクセスしてみます。

https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/

![Screenshot 2023-12-17 at 22.51.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/b89d2e49-e38a-f731-3f9f-ac17070c5bf5.png)

無事アクセスできましたね！おめでとうございます！

## やめたほうがいいこと
 
以下、Tor接続でやめておいた方がいいことを記しておきます。

- 違法取引がされているサイトへのアクセス
- 金融取引
- 必要最低限以外のTor接続を利用したアクセス

ちなみに、3個目はシンプルにアクセスが拒否されることが多い上に速度も低いので、普通のWebさいとをTor経由でアクセスすることは全くお勧めしません。

## 何がいいの

さて、このTorのプロキシを設定するとどんなことが可能となるのでしょうか。

- PythonなどのプログラムでのTor接続
- 他の端末からのアクセス（SOCKS対応かブリッジ対応）
- Tor Browser以外の利用

ちょっとマニアックな方向けの機能ばかりになりそうですね。ちなみに、2個目の方はまだ試したことがないんですので、もしやることがあればそのときに追記したいと思います。

# 最後に

今回は軽く、備忘録がてらTor接続の使い方について記述しました。もしTorのことで追記することがあれば随時更新していきたいと思います。6ということで、今後のアドカレ 23 の記事をお楽しみにしてください。

https://qiita.com/0_terarin_0/items/0f367210e2465f7772c9
Pybricks 独自デバイスの作成

# はじめに

Pybricks の API ドキュメントの中には[独自デバイス用](https://docs.pybricks.com/en/latest/iodevices/pupdevice.html)のものがあります。

![スクリーンショット 2023-12-17 21.59.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/1ff8db89-a090-c4cd-1ac8-acd633d3fc09.png)

しかし、独自デバイスの作り方に関するドキュメントは見当たりませんでした。本記事では独自デバイスに挑戦してみたことを書きます。

# ハブとデバイス間の通信プロトコル

ハブに繋げられるデバイスの多くはマイコンを内蔵していて、ハブとUARTでシリアル通信しています。通信プロトコルについて Pybricks で解析したドキュメントは[ここ](https://github.com/pybricks/technical-info/blob/master/uart-protocol.md)にあります。見てみると、けっこうめんどうくさいプロトコルです。

プロトコルの概略は次のようなものです。

* *システムメッセージ(2400bps)*<br>デバイス情報をハブに通知するメッセージ
    * デバイスID
    * モード数
    * 通信速度
    * デバイスバージョン(ファームウェア、ハードウェア)

* *モード情報メッセージ(2400bps)*<br>各デバイスモードの情報をハブに通知するメッセージ
    * モード名
    * データサイズ
    * 生データ値の範囲
    * パーセントデータ値の範囲
    * SI単位データ値の範囲
    * 単位名
    * マッピング(絶対値か相対値か、NULL値を許すかなど)
    * 値のフォーマット(データセット数、バイト数、全体桁数、小数部桁数)
* *送信データメッセージ(システムメッセージで通知した通信速度)*<br>実際のデータ送信
    * デバイスモード
    * データ長
    * データ値

# 通信に使うピンとケーブル

[13日目の記事](https://qiita.com/inachi/items/02a92cb369df6444b0f0#%E5%85%A5%E5%87%BA%E5%8A%9B%E3%83%9D%E3%83%BC%E3%83%88)にも書いたとおり、UART の通信にはコネクタの5番と6番を使います。

![スクリーンショット 2023-12-13 22.26.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/da4e121d-91c1-d0f1-269b-218c58593431.png)

ポートのピン構成は次のようになっています。

| ピン | ラベル | 機能 |
|----|-----|-----|
| 1 | M1 | モータ出力用 |
| 2 | M2 | モータ出力用 |
| 3 | GND | グラウンド |
| 4 | VCC | 3.3V |
| 5 | D1 | UART(ハブ→デバイス) |
| 6 | D2 | UART(デバイス→ハブ) |

問題はケーブルです。独自デバイスのためにセットに付属のケーブルをぶった斬るのはもったいないですが、純正品の個別販売もしていないようでした。

AliExpress に互換品がないか探したところ、使えそうなのがありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/06f07f12-0d59-afa7-6f3f-0ec52ddde389.png)

これに、ピンソケットを半田付けして、独自デバイスの実験用にしてみました。

![IMG_7221.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/d4ffbbfb-959a-dae5-b78f-2585e5aab754.jpeg)

# 独自デバイス作成

独自デバイス用のマイコンとしては XIAO RP2040 を使いました。センサーとしてはLEGO純正で絶対に出そうもない人感センサーを選んでみました。

結果、作ってみたのが以下のようなもので、人感センサーが反応すると、Color Light Matrix が点灯するものです。

![スクリーンショット 2023-12-17 22.24.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/ece7c830-14aa-2ab5-f1f1-df63503b13c6.png)

デバイス側スクリプトとしては[ここ](https://github.com/antonvh/SerialTalk/tree/master/serialtalk_lpf2)にあるものを参考にさせてもらい、独自デバイスを拡張できることを確認できました。
やっぱ LaTeX 書くときに Overleaf 便利だねって話。

こちらは 「[法政大学情報科学部 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/cis_hosei)」 20 日目の記事になります。

# はじめに
このカレンダーもついに 3 年目ですね。今は 4 年で、もうすぐ (うまくいけば) 大学卒業です。
現在、論文を執筆しているんですが、情報科学部は理系学部なので、LaTeX を使用した論文執筆を行う研究室が一定数あります。
TeX Live + VS Code + LaTeX WorkShop なんかで書くのが今どきの TeX の書き方ですが、
主に環境構築に時間 (No GUI で 5GB のダウンロード) がかかったり、設定多かったり、設定ちょっとでもミスるとエラー出たり、モジュール足りないって怒られたり...結構面倒で、
さらにパソコン変えましたなんて言うと結構絶望的だし、設定した PC でしか書けないからスマホで移動時間に確認するなんてできないし...
自分にとっては面倒が過ぎました。

そんな時 [Overleaf](https://www.overleaf.com/) に出会って、感動したので、後輩にこう言う選択肢もあるんだぞってことでここに書いておきますね。

# Overleaf とは
インストール不要でブラウザベースで使用できる無料の LaTeX エディタです。
オンラインでのコラボレーションとかもできます。
スマートフォンでも (正直使いづらいですが、内容を確認するくらいなら) 使えます。

https://www.overleaf.com/

元々は Overleaf, ShareLaTeX という 2 つのプロジェクトがあったそうなのですが、
Overleaf に吸収され、今は Overleaf v2 となっているらしいです。

余談ですが、Overleaf (旧 ShareLaTeX) プロジェクトはオープンソース化されており、
自分のサーバでセルフホスト使用することも可能となっています。
Overleaf は、無料版だとコンパイル遅めなところがあるので、
筆者はセルフホストした Overleaf に TeX Live の Full バージョンを入れて動かして、そこで論文を執筆しています。
(ローカルで Docker Compose を使用して楽に執筆をできるようにもなっています)

https://github.com/overleaf/overleaf

# 使ってみよう
実際にテンプレートを用いて書けるところまでやってみます。

## アカウント登録
アカウント登録は簡単で、Google アカウントのログイン一発でいけます。

## 今回使用する TeX テンプレート
今回は情報科学部の卒論サイトで公開されている日本語の LaTeX 抄録テンプレート + 文献ファイルを使用できるようにします。

テンプレートは[こちら](https://cis.k.hosei.ac.jp/sotsuken/template/)。

## アップロード
ログインするとこんな感じの画面になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246409/161f0012-c929-6df0-5fc8-166312a78914.png)

左上の [New Project] > [Upload Project] で ZIP 圧縮された形式のファイルがアップロードできるので、手に入れたテンプレートをアップロードします。

もし ZIP 形式にするのが面倒だったら、
[New Project] > [Blank Project] で空のプロジェクトを作成して、
ファイルアップロードすることもできます。 (こっちの方がおすすめかも)

## 書けるようにする
そのままだと日本語が書けないってコンパイルエラーになるので、使えるようにしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246409/32c5fb4a-a95c-0431-79fa-88adf832d0aa.png)

左上の [Menu] > [Settings] > [Compiler] 項目の [pdfLaTeX] を [LaTeX] にします。

次に [Menu] 下の [New File] (ファイルマーク) のボタンを押し、
`latexmkrc` ファイルを作成します。

作成したファイルに以下を記述します。

それぞれの意味は、
1 行目は、LaTeX コンパイル時に走るコマンドを記載しています。日本語には platex が対応しています。
2 行目は、BibTeX (文献ファイル) コンパイル時に走るコマンドを記載しています。日本語には pbibtex が対応しています。
3 行目は、LaTeX はコンパイル後に dvi と言うファイルを作成します。そのファイルを PDF 形式に変換するとき走るコマンドを記載しています。日本語には dvipdfmx が対応しています。

```tex:latexmkrc
$latex = 'platex';
$bibtex = 'pbibtex';
$dvipdf = 'dvipdfmx %O -o %D %S';
```

## Congratulations🎉
これで書けるようになりましたね！
PC にインストールするよりも楽に、そして早く執筆を開始できるようになりました!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246409/cf052c01-056d-5d14-296d-58fb121a8c14.png)

# 終わりに
今年は論文執筆のために Overleaf おすすめするぞって記事書きました。
これが後輩に届いて、早めに論文執筆に取り掛かれるようになることを願っています。

卒業できるように頑張ります...。
ちょっと親切なマークアップ

## 概要
- ユーザーに対して親切なマークアップ
- コードを読む人に対して親切なマークアップ

この二点でみていきます。

## ユーザーに対して親切なマークアップ
とにかくJSが必要なUIが出てきたら注意しましょう。

まず以下を見ます。大体のUIはこれを見れば解決しますし、これ以上に複雑なUIがあるなら実装をやめてUIを考え直したほうがいいかもしれません。
俺の考えたイケてるUIをユーザーが理解できると思い込まないようにしましょう。
学習コスト0で使えるUIがベストです。

- https://www.w3.org/WAI/ARIA/apg/patterns/
- https://design-system.w3.org/components/

ライブラリがあるなら使ってもいいかもしれませんが、デモコードをみて無駄にdivで実装されているものがあったら使わないようにしましょう。

### アクセシビリティを学ぶ
これにつきます。
動いてたらいい　はもう卒業しましょう。


## コードを読む人に対して親切なマークアップ
### roleのあるタグを使う
a, button, header, ulなどわかりやすいタグは可読性が高いので積極的に使っていきましょう。
そもそも意味のあるタグを使って文章構造を作っていくのがマークアップです。

divだらけのマークアップはアクセシビリティの面でも最悪です。

### sectionタグを使う
よくある読みにくいマークアップとして、sectionタグをあまり使っていないというものがあります。

**基本的に見出しタグとそれに関わるコンテンツはsectionタグで囲むようにしましょう。**
これだけでかなり見通しのいいコードになります。

コンポーネント化できるのであればセクション単位で別コンポーネントに切り分けるのもおすすめです。
ここからここまでその前後と違う話してるな　と思ったらsectionで囲いましょう。

これ単体で別のページにできるな　と思ったらarticleにするのも検討しましょう。

セクションの中で導入となる部分にはheaderタグの使用もおすすめです。
見出しと導入分はデザイン的にもひとまとまりになっていることが多いので、headerタグに見出しと段落をいれると見やすいコードになります。

また、セクションは基本的にそのセクションがどこからどこまでの範囲を占めるのかを示すためにpaddingを指定しておくのがおすすめです。
背景色を敷かれた時に綺麗な見た目になるように意識してpaddingをつけるのがおすすめです。

sectionとsectionの間にmarginやgapを使うことはあまりないです。

### paddingの考え方
sectionでも書きましたが、paddingがあたるエリアに仮に背景色が付いたら綺麗な見た目になるか　を基準に考えるといいです。

marginやgapをつかうのかpaddingを使うのかはこれがいい基準になります。
いいデザイナーさんが作ったデザインはそもそも意識しなくても何で余白を作ればいいのか誘導してくれることが多いですね。

### before afterを使わない
装飾のためにbefore, after擬似要素を使うことも多いかもしれませんが、
CSSやHTMLを見てそのbefore, afterが何を意味するのか理解するのが難しいです。

spanタグを置いてしまってクラス名を振ったり別コンポーネントに切り分けたほうが読みやすいコードになります。

### CSSに意味を含める
例えば。

```html
<p class="mt-4">段落</p>
<p class="mt-4">段落</p>
<p class="mt-4">段落</p>
```

わかりにくいです。

```html
<div class="grid gap-4">
  <p>段落</p>
  <p>段落</p>
  <p>段落</p>
</div>
```
こうしましょう。

## Tailwind CSSを使っているときのコンポーネント編
上に書いた内容が活きてきます。

Tailwind CSSではユーティリティクラスを使用します。
ユニークなクラス名をつけることはあまりないので、どこまでが何を表すのかがわかりづらいHTMLが書かれてしまいがちです。

Tailwind CSSを使っているときは大体コンポーネントを作成できるライブラリやフレームワークがあると思うので、コンポーネント名に意味を含めるようにしましょう。

Tailwind CSSはクラス名の命名の手間がないことがメリットに上がることもありますが、読みやすいコードを書こうと思ったら命名はやはり必要です。

## まとめ
- アクセシビリティを気にしてマークアップしよう
- sectionを使おう
- 余白につかうmargin, gap, paddingに意味を持たせよう
- ユーティリティクラスを使っているときはコンポーネントを細かく切って名前に意味を含めよう
JSONファイルを操作する方法(Python)

# はじめに
JSON（JavaScript Object Notation）はデータのやり取りに広く使われる形式です。下記の記事で、JSON 形式についてまとめていますので、ご興味がありましたら、ぜひご閲覧ください。

https://qiita.com/skm_bnn/items/ecf3d0fe1188e666d079

本記事では Python で JSON 形式のファイルを作成と編集、複製、削除する方法についてまとめました。

# JSONファイルの作成
Python で JSON 形式のファイルを作成していきます。このプログラムでは、辞書型のデータ ```data``` を JSON 形式でファイルに書き込んでいます。

```python: makeJson.py
import json

# 作成するJSONファイル名
FILE_NAME = "data.json"

# データを定義
data = {
    "name": "John Doe",
    "age": 25,
    "city": "Example City"
}

# JSONファイルに書き込み
with open(FILE_NAME, "w") as json_file:
    json.dump(data, json_file, indent=4)

print("JSONファイルが作成されました: " + FILE_NAME)
```

プログラムの実行結果を示します。

```
$ python .\makeJson.py
JSONファイルが作成されました: data.json
```

プログラムの実行により、次のような data.json が作成されます。
```json: data.json
{
    "name": "John Doe",
    "age": 25,
    "city": "Example City"
}
```

# JSONファイルの編集
Python で既存の JSON 形式のファイルを編集していきます。このプログラムでは、先ほどの data.json ファイルを読み込み、データを変更してから再びファイルに書き込んでいます。

```python: editJson.py
import json

# 編集するJSONファイル名
FILE_NAME = "data.json"

# JSONファイルを読み込み
with open(FILE_NAME, "r") as json_file:
    data = json.load(json_file)

# データを編集
data["age"] = 26
data["city"] = "New City"

# 編集したデータをJSONファイルに書き込み
with open(FILE_NAME, "w") as json_file:
    json.dump(data, json_file, indent=4)

print("JSONファイルが編集されました: " + FILE_NAME)
```

プログラムの実行結果を示します。

```
$ python .\makeJson.py
JSONファイルが作成されました: data.json
```

プログラムの実行により、data.json は次のように編集されます。```"age"```キーと```"city"```キーの各値が変更されていることを確認してください。

```json: 編集後の data.json
{
    "name": "John Doe",
    "age": 26,
    "city": "New City"
}
```

# JSONファイルの複製
Python で既存の JSON 形式のファイルを別名で複製していきます。このプログラムでは、先ほどの data.json ファイルを読み込んで、新規に dataCopied.json という別名のファイルを作成することでファイルの複製をしています。

```python: copyJson.py
import shutil

# 複製するファイル名
ORIGINAL_FILE_NAME = "data.json"

# 複製で作成されるファイル名
COPY_FILE_NAME = "dataCopied.json"

try:
    # JSONファイルをコピー
    shutil.copy(ORIGINAL_FILE_NAME, COPY_FILE_NAME)
    print(f"JSONファイルがコピーされました: {COPY_FILE_NAME}")
except FileNotFoundError:
    print("指定されたファイルが見つかりません")
except Exception as e:
    print(f"エラーが発生しました: {e}")
```

プログラムの実行結果を示します。

```
$ python .\copyJson.py
JSONファイルがコピーされました: dataCopied.json
```

プログラムの実行により、data.json ファイルが複製され、新たに dataCopied.json が作成されます。各 JSON ファイルの内容が同一であることを確認してください。

# JSONファイルの削除
最後に、Python プログラムで JSON ファイルを削除する方法を記します。このプログラムでは、```os``` モジュールを使用して指定したファイルを削除しています。

```python: deleteJson.py
import os

# 削除するJSONファイル名
FILE_NAME = "data.json"

# ファイルを削除
if os.path.exists(FILE_NAME):
    os.remove(FILE_NAME)
    print("JSONファイルが削除されました: " + FILE_NAME)
else:
    print("指定されたJSONファイルは存在しません")
```

プログラムの実行結果を示します。

```
$ python .\deleteJson.py
JSONファイルが削除されました: data.json
```

これにより、data.json が削除されます。

# おわりに
本記事では、Python を使用して JSON ファイルを操作する基本的な手順をまとめました。不明な点や誤っている点があればコメントにてご連絡ください。
【Jetpack Compose】HorizontalPagerのスワイプ判定を調整する

この記事はand factory.inc Advent Calendar 2023 16日目の記事です。

## はじめに
今までAndoridViewではUIを実現するために諸々手間がかかっていたものが
JetpackComposeを利用することで一気に楽になる経験を多くされていると思います。


その中でもPagerの実装は非常に簡単になったと実感しており、
以下のコード(HorizontalPager)だけでPagerが実装できると知った時は私自身大変驚きました😅

```Kotlin
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun HorizontalPagerSample() {
    // ページの総数
    val state = rememberPagerState { 10 }
    HorizontalPager(
        state = state,
        modifier = Modifier.fillMaxSize(),
    ) { page ->
        Box(
            modifier = Modifier
                .padding(10.dp)
                .background(Color.Blue)
                .fillMaxWidth()
                .aspectRatio(1f),
            contentAlignment = Alignment.Center
        ) {
            // ページ毎のコンテンツを記述
            // pageでindexは渡ってくるのでそこで切り替えれば良い
            Text(text = page.toString(), fontSize = 32.sp)
        }
    }
}
```
これだけで書けてしまいます、すごい簡単わかりやすい

今までの
Activityのxmlの中にViewPagerの枠をとって、、FragmentPagerAdapter用意して、、あ、ページ毎にFragmentも作らなきゃ…！みたいな手間がなくなって嬉しい限りですホントに🙌

## 本題

そんな感じで簡潔かつ状態も扱いやすいHorizontalPager君ですが、
ビルドして実際に触ってみたの違和感として`ページのスワイプ判定が厳しく`
従来のAndroidViewでの操作感との差を考えたときに
UX観点から導入、もしくはComposeへのリプレイスを躊躇っていられる方もいらっしゃるのではないでしょうか？

私自身そんな思いを抱えていまして、なんとか解決できないかとドキュメントを漁っていたところ
流石はJetpackComposeといったところでそれ用のパラメーターが用意されていました。

それがこのflingBehavior`snapPositionalThreshold`というパラメーターです。



https://developer.android.com/reference/kotlin/androidx/compose/foundation/pager/PagerDefaults#flingBehavior(androidx.compose.foundation.pager.PagerState,androidx.compose.foundation.pager.PagerSnapDistance,androidx.compose.animation.core.AnimationSpec,androidx.compose.animation.core.DecayAnimationSpec,androidx.compose.animation.core.AnimationSpec,kotlin.Float)

ざっくり説明するとページのスワイプを判定する割合を設定するパラメーターで初期値だと`0.5f`、つまり50%が設定されています。
だからスワイプ判定が厳しく感じていた、というわけです。

なので、この割合を調整してあげるとAndroidViewと似たような、もしくは任意のスワイプ範囲を設定してあげることができます。

```Kotlin
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun HorizontalPagerSample() {
    // ページの総数
    val state = rememberPagerState { 10 }
    HorizontalPager(
        state = state,
        modifier = Modifier.fillMaxSize(),
        // ここに追加,今回は20%
        flingBehavior = PagerDefaults.flingBehavior(state, snapPositionalThreshold = 0.2f),
    ) { page ->
        Box(
            modifier = Modifier
                .padding(10.dp)
                .background(Color.Blue)
                .fillMaxWidth()
                .aspectRatio(1f),
            contentAlignment = Alignment.Center
        ) {
            Text(text = page.toString(), fontSize = 32.sp)
        }
    }
}
```


## おわりに
以上、ComposeにおけるPagerでのスワイプ判定の調整方法でした。
Pager+Tab等で実装の機会はたくさんあると思うのでお役立ちできれば幸いです。
local環境でconflictを解消する方法

## はじめに
エンジニアに転職して3ヶ月経ちましたが、プルリクエスト（以下PR）をmergeするときはいまだに緊張します。特に初めてconflictが起きたときは、⚠️マークが表示されているのを見て、何かやらかしてしまったのではないかと焦りました…取り返しがつかないようなミスはしたくないですよね🥺
本日は、PRをmergeするときにConflictが起きた時の解消方法を教えていただいたので紹介します。Conflictが起きても、焦らずに対処できるようになりましょう！

## 背景
作業中のfeatureブランチからdevelopにPRを出している。
GitHub上でPRをmergeしようとしたところ、conflictが発生していることがわかった。
local環境でconflictを解消する方法を先輩から教わった。

## PRをmergeするときにlocalでconflictを解消する手順
### 1. developブランチをpull
まずは、developブランチをpullして最新の状態にしておきましょう。
```terminal
git checkout develop
git pull origin develop
```

### 2. featureブランチに移動してmerge
次に、作業中のfeatureブランチに切り替えて、1.で最新化したdevelopブランチをfeatureブランチにmergeします。
```terminal
git checkout feature-branch
git merge develop
```
ここでconflictが発生します。
local環境で起きているだけなので、焦らずに対処しましょう。
### 3. conflict解消
conflictが発生した場合、VSCodeやForkなどのツールを使用してConflictを解消します。
私は、簡単な変更であればFork上で解消していますが、ソースコードの前後を見ないと判断できないような場合はVSCode上で確認しています。
どちらの修正を取り入れればいいのかをじっくり考えましょう。
### 4. commit
conflictを解消したら、変更内容をcommitします。
```terminal
git add .
git commit -m "Merge: Resolve conflict"
```
### 5. developブランチにpush
解決したconflictを含むfeatureブランチをdevelopブランチにpushします。
```terminal
git push origin feature-branch
```
### 6. PRを再度merge
これで、conflictが解消されたfeatureブランチがGitHub上のリポジトリにpushされ、PRが再度merge可能になりました。GitHub上でmergeしましょう🎉

## 終わりに
local環境ではなく、GitHub上でもconflictを解消することはできますが、より安全に対応するために、git操作に慣れるまでは控えた方が良さそうです。
対処方法がわかっていればconflictが起きてしまっても焦らずに対処できそうです。もし自分1人で不安な場合は、先輩に確認してもらいながらmergeしましょう！！
UnityのAdressableなアセットを順番に使いたかった

## まえがき
Unityの開発をする中で、Adressable Asset Systemを利用してアセットの管理を行っているときに順番通りにアセットを取得したい局面に出会いました。
アセットを一括取得する場面では、下のようにラベルを指定してアセットを一括取得すると思います。
```csharp
   Sprite spriteHandle = Addressables.LoadAssetsAsync<Sprite>({"任意のラベル"}, null);
```
ラベルで取得するアセットはAddressable windowで登録された順番が参照され、スクリプト等を利用して一括でアセットの登録した場合などでは、取り出されてくる順番がバラバラになってしまいます。

加えて、Adressable window内にはアセットを取り出す順番をソートする機能がないので、アセットを順番に取り扱うにはAdressableの内部データを操作するなど、他の方法で解決する必要があります。

以上を踏まえて自分が取れる上での解決方法をメモがてら残しておこうと思います。


## 動作環境
● Unity 2021.3.22f1
● Addressables 1.19.19


## どう対処したか
力技で解決しました。

1.アセットそれぞれに取り出したい順番に数字で名前を振っておく。
2.ファイル名の数字部分からアドレス名を指定、それらをラベルで一括取得する。
3.アドレス名でソートして、新たな配列やリストに代入する。


## コード
```csharp:hoge.cs
private IEnumerator GeneratePrefab()
    {
        var piyoHandle = Addressables.LoadAssetAsync<GameObject>("piyo.prefab");
        var spriteHandle = Addressables.LoadAssetsAsync<Sprite>({"testSprite"}, null);

        yield return new WaitUntil(() => piyoHandle.IsDone && spriteHandle.IsDone);
        
        if (piyoHandle.Status == AsyncOperationStatus.Succeeded && spriteHandle.Status == AsyncOperationStatus.Succeeded){
                //得られた結果の長さだけ配列を作成
            Sprite[] Array = new Sprite[spriteHandle.Result.Count];
            //中身の並び替え
            for (var i = 0; i < spriteHandle.Result.Count; i++)
            {
                var num = int.Parse(spriteHandle.Result[i].name);
                Array[num] = spriteHandle.Result[i];
            }
            SetActive.childrens = new GameObject[Array.Length];
            //prefabから自動生成
            for (var i = 0; i < Array.Length; i++)
            {
                var _PrefabObj = Instantiate(piyoHandle.Result, ApplyColider.instance.parentTransform);
                var _PrefabRenderer = _PrefabObj.GetComponent<SpriteRenderer>();
                _PrefabRenderer.sprite = Array[i];
            }
        }
    }
```
今回はアドレスを用いて取得したprefabのSpriteRendererコンポーネントに、これまたアドレスを用いて取得したspriteを割り当てて生成していくケースを想定しています。



上記コードの
```csharp
            Sprite[] Array = new Sprite[spriteHandle.Result.Count];
                //中身の並び替え
            for (var i = 0; i < spriteHandle.Result.Count; i++)
            {
                var num = int.Parse(spriteHandle.Result[i].name);
                Array[num] = spriteHandle.Result[i];
            }
```
の部分で取得してきたspriteの長さに応じて配列を作成し、アセット名に用いている数字を数値に読み替えつつその値に応じて配列に詰め直しています。

後はforループを回して目的のprefabを生成するだけです。

# 参考サイト等

https://docs.unity3d.com/ja/Packages/com.unity.addressables@1.20/manual/LoadingAddressableAssets.html

https://qiita.com/kochiyukimoto/items/86544bd1fb3628de5dea

 https://forum.unity.com/threads/order-of-assets-in-groups.1397716/
過去に仕事で出会ったコードの中で最悪のもの

# これは何？

クソコードお焚き上げの会 Advent Calendar 2023 に参加するために書いた記事。

https://qiita.com/jaque/items/a82929709407d5c3beb2

を見て、書こうと思った。

# 事例

ぼかすけど。

まあ下記のようなコード。本物は関数名こそちがうけど、まったく同じ趣旨。

```C:C言語
/* a[i] と a[j] を入れ換える */
void FooSwapInt( int * a, int i, int j ){
  int tmp = a[i];
  a[j] = tmp;
  a[i] = a[j];
}
```

# 経緯

私は、ある装置の機能追加のために参加した。
前バージョンは出荷済み。

私がやるべき仕事に上記の関数の周辺はあまり関係なかったんだけど、コード全体の量がそれほど多くなかったのと、なんとなく見ておいたほうが良いという予感があり。
頼まれてもいないのに全体を眺めてたら発見した。
たいへん驚いた。

# 何がまずいのか

関数名もコメントも値の入れ替えを意図しているように見えるし、中身も一時変数を使った入れ替えのコードによく似ている。

しかし、よく見ると分かるが、上記の計算では入れ替わらない。

酷い。
しかも、この関数は何箇所かで呼ばれていた。

# なぜ生き残っていたのか

ここまで酷いと、なぜこのコードが生き残っていたのかが気になる。
入れ替えたくてこれを呼んでも入れ替わらないので、致命的な不具合として観測できそうなものだ。

調査した結果。
前述の通り、このコードを呼んでいる場所は何箇所かあったものの。
それぞれの箇所の流れを追うと、結局 `FooSwapInt` は一度も呼ばれておらず、装置の動作に影響を与えていなかった。

Swap 操作をする関数は他にも何個かあり (!)、本当に Swap が行われる場所は `FooSwapInt` 以外の関数で Swap 操作をしていた。

# まとめ

このコードが発見されたことで、コードレビューがまともに機能していなかったことがわかった。

こんなに明瞭な間違いが出荷済みのコードの一部として発見されるという体験で、たいへん驚いた。
subprocess.runが吐いた文字列をJsonにデコードできない？ANSIエスケープシーケンスが原因かも

pythonで、ghコマンドを叩いてGithubからデータを取得しようとしたある日のこと。

## 突然のJSONDecodeError
subprocess.runで次のghコマンドを叩きました。
`gh issue list --json title,url`

レスポンスの文字列
![スクリーンショット 2023-12-17 22.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130234/aabf3a43-6217-f8ba-2aea-dcb463a22c7f.png)

文字列のままでは扱いづらいため、json.loadsによってJsonにデコードすると

```
---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
Cell In[123], line 18
     16 # subprocessモジュールを使用してzshコマンドを実行
     17 result = subprocess.run(["zsh", "-c", zsh_command], stdout=subprocess.PIPE, text=True).stdout
---> 18 JSON(json.loads(result))
（略）
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
```

JSONDecodeErrorが発生しました。

レスポンスの文字列をよく見ても、コピーしてJson構文を機械的にチェックしてみても、おかしなところは見当たりません。では、いったいなぜ・・


## JSONDecodeErrorの原因
レスポンスの文字列をもう一度見てみましょう。
![スクリーンショット 2023-12-17 22.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130234/aabf3a43-6217-f8ba-2aea-dcb463a22c7f.png)

文字が青色や緑色で着色されています（※Jupyter Labという開発環境での表示です）。これがJSONDecodeErrorを引き起こしている原因でした。

ANSIエスケープシーケンスと呼ばれる特殊コードを文字列に含めることによって実現されているようです。

https://www.python.ambitious-engineer.com/archives/3721

## JSONDecodeErrorの解決方法
下記コードによって、ANSIエスケープシーケンスを除去します。
```python
def remove_ansi_escape_codes(text):
    # ANSIエスケープコードを削除
    ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
    return ansi_escape.sub('', text)
```

これによって、json.loadsでJSONDecodeErrorになる問題を無事回避できました。
![スクリーンショット 2023-12-17 22.18.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130234/7e963282-c4fa-e462-35f1-25276e95d5a0.png)


## おわりに
標準出力の着色の仕組みを理解していないと、検討がつかず焦りますね。
コマンドを叩いた結果を処理するときは、ANSIエスケープシーケンスに気をつけましょう。
IRC

[インターネット老人会の魔法書 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ancient-internet) の11日目の記事です。

# IRCとは

Internet Relay Chatの略。
インターネット創成期からのグループチャットの仕組み。
IRCサーバを構築しないといけないのと、クライアントアプリが必要だが、リアルタイムのチャットができるため、Slack等がない時代は、社内でこれを立てて連絡場所にしているところが多かった。

イントラネット内にサーバを立てればインターネットにつながっていないところでも使えるので、セキュリティ的な面でも重宝された。

# 顔文字辞書

Slackのように絵文字を送ったり発言に絵文字で反応したりなどはできないので、Shift_JIS第一水準文字規格内で顔文字を作る必要があった。チャット厨の民はみんな顔文字辞書を登録して、感情表現をすぐに顔文字で表現できるようにしていた。

そのため「(˃ v < *)ｳﾝｳﾝ」を送ろうとして誤変換で「ｳﾝｺｰ!(*ﾟ∀ﾟ)=3」を送ってしまうなどの事故が多発した。