OmniAICreator/Qiita-1.07M huggingface dataset:
AIカートコバーン2

# この記事の続き
https://qiita.com/chariumaboat/private/4df8277b16b2a54fb7de

## 運用を経て
- 文字だけだと寂しいことに気がついた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354194/f4f233a4-54d7-5b11-b5e3-5acddd526169.png)

## 画像を作る
- stable-diffusion-webuiをインストール
  - プロンプトを考えなくていいようにモデルはAnything4.5をチョイス
  - 画像がガサガサしてたからVAEを導入
  - Lora入れたけど使わなかった

- 100枚画像作った
  - `./jpg/ai_kart/`に保存 

## 画像を一緒にツイート
- 前回のに以下のを足す
```python:ai_kart.py
def auth_api_v1(envName):
    config = configparser.ConfigParser()
    config.read('ai_kart.ini')
    consumer_key = config.get(envName, 'consumer_key')
    consumer_secret = config.get(envName, 'consumer_secret')
    access_key = config.get(envName, 'access_key')
    access_secret = config.get(envName, 'access_secret')
    auth = tweepy.OAuth1UserHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_key, access_secret)
    api = tweepy.API(auth)
    return api

directory_path = './jpg/ai_kart/'
image_files = [f for f in os.listdir(directory_path) if f.endswith(
    ('.jpg', '.jpeg', '.png', '.gif'))]
if image_files:
    random_image = random.choice(image_files)
    image_path = os.path.join(directory_path, random_image)
    print("ランダムに選択された画像パス:", image_path)
else:
    print("ディレクトリ内に画像が見つかりませんでした。")
    sys.exit(1)
api = auth_api_v1('ai_kart')
media_id = api.media_upload(image_path).media_id_string
print(media_id)
client = auth_api_v2('ai_kart')
post_tweet = client.create_tweet(text=content, media_ids=[media_id])
print(post_tweet)

```

### 結果
- 無から有を生み出した

https://twitter.com/114bot/status/1736543630892867613

## 毎回画像をつけるの嘘くさいから1/5の確率でつけたい
- 雑に`randint`で

```python:ai_kart.py
if random.randint(1, 5) == 1:
    #　あたりの処理
else:
    # ハズレの処理
```

### 結果
- いい感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354194/e43ee372-121d-1243-8bcf-eb884ead4111.png)

## 発言をランダムにする
- プロンプトをいくつか用意してランダムにチョイスするようにした

```python:ai_kart.py
def randam_text():
    text_list = ["ロックスターとして政治的発言を140文字でしてください",
                 "新譜「nevermind pt2」について一言コメントをください。140文字以下にまとめてください",
                 "炎上しそうなツイートを140文字でしてください",
                 "カートコバーンの生まれ変わりとしてオリジナルのカートコバーンについて非常に厳しく140文字で批評してください",
                 "カートコバーンの生まれ変わりとしてオリジナルのカートコバーンについて非常に厳しく140文字でdisってください",
                 "ファンに向けて一言、調子に乗ってる感じで、140文字で",
                 "ファンに向けて一言、馬鹿にした感じで、140文字で",
                 "人を馬鹿にしてください、140文字で",
                 "オーディエンスを煽ってください、140文字で"
                 ]
    return random.choice(text_list)
```

# そろそろ飽きると思う
## そろそろ飽きると思う
### そろそろ飽きると思う
#### そろそろ飽きると思う
##### そろそろ飽きると思う
###### そろそろ飽きると思う
飽きたかも
箸休めポエム小説

# はじめに
ブロックチェーンの技術普及推進活動を進めているNPO法人 NEM技術普及推進会 NEMTUS(ねむたす) の飯田友広です。
2023年9月ごろから、マーケターとして携わっています！

tech以外のことで何を書こうかな〜〜自分なりの新規事業企画方法にしようかなあなどと考えていたものの、小難しいことはやめて旅のお供になるペーパーバックようなものをChatGPTと共に作ってみることに至った次第です。
ちょうど明日はXYMPOSIUMでみなさん移動されることかと思うし！

というわけで。Symbolブロックチェーンについて、SF物語を書いてみました。
SFといえばもちろんこの人！「電気羊は〜〜」の"フィリップ・K・ディック"ということで、全体の作風はこの作家さんでまとめました。
さあそれでは、Symbolが鍵を握る壮大なサイエンスフィクションをお楽しみください＾＾

# 第1章：影の中の真実
### 宇宙ステーション・オリオン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323073/ca500390-ce32-aefe-5124-01675b428a1f.png)


オリオン、人類の到達した最も遠い場所に浮かぶ巨大な構造物。ここでは、宇宙の隅々から集まった人々が、互いに知識を交換し、時には疑念を抱きながら生活している。この宇宙ステーションの一角、暗く静かなカフェの片隅で、ミナは自分の存在について深く考え込んでいた。

彼女の前には、複雑に絡み合ったデータの塊が浮かんでいる。未来から持ち帰ったこのデータは、Symbolブロックチェーンで暗号化され、彼女自身の過去と未来を暗示しているかのようだった。

「このデータが示すのは、単なる情報ではない…これは、存在の証明…」

ミナの思索を遮るように、タクミが近づいてきた。彼の目には好奇心と疑念が同居している。彼はミナに向かって低く語りかけた。

「ミナさん、そのデータは何ですか？」

ミナは静かに答えた。「未来の遺産です。Symbolブロックチェーンに守られている…私たちの運命を変えるかもしれないデータです。」

タクミの目が輝いた。「それは興味深いですね。私たちの運命ですか…」

カフェの外では、宇宙ステーションの光が遠くの星々に反射していた。宇宙の静寂の中で、ミナとタクミは、この暗号化された遺産の解読に取り組み始める。しかし、彼らが知らなかったのは、このデータが持つ真実が、彼らの現実を根底から揺るがすものであるということだった。


# 第2章：影の中の連帯
### 宇宙ステーション・オリオン、秘密の研究室

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323073/82ee85bb-5c6c-95a3-bdf3-3aafc3c83c83.png)

ミナとタクミは、オリオンの秘密の研究室に身を隠していた。彼らの周りは、未来技術と古い機器が入り混じる奇妙な風景で満たされていた。ミナは、Symbolブロックチェーンのデータを解読するために、彼女の持ってきた先端機器をセットアップしていた。

「このデータが示すものが何であれ、私たちは準備をしなければなりません。」ミナは言った。

タクミは彼女の作業を見守りながら、疑問を投げかけた。「このデータが、本当に未来を変える力を持っているのですか？」

ミナは深いため息をついた。「未来は常に変わり続けます。しかし、このデータには、私たちの世界を根底から変える可能性があります。」

彼らの作業は、次第に進展を見せ始めた。データには、未来の重要な出来事や技術の進歩が暗号化されていた。ミナとタクミは、これらの情報がどのように現在に影響を与えるかを議論した。

そんなある日、突然、研究室のドアがノックされた。二人は驚いて顔を見合わせた。この場所を知っているのはほんの一握りの人間だけだった。ミナは息を潜め、ドアに近づいた。ドアを開けると、そこには予期せぬ人物が立っていた。

「私は…助けに来ました。」

# 第3章：未来への扉
### 宇宙ステーション・オリオン、研究室の外

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323073/9f268f6d-874f-ec27-2eb6-719f62108f5b.png)


ドアの外に立っていたのは、オリオンステーションのセキュリティチーフ、イサムだった。彼はミナとタクミに警告するために来たのだ。

「ステーションが…あなたたちの研究に気づきました。私たちは時間がない。」

イサムの言葉に、ミナとタクミは緊張を感じた。彼らの研究が宇宙ステーションの秩序を乱す可能性があることを彼らも理解していた。

「しかし、このデータは未来を救うかもしれない。」ミナは力強く言った。

タクミはミナの目を見つめ、同意した。「私たちの運命を変えるチャンスです。」

イサムは彼らに協力を申し出た。「私は皆さんの目的を理解しています。私も協力しましょう。」

結局、彼らはSymbolブロックチェーンのデータを全て解読することに成功した。データには、未来の大災害を防ぐための重要な情報が含まれていた。彼らはその情報をもとに、宇宙ステーションの科学者たちと協力し、未来を救う計画を立て始めた。

物語の終盤、ミナはタクミと共に宇宙ステーションの窓から星々を眺めていた。彼らの前には新たな未来が広がっていた。ミナは小さく微笑み、タクミに言った。

「私たちの物語はまだ終わっていない。これからが本当の始まりです。」

そして、二人は新たな未来へと歩みを進めた。


# おわりに
先日12月16日から、NEMTUS主催のハッカソンが始まりました！
テーマは"Real Impact".
これからどんどん盛り上げていきます〜〜〜〜〜！！

https://hackathon-2024.nemtus.com/


### Supported by...
- [自動小説生成GPT](https://chat.openai.com/g/g-KZx0da9yo-zi-dong-xiao-shuo-sheng-cheng-gpt)
- [フィリップ・K・ディック](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%AA%E3%83%83%E3%83%97%E3%83%BBK%E3%83%BB%E3%83%87%E3%82%A3%E3%83%83%E3%82%AF)
HTMLだけで簡単に作れるアコーディオンが進化していた

## `details` を使ったアコーディオン

Internet Explorerではできませんでしたが、`details` と `summary` タグを組み合わせて、簡単にアコーディオンが実装できるようになっています。
Internet Explorerのサポートが終了してから、簡単なアコーディオンに採用している方もいるのではないでしょうか。

## 進化した点

Chrome120から、 `details`タグに `name` 属性がサポートされるようになりました。
これによって同じ `name` を持つ複数の `details` がセマンティックグループを形成します。
グループ化した `details` では、一度に開くことができる要素は1つです。
新しく `details` を開くと、前に開いていた `details` は自動的に閉じられます。
これを `排他的アコーディオン` と呼ぶそうです。

なお、排他的アコーディオンは、離れていても有効です。
同じドキュメント内にあれば、離れていても同じ排他的アコーディオンとして機能します。

## デモ

実際にどのような挙動をするのか、Codepenで書いてみました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xxMvWJr" data-user="gilly135" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/gilly135/pen/xxMvWJr">
  details accordion</a> by gilly135 (<a href="https://codepen.io/gilly135">@gilly135</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 対応ブラウザ

2023年12月時点では、残念ながらFirefoxがまだ `details`タグに `name` 属性がサポートされていません。
Firefoxで `details`タグに `name` 属性が入っていても、表示が崩れることはありませんが、排他的アコーディオンとしては機能しない状態です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215239/10f1a757-a88a-3449-2ff8-3b7575fbff5d.png)


## 参考

[CSS ラップ: 2023 年  |  Blog  |  Chrome for Developers](https://developer.chrome.com/blog/css-wrapped-2023?hl=ja#named-details)
STARC RTL設計スタイルガイド　ふたたび HDL(4)

HDL: Hardware Description Languageには、Verilog HDL, VHDLなどの種類がある。

RTL設計スタイルガイド Verilog HDL編
https://qiita.com/kaizen_nagoya/items/c883b9aab40c53c1d259

改訂がありSystem Verilogにも対応するようになった。

RTL設計スタイルガイド Verilog HDL編(System Verilog対応版）
https://qiita.com/kaizen_nagoya/items/4c02f1575db1f28310a7

プログラマが知っているとよい設計指針（4）STARC RTL 設計スタイルガイド
https://qiita.com/kaizen_nagoya/items/7a3298801259409bd1b9

Xilinx: FPGA と Verilog HDL
https://qiita.com/kaizen_nagoya/items/6db0b65fb1c227722660

FPGAをクラウドで開発する環境を探し中。
https://qiita.com/kaizen_nagoya/items/cdf429ae3d134bae358e

<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

# 関連資料

slideshare top 10 on kaizenjapan(@kaizen_nagoya)
https://qiita.com/kaizen_nagoya/items/2035b961adad19b74c17

CPUの創りかた, 渡波 郁
https://qiita.com/kaizen_nagoya/items/2e1b6b79ea3e6b2bf0c0

みんなでCPUを創ろう。新人プログラマ応援 -
https://qiita.com/kaizen_nagoya/items/605423527ce8a7fcdbe9

プログラミング言語教育のXYZ。 仮説（52）
https://qiita.com/kaizen_nagoya/items/1950c5810fb5c0b07be4

言語学習母語方式
https://qiita.com/kaizen_nagoya/items/52640bbaff6349db61e2

言語規格、コーディング標準の使い方
https://qiita.com/kaizen_nagoya/items/01256365b82666e101aa

設計ってなんですか
https://qiita.com/kaizen_nagoya/items/517f7fe26bc33a992e36

ソースコードは設計である３つの理由。仮説(79)
https://qiita.com/kaizen_nagoya/items/1963f555dbc22770e149

ソースコードで議論しよう。日本語で議論するの止めましょう（あるプログラミング技術の議論報告）
https://qiita.com/kaizen_nagoya/items/8b9811c80f3338c6c0b0
# 補足資料（Additions）
2023 Countdown Calendar 主催・参加一覧
https://qiita.com/kaizen_nagoya/items/c4c2f08ac97f38d08543

CountDownCalendar月間　いいねをいただいた記事群　views　順
https://qiita.com/kaizen_nagoya/items/583c5cbc225dac23398a


＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.
# 文書履歴(document history)
ver. 0.01 初稿 　20231218
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
Microserivce APIs

『Microservice APIs』はREST APIとGraphQLの設計に関する入門書レベルの書籍です。

<a href="https://www.amazon.co.jp/Microservice-APIs-Jose-Haro-Peralta/dp/1617298417"><img src="https://m.media-amazon.com/images/I/61oz6uvEuRL._SL1500_.jpg" width="200" alt="Microservice APIs書影"/></a>

７章あたりにきて、ようやく実装例が出てきますが、「ヘキサゴナルアーキテクチャで実装しましょう」「OrderServiceとOrderRepositoryを作ります」「ドメインオブジェクトとしてOrderを作ります」「Orderのpayメソッドは、Paymentサービスを呼び出します(下記コード参照)」みたいな調子なので、ソフトウェア設計の参考として読むのはやめておいた方がよさそうなスメルがします。あくまでもREST APIやGraphQLを初めて触る人向けの入門書です。

```python
class Order:
    # ...
    def pay(self):
        response = requests.post(                                  
            'http://localhost:3001/payments', json={'order_id': self.id}
        )
   # ...
```

## マイクロサービス

一応、『Microservice APIs』はマイクロサービスのテーマの本でもあるので、そこに言及しているところを深掘りしてみます。

3章ではサービス分割の指針として、以下2通りがあるとされています。

1. ビジネスケイパビリティによる分割
1. サブドメインによる分割

これ自体は、なんら新しいものでもなく、[microservices.io](https://microservices.io/patterns/)にて、分割のパターンとして紹介されている2つです。

ここで、よくわからないのが「ビジネスケイパビリティ」というものです。『Microservice APIs』では「事業がどのように組織化しているかを調べ、その組織構造を反映したマイクロサービスを設計する」と説明されており、違和感甚だしいです。

[microservices.ioのDecompose by Business Capability](https://microservices.io/patterns/decomposition/decompose-by-business-capability.html)のページでは、「ビジネスアーキテクチャモデルにおける概念であり、ビジネスが価値を生み出すために行うこと」としています。こんな説明で理解できる人がいるのでしょうか?


『[Strategic Monoliths and Microservices](https://www.amazon.co.jp/-/en/Vaughn-Vernon/dp/0137355467)』では、そこそこの分量を割いて、そのあたりが説明されています。

『Strategic Monoliths and Microservices』に以下のような一節があります。

> サブドメインによって表されるビジネスケイパビリティ概念は、同じ名前の境界づけられたコンテキストで実装される

> 境界づけられたコンテキストとは、ビジネスケイパビリティのカプセル化であり、各ビジネスケイパビリティは完全な実装を持たなければならない。あるビジネスケイパビリティのいかなる部分も、その境界づけられたコンテキストの外に残されたり、実装されたりしてはならない。

これを図示すると以下のようになると考えられます。

![サブドメインと境界づけられたコンテキスト、ケイパビリティの関係](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8475/0d2184ff-c0c1-8ceb-4d7b-0b8695cbe56e.png)

さらには、サブドメインと境界づけられたコンテキストは、mustではないにしろ、洗練されたモデルでは1:1対応し、境界づけられたコンテキストは1つのビジネスケイパビリティを実装する、と述べています。

ということで、ビジネスケイパビリティからのアプローチも、サブドメインからのアプローチも同じことを意味します。そもそも「サブドメインによる分割」というのは問題空間を意味し、全部をソフトウェアで解決するわけではないので、マイクロサービス分割の指針としてはおかしな話です。

ドメイン駆動設計の言葉を使って、マイクロサービスの分割を語るのであれば、

* 境界づけられたコンテキストを出発点として、サービス分割を考えるのは良い。
* だが、正しい境界をはじめから引くことはできないし、「正しい」も移り変わるので、変更に追従できるように設計を考えておく方が重要である。
* 境界づけられたコンテキストのサイズは、ビジネスケイパビリティとそのユビキタス言語の範囲によって制限されるべきである。断じてコードサイズではなく、「マイクロ」を強調すべきではない。

ということになりそうです。
[18日目] Google WorkspaceのドメインDNSまとめ

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の18日目の記事です。

この記事では、Google WorkspaceのGmailを使う際に設定する必要がある（しておいた方が良い）ドメインのDNSについて紹介します。

# MXレコード
Googleのサーバーにメールが正しく到達するようにMXレコードを設定する必要があります。
以下は私のGoogle Workspaceで設定しているドメインの設定です。
```
<domain>. 300 IN MX 1 aspmx.l.google.com.
<domain>. 300 IN MX 5 alt1.aspmx.l.google.com.
<domain>. 300 IN MX 5 alt2.aspmx.l.google.com.
<domain>. 300 IN MX 10 alt3.aspmx.l.google.com.
<domain>. 300 IN MX 10 alt4.aspmx.l.google.com.
```

# SPFレコード
メールが正規のメールサーバから送信されたことを確認するレコードです。
Google WorkspaceのGmailを使う場合は、以下のSPFレコードを設定します。
```
<domain>. 300 IN TXT "v=spf1 include:_spf.google.com ~all"
```

# DKIMレコード
メールの送信元を認証するレコードです。DKIMレコードを設定することで、なりすましメールの対策につながります。

DKIMのレコードは、Google Adminのアプリ → Google Workspace → Gmail の設定 → メールの認証 から確認することが出来ます。

# DMARCレコード
DKIMレコードの設定状況を通知するレコードです。DMARCレコードを設定することで、なりすましメールの対策を強化することができます。

Cloudflareを使っている場合は、DMARC Managementを使うことが出来ます。これを使えば簡単にレポートを見ることが出来ます。（ダッシュボード上から）

これだけ設定すれば大丈夫でしょう！！
バイトコードとネイティブコード

# はじめに
毎週1本様々な技術に関する記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiita.com/7_inai_)


# バイトコードとネイティブコード
### ■バイトコード
`バイトコードとは、特定の仮想マシン(JVM,CLR)上で実行される中間言語`のことで、エミュレータで動作させるために作られた実行可能なバイナリ表現の中間言語をバイトコードと呼びます。

### ■ネイティブコード
`ネイティブコードとは、特定のCPUに向けて作られた機械語`のことで、オブジェクトコードと呼ばれることもあります。

# バイトコードがjavaを早くする？
バイトコードは通常、JITコンパイラ（Just-In-Timeコンパイラ）によって逐次的に処理されます。JITコンパイラは、実行時にバイトコードをマシンコードに変換し、そのマシンコードを直接実行します。これにより、プログラムの実行が高速化されます。JITコンパイラは、実行中に必要な部分のみをコンパイルすることができるため、効率的な実行が可能です。

# Javaでバイトコードとネイティブコードを使う理由
プログラムの柔軟性やパフォーマンスを向上させるために、Javaではバイトコードとネイティブコードの両方を使用します。

バイトコードは __プラットフォームに依存しない中間言語__ であり、__異なるプラットフォーム上で同じバイトコードを実行__ できます。このため、Javaプログラムは __移植性が高く、異なる環境で動作__ します。

一方で、ネイティブコードは、__特定のプラットフォーム向けに最適化されたコード__ です。JITコンパイラはバイトコードを実行時にネイティブコードに変換することで、実行速度を向上させます。特定の環境で __ネイティブなコードを実行することで、より高速で効率的な実行が可能__ です。

# 終わりに
前述した通り、バイトコードとネイティブコードの両方がJavaの柔軟性とパフォーマンス向上に貢献しています。バイトコードの移植性とネイティブコードの効率的な実行が組み合わさり、Javaが広く活用される要因となっています。

最後までお付き合いくださりありがとうございました。
chatGPT APIとdiscord.pyでBOTを作ってデプロイまでしてみた。

# はじめに
前々からdiscordBOTを作ってみたかったので、今回chatGPTに質問ができるdiscordBOTを作成してfly.ioでデプロイまでしてみました。


# 実装
## discord側の設定
botを作成する設定は[こちらの記事](https://qiita.com/Naoya_pro/items/d8259d072d1e8f046a93#discord%E3%81%AB%E6%8A%95%E7%A8%BF%E3%81%95%E3%82%8C%E3%81%9F%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%97%E3%81%91%E6%B8%A1%E3%81%99)にわかりやすくまとまっていたのでこちらを参考に設定しました。

## 必要なライブラリのインストール

```
pip install openai
pip install discor.py
pip install python-dotenv
```

## chatGPTのAPIを利用するためのclass
```main.py
from openai import OpenAI

class GPT():
    def __init__(self, API_KEY):
        self.client = OpenAI(api_key=API_KEY)
        self.messages = [
            {'role': "system", "content": "あなたはプロのプログラミング初心者の講師となります。プログラミング学習初心者からの質問を簡潔に返答することが求められます。また、回答は文字数で200文字以下である必要があります。"}
        ]

    def response(self, message: str):
        self.messages.append({"role": "user", "content": message})
        completion = self.client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=self.messages,
            temperature=0.5
        )
        response = completion.choices[0].message.content
        self.messages.remove({"role": "user", "content": message})
        return response
```

プログラミングの講師としての役割付を事前に行います。またtemperatureの値を0~1の範囲で変更すれば出力の多様性が変化します（0の方が確率のたかい出力が、1に近いほうが低い確率の単語が選ばれます）。

また、このclassのインスタンスを作成するタイミングでAPI_KEYが必要になります。`.env`を作成して以下のようにopenAIのAPI_KEYを設定しておいてください。
```.env
CHAT_GPT_API_KEY = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## discordの実装
```main.py
from discord import app_commands
import discord
from dotenv import load_dotenv
import os

from openai import OpenAI


load_dotenv()

# 略

intents = discord.Intents.default()
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)


@client.event
async def on_ready():
    print('ログインしました')

    new_activity = f"Be ready to response commands"
    await client.change_presence(activity=discord.Game(new_activity))

    await tree.sync()


@tree.command(name='gpt', description='Get Response by ChatGPT API')
async def gpt(interaction: discord.Interaction, prompt:str):
    await interaction.response.defer()
    gpt = GPT(os.getenv('CHAT_GPT_API_KEY'))
    answer =  gpt.response(prompt)
    response = f"`You >>>`\n{prompt}\n`ぴょえGPT >>>`\n{answer}\n"
    await interaction.followup.send(response)


client.run(os.getenv('TOKEN'))

```
treeはdiscordの/コマンドを実現することができるようです。
今回は/gptというコマンドを作成しています。
このコマンドでは promptで引数をもらい、その部分がAPIへの入力となっています。


また、discordBotのtokenも.envに追記しておきましょう！
```.env
TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
CHAT_GPT_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

これで実行できると思います！

# 最後に
discordBOTはかなり難しいものと思っていましたが、簡単に実装できました！
デプロイに関しては[こちらの記事](https://qiita.com/Pumila/items/f134f210789842340066)の通りに進めると問題なくできたので、ホスティングまでしてみたい人はこちらを参考にしてみてください。
Gitでブランチを切り忘れて作業してしまった時の対処法

# はじめに
Gitでコード管理する際に、作業ブランチに移動するのを忘れてしまった場合の対処法について書いていこうと思います。
こちらは、commitする前になります。

作業ブランチにて作業するのが正しいところを、mainブランチでそのまま作業してしまった場合を想定しています。


## 状況の確認
```
$ git status
```

![スクリーンショット 2023-12-18 21.19.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/b570f7a0-acd1-95ec-9106-cc819310463c.png)
こちらで確認するとmainブランチで作業しているのが確認できます。

なのでこちらを作業ブランチに移動していきたいと思います。

### mainブランチの作業内容を一時的に退避させる
```
$ git stash save "メッセージ"
```

![スクリーンショット 2023-12-18 21.20.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/ecb44d39-9923-914b-811a-37a1317cd348.png)


### 退避できているか確認する
```
$ git stash list
```
![スクリーンショット 2023-12-18 21.21.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/e09e635b-6d46-7f69-d129-98217f73aafd.png)

退避番号、ブランチ名、メッセージの内容で退避していることが確認できます。

### 作業ブランチを作成する
```
$ git branch <ブランチ名>

# ブランチの確認
$ git branch
```
![スクリーンショット 2023-12-18 21.20.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/d56b41df-d1c6-a48d-3a48-2dff89a45f34.png)

作業ブランチを作成したことを確認しました。

### ブランチの移動
```
$ git checkout <ブランチ名>
```
![スクリーンショット 2023-12-18 21.21.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/c5a3e342-fe9d-9685-d6d8-bc44a342c1e6.png)

mainブランチから作業ブランチに移動したことを確認できました。

### 作業ブランチに退避した内容を反映させる
```
$ git stash apply stash@{0}
```

![スクリーンショット 2023-12-18 21.21.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/e123fa12-eb78-ae93-9db5-01a71a4be833.png)


### 反映されているか確認する
```
$ git status
```

![スクリーンショット 2023-12-18 21.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/9fbfcd56-bb7b-a20f-5a3f-c7ff925013ef.png)

作業ブランチにて反映されていることが確認できました。
これで作業ブランチにて続きの作業をしていきます。


# 最後に
今回はブランチを切り忘れて作業をしてしまった時の対処法について書いていきました。
いざ忘れたとなると経験値が少ないので焦ってしまいがちになりますが、落ち着いて今回のように退避させることによって対処できることが分かったので良かったです。

忘れないことが一番なので、次回以降気をつけて作業に取り掛かろうと思います。
エンジニアもやさしい日本語を使おう

## やさしい日本語とは
　やさしい日本語とは、難しい言葉を言い換えるなどして、わかりやすくした日本語のことです。
　元々は外国人に情報を伝えるときのことを考慮した概念ですが、高齢者や障がい者など、**あらゆる人にとってわかりやすい書き方**です。

　今回は、「テックブログを書くときも、やさしい日本語を使うと良いのではないか？」という仮説を書いていきます。

※具体的なやさしい日本語の書き方については、あまり触れません。

## 先にまとめ
- やさしい日本語で書かれた文章はあらゆる人にとってわかりやすく、これから日本のエンジニア市場に入りたい外国人や学生の助けになる
- やさしい日本語は、ITの技術やサービスもわかりやすく伝えることができる
- やさしい日本語で文章を書くときも、IT専門用語は使ったほうがよいかもしれない

## テックブログにやさしい日本語を使う利点
### これから日本でエンジニアを目指す人が勉強しやすい
　やさしい日本語では、あらゆる人にとってわかりやすい文章を目指します。これは、これからエンジニアを目指す人たちも勉強しやすいということです。

　エンジニアが不足しているという昨今、外国人やコンピュータ科学を専攻していない人など、あらゆる属性の人たちがエンジニアになる可能性が大いにあります。さらに、**学校でのプログラミング授業の必修化**もあり、より多くの学生がテックブログを見ることが考えられます。

　出自や年齢などが異なるあらゆる属性の人が、テックブログを見るかもしれない。そう考えてやさしい日本語を使うことで、彼／彼女たちが勉強しやすくなると思います。

### 使う人のコミュニケーション能力が上がる

　やさしい日本語には、使う側のコミュニケーション能力が上がるという利点もあります。

　やさしい日本語を作るポイントとして、例えば以下のようなものがあります。

- 伝えたいことを整理し、情報を取捨選択する
- 一文は短くする（一文に言いたいことは1つだけ）
- 二重否定を使わない
- 曖昧な表現はできる限り使わない

　これらのポイントを守って文章を作る能力は、**伝えたいことを正しく伝える能力**と言い換えることができます。やさしい日本語を使うよう心がけることで、自分が原因のコミュニケーションの齟齬を減らすことができます。（よりよいコードを書くことにもつながるかもしれません。）

　特にIT技術は専門性が高く、そもそも理解が難しいです。せめて文章がわかりやすいことで、本来の目的である知見の共有が簡単になります。

## テックブログでやさしい日本語を使うときの疑問点
### 専門用語は使ってもいいのか?
　やさしい日本語では、専門用語をできる限り使わないことが推奨されています。

　しかし、テックブログの目的はITの知識を伝えることなので、専門用語を使う必要があります。**ITの専門用語は残しつつ、その他の分野の専門用語は極力避ける**のが良いと思います。

　また、専門用語を使わずに説明しようとすると、かえって説明が長くなってしまい、伝えたいことが伝わらないリスクが増えます。さらに、**専門用語を使わないことで、読んでいる人の次の学習の機会が失われることもある**と思います。
　やさしい日本語のポイントからは外れてしまいますが、専門用語は適度に入れるべきだと思います。

## 終わりに
　ここまで、「テックブログでの」やさしい日本語の使用を提案しました。
 
 　実際にはテックブログ、あるいはIT業界に関わらず、あらゆるコミュニケーションでやさしい日本語は有用です。
　しかし、あらゆる人がコンピュータにふれる世の中において、**エンジニアがやさしい日本語を使うことには大きな意義がある**と思います。

## 参考

https://www.bunka.go.jp/seisaku/kokugo_nihongo/kyoiku/92484001.html

吉開章. 『入門・やさしい日本語 外国人と日本語で話そう』. 株式会社アスク出版, 2020.
Macでペースト操作をすると10秒くらいフリーズする問題の解決策

ググってもドンピシャの症状が見当たらなかったので、書きます。
小ネタなので、手短に。

## 結論

- VSCodeでペースト操作（Command ＋ V）すると、急にフリーズするようになった。
- Karabinerで「コマンドキーを単体で押した時に、英数・かなキーを送信する。」設定を適用したのが原因だった。
- この設定を解除したところ、フリーズが発生しなくなった。

## 環境

- MacBook Pro (13-inch, M2, 2022) 
- Ventura
- ロジクール SIGNATURE K855 を使用

## その他

- Win/Mac 両刀使いに最適なショートカット設定がほしい。。。
  - option が押しづらい（単語単位の移動をよく使う）
  - 英数キーにoptionを割り当ててみた
  - 英数切り替えを command で兼ねようとしたら本件発生
  - option キーに 英数キーを割り当ててみたが使いにくい（今ここ）
  - かなキー単体で英数／かなをトグルするのが良いかも？

皆様のベストソリューション、ぜひ教えてください。。。
「iOSエンジニアは5年後にAppleエンジニアに転ずる」論者の考察

# ようこそ考察の沼へ
こんにちは。
山田遍音とかいて、やまだあまねと呼んでください。
ツバメと聞くと、舌打ちをしたりしていませんか？
りんご味のグミを過剰に咀嚼していませんか？
胸に手を当てて自分に聞いてみてください。

# 想定する記事読者
わたしの記事を開いた人は、残念だが、iOSエンジニアとして、食いつなげるかわからないが、iOSを含めApple製品の調査やコーディングをして糊口をしのぎたい人だ。
とどのつまり、わたしだ。

# Appleエンジニア・・・？
Appleエンジニアは、Apple社員かつエンジニア職に就いている人のことではない。
いや、おそらく、Apple社員かつエンジニア職に就いている人はAppleエンジニアと称していいはずだ。
iOSエンジニア・コーディングやアプリのリリースに関わる者は、今後2分する。
前者は従来通り、コーディングやライブラリ生成に関わるものたちだ。プログラマやPMとして、従来通り働く。
後者は、コーディングは得意ではないが、日本人でありながら翻訳が非常に得意で、Appleのドキュメントを迅速に理解し、チームメンバにわかるように連携する仕事に従事することになる。
サーバエンジニアがAWSエンジニアやGCPエンジニアに転じたように、iOSエンジニアから、Appleのサービスを代わりに理解するエンジニア(Appleエンジニア)が発生するだろう。

## それって、エンジニアなのか？
本質を組み替えて換骨奪胎して、本家に劣るとも勝らないガイダンスを作る仕事になる。
これがエンジニアリングなのか？
そもそもエンジニアとは、なんなのか？

それでも、私の主張は今の時点では揺るがない。
Appleエンジニアは、親鳥がひな鳥に生きの良いシャクトリムシを与えるような仕事をするだろう。2025年が転換期だろうか？
日本のAppleエンジニアは、日本人に理解可能な形に、英文を咀嚼して質の良いガイダンスを吐き出すはずだ。
このテキストを打ち込んでいるわたしが、うんざりしていると思うか？
このテキストを呼んでいる人が、内容がなくてがっかりしているとは思う。

## 最後に
英語がないと、やっていけない日本にしたのは、紛れもなく我々日本人だ。
「美しくないけど日本！なんかとにかく残したい」派閥の山田遍音としては、Appleエンジニアか、やってこ！という感じである。
勉強をして足りないという日は来ないもんだな。
Linuxファイル管理とIOリダイレクト(一)

こんにちは、夏です。

知識を共有できるのでとても嬉しいです。新しい友達を作ることを楽しみにしています。よろしくお願いします。

# 概要
* ファイルシステムのディレクトリ構造
* ファイルの作成と表示
* ファイルのコピー、転送、削除
* ソフトリンクとハードリンク
* IOリダイレクトとパイプ

## 1. File system directory structure
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/4eb0e3e2-16c9-a574-29a2-91f6c48fe586.png)

:::note info
FHS ファイルシステム
* FHS (Filesystem Hierarchy Standard) は、ディストリビューションのメーカーや開発者が共通の標準を使用して、配布する Linux システムまたは開発するソフトウェアが共通のファイルとディレクトリの標準に準拠していることに同意するのを支援するために、Linux Foundation によって維持されています。
* FHS は、ほとんどの Linux バージョンで使用されるファイル編成形式であり、ツリー構造を使用してファイルを編成します。
* FHS は、システム内の各領域の目的、最低限必要なファイルとディレクトリを定義し、例外処理と競合処理も提供します。

公式ウェブサイト：https://www.pathname.com/fhs/
:::

### 1.1 ファイルシステムのディレクトリ構造

* ファイルとディレクトリは、単一ルートの逆ツリー構造に編成されます。
* ファイル システムは、「/」で表されるルートディレクトリから始まります。
* ルートファイルシステム (rootfs): root filesystem
* 標準Linuxファイルシステム (ext4 など)、ファイル名は大文字と小文字が区別されます (MAIL、Mail、mail、mAiL など)。
* '.' で始まるファイルは隠しファイルです
* パス分離 /
* ファイル名は255バイトまでです
* ファイル名の最大長はパスを含めて4095バイトです。
* 青→ディレクトリ、緑→実行ファイル、赤→圧縮ファイル、水色→リンクファイル、灰色→その他のファイル
* スラッシュとNULを除くすべての文字が有効です。ただし、特殊文字を使用したディレクトリ名やファイルは推奨されません。一部の文字は引用符で囲む必要があります。
* 各ファイルには2種類のデータがあります。 
    * メタデータ: メタデータ、つまり属性
    * データ: データ、つまりファイルの内容

### 1.2 ファイルシステムの一般的なディレクトリ機能
* /boot 
    * ブートファイル格納ディレクトリ、カーネルファイル(vmlinuz)、ブートローダ(bootloader、grub)が格納されるディレクトリ
* /bin 
    * すべてのユーザーが使用する基本コマンド。OS の起動時に使用される独立したパーティションやプログラムに関連付けることはできません
* /sbin 
    * 管理用の基本的なコマンド。独立したパーティションに関連付けることはできず、OS の起動時に使用されるプログラムです。
* /lib 
    * プログラムが起動時に依存する基本的な共有ライブラリ ファイルとカーネル モジュール ファイル (/lib/modules)
* /lib64 
    * x86_64 システム専用の補助共有ライブラリ ファイルの保存場所
* /etc 
    * 設定ファイルのディレクトリ
* /home/USERNAME
    * 一般ユーザーのホームディレクトリ
* /root 
    * 管理者のホームディレクトリ
* /media  
    * ポータブル モバイル デバイスのマウント ポイント(Portable mobile device mount point)
* /mnt 
    * 一時ファイルシステムのマウントポイント
* /dev  
    * デバイスファイルと特殊ファイルの保存場所、b:block device、ランダムアクセス、c:character、デバイス、リニアアクセス
* /opt 
    * サードパーティ製アプリケーションがインストールされている場所
* /srv
    * システム上で実行されているサービスによって使用されるデータ
* /tmp  
    * 一時ファイルの保存場所
* /usr 
    * universal shared, read-only data
* /usr/bin
    * システムの完全な機能を保証するために提供されるアプリケーション
* /usr/sbin
    * 上記と同じ
* /usr/lib 
    * 32ビット使用
* /usr/lib64 
    * 64 ビット システムにのみ存在します
* /usr/include
    * Cプログラムヘッダファイル（header files）
* /usr/share
    * doc、man などの構造化された独立したデータ
* /var  
    * 変数データファイル
* /var/cache
    * アプリケーションキャッシュデータディレクトリ
* /var/lib 
    * アプリケーションステータス情報データ
* /var/local
    * /usr/local 内のアプリケーションの変更可能なデータを保存する
* /var/lock 
    * ロックファイル
* /var/log
    * ログディレクトリとファイル
* /var/opt
    * /opt 内のアプリケーションの変更可能なデータを保存する
* /var/spool
    * アプリケーションデータプール
* /var/tmp
    * システムの再起動の間に生成される一時データを保存する
* /proc 
    * カーネルお​​よびプロセス情報の出力に使用される仮想ファイル システム
* /sys 
    * 現在のシステム上のハードウェアデバイスに関連する情報を出力するために使用される仮想ファイルシステム
* /selinux
    * security enhanced Linux selinux 関連するセキュリティポリシーおよびその他の情報の保管場所


次回に続きを更新しましょう
おやすみ
タスク管理を見なおそう！GTDのすすめ

この記事はHRBrain Advent Calendar 2023 18日目の記事です。

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


# はじめに
こんにちは、株式会社HRBrainでエンジニアリングマネージャーをしている阿部です。
12月も後半となり、年の瀬が迫ってきました。今週末はクリスマスですね！
みなさんは2023年にやろうとしていたこと、できましたか？
お正月やGW、夏休みなどに「2023年はこれをやろう！」と決めたこと、きちんと消化できましたか〜？

このエントリは、会社の忘年会などで今年を振り返ったときに、「2023年にやろうとしてできなかったことがある」「2024年こそ計画的にいろんなことをやってみたい！」と考えている、私を含めたみなさんのための、GTDというタスク管理についてのお話です。

# GTDを使ったタスク管理のおさらい

みなさんは普段、タスク管理をどのように行っているでしょうか？JIRA・GitHubなどの開発ツールでタスク管理をする方、手帳に書いてアナログで管理している方、さまざまだと思います。
今回紹介するGTDというタスク管理方法もそのひとつです。

ここではGTDとは何なのかの基本的な話は省きますが、GTDを使うと
- シンプルなやり方で大量のタスクを管理できる
- あとでやろうと思っていたことに取り組むきっかけを作れる
- うっかり忘れていたタスクを思い出すことができる
- 頭の中からタスクを追い出して、頭をスッキリさせることができる

ことができるのが特徴です。

GTDについて知りたくなった方は、インターネットにある各種エントリか、GTDの生みの親David Allen氏の↓の本を読んでみてくださいね。

https://www.amazon.co.jp/dp/4576060732

https://www.amazon.co.jp/dp/4576151878



# GTDがすごいこと：タスクを忘れない
よくいわれますが、GTDの素晴らしいところが「レビュー」という仕組みです。
GTDでは週次・月次・年次などで振り返りポイントを作ることができ、これまでのタスクをふりかえる機会を持つことができます。

仕事をしているときはすぐやらないといけないタスクが多く、「来月の旅行の予定を立てる」「月末までに炭酸水を買い足す」「年末の帰省の飛行機を予約する」などの「あとでやる」タスクを忘れがちです。これらは期日があるからいいですが、「フランス語をやる」「食生活を見なおす」といった、しめきりがない / 漠然とした目標はどうしてもあとまわしにしがち。

だからといって、「今週中に仏検2級のテキストの20ページまで終わらせる」みたいな具体的なタスクを作るほどテンションがアガらないときもありますよね。

GTDを使えば、こうした「あとでやる」「漠然としている」タスクを「レビュー」で定期的に見なおすことができます。毎週・あるいは毎月レビューがあるので、「年明けに目標を作ったけど、気づけば年末になっていた！」ということが、構造上起きないような仕組みが作られています。
また、「思いついたときにタスクを入れておけば、あとでレビューするときにみなおせる」という安心感もあるため、ふわっとしたタスクを気軽に作っておけます。

# GTDを使い続けて思うこと：コマンダーでいつづけよう！
私はGTDをはじめて10年ほどになりますが、GTDのいちばんすごいことは「大量のタスクをかかえているのに、頭がスッキリとすること」ではないかと思っています。
これを実現するのが、GTDの本に書いてある「自己管理の4つのマトリクス」です。

GTDでは自分の状態を4つのマトリクスを使って判断することをすすめており、うまくいっていない場合自分の立場を修正することができます。

![スクリーンショット 2023-12-18 21.44.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/914347/f7a0b42b-ae52-95b6-ef42-3b23a397f49d.png)



4つの状態とは
- キャプテン & コマンダー
- 細かすぎるマネージャ / 実装者
- 空論家 / 理論家
- 被害者 / 対応者

です。

GTDでは、上の図のマトリクスの「キャプテン & コマンダー」の状態でいられることを目指します。
とはいえいつもこの状態でいられるわけではありません。未来のことばかり考えてしまい、目の前のタスクに手がつけられない「空論家 / 理論家」の時もあれば、目の前のタスクをどうこなすかだけ考えて、大きいゴールが見えていない「細かすぎるマネージャ」状態のときもあります。
定期的にこの図を見返すことで、自分がどの状態にあるかをセルフチェックし、「キャプテン & コマンダー」の状態でタスクマネジメントできるように自分を調整していくことができます。

冒頭に書いた「大量のタスクを抱えているが頭がスッキリしている状態」は、「キャプテン & コマンダー」の状態と近いと思っています。日々の自分の状況と向き合いながら、GTD的に良い状態になるようにセルフケアしていくことが大事になるわけです。


# おわりに
HRBrainのエンジニアリングマネージャー職は、組織開発・採用・育成・メンバーマネジメントとさまざまなタスクがありますが、GTDを使って楽しくお仕事しています！

そんなHRBrainでは仲間を募集していますので、ぜひカジュアルにお話しましょう！

みなさんもGTDを駆使して、仕事もプライベートも充実した2024年を迎えましょうね！

https://www.hrbrain.co.jp
Visual Studioで呼び出された関数が分かる[呼び出し履歴]ウィンドウとスタックとメモリ

# 経緯
今日もエラーの原因調査のために地道に関数を1個ずつ見てたりネットで調べてました。
いつまで経っても結果を報告しに来ない私に、無口な先輩が遠くから「順番追えば行けるやろ。コールスタック見ろ」と声がかかります。
何を言っているのか分からないので黙っていると、先輩がすっ飛んできました。
「スタックって分かる？」

# メモリとスタックと再帰関数
スタックとは、後に入れたものが先に出る構造(FILO: First In, Last Out)になっている何かのこと。
スタックの説明でよくコップ上の絵が書いてありますよね。
![stack_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568190/f3ca9870-caae-8bf3-0381-ec14ee18a277.png)

先輩「メモリの中に変数や関数をスタックする領域がある。機械は人間が読めるような言語じゃなくて、機械語を読んでる。機械語からCPUが計算したあと、次にどこに戻ればいいかがスタックされてる。」

だから再帰関数の戻り値とか変数とか同じ関数内なのに、それぞれきれいに上へ戻して計算できるのはスタックからFILO順に結果を返しているからだそう！

# スタックオーバーフロー
stack over flow エラーって見ますよね。
これはメモリのスタックで使用している領域が足りなくなると発生するエラーだそうです。
たしかに再帰関数で終了条件を間違えた時に見たことがあります。おそらくスタックの容量が不足したんでしょうね。

# Visual Studioでも存在を確認
Visual Studioの「呼び出し履歴」はスタックを利用したものだそうです。
関数がどこから呼び出されているか順番に表示されます。
どこかにブレークを置いてデバッグ中に、[デバッグ] メニュー -> [ウィンドウ] -> [呼び出し履歴] で開きます。

- [デバッガーで呼び出し履歴を表示し、[呼び出し履歴] ウィンドウを使用する: Microsoft](https://learn.microsoft.com/ja-jp/visualstudio/debugger/how-to-use-the-call-stack-window?view=vs-2022)

英語名は "call stack window", つまり先輩が言っていた「コールスタック見ろ」が指すのは「呼び出し履歴」のことでした。

# あとがき
Atcoderでデータ構造の一種としては学びましたが、実際にどう役に立ってるか意識してなかったので、知識と経験が繋がっていって驚きました！
スタックがメモリで使われていることで、エラー内容やvisual studioの機能といった目に見える形で現れているとは気づいていませんでした。
パソコンのことは本だけではなく、実践からも学べておもしろいですね。

# 参考
- [スタックとは:「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word14717.html)
- [スタックってなあに？（2）: 東光高岳](https://uquest.tktk.co.jp/embedded/learning/lecture07-2.html)
- [デバッガーで呼び出し履歴を表示し、[呼び出し履歴] ウィンドウを使用する: Microsoft](https://learn.microsoft.com/ja-jp/visualstudio/debugger/how-to-use-the-call-stack-window?view=vs-2022)
ダイソーで買った USB接続の人感センサーケーブルを軽く試してみる【完走賞ゲット-19】

:::note info
※ [Qiita の完走賞をゲットするための条件は「単一／複数のカレンダーに投稿した記事が合計25」です](https://twitter.com/Qiita/status/1593441648796524545)
:::

この記事は、「[完走賞ゲットのため小ネタ 25記事を投稿しようとチャレンジ v2 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/youtoy)」の 19日目の記事です。

## 今回の内容
今回の内容は、以下のポストの写真左上にある「USB接続の人感センサーケーブル」に関する内容です。

https://twitter.com/youtoy/status/1736543676279742679

以下の記事や X のポストで情報を見かけて、気になっていたところ、ふと立ち寄ったダイソーでたくさん見かけたので、1つ買ってみました。

●ダイソーのUSB人感センサーケーブルに可能性を感じる〜 - あっきぃ日誌
　https://akkiesoft.hatenablog.jp/entry/20231217/1702791482

それをさっそく試してみた、という話です。

### 余談
軽く今回のお試しをしてみたら、活用できそうな感じだったので、買い足してしまいました 笑

https://twitter.com/youtoy/status/1736593815597953089

### 仕様に関する補足
まず、パッケージに書かれた情報から、仕様を確認してみます。

![パッケージに書かれた情報](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3bbd99ca-be69-c146-a308-82ba5adc2509.jpeg)

パッケージに書かれている内容を抜粋して、以下に記載してみます。

- 仕様の抜粋
   - 周囲 2m（角度 120度）を感知
   - 感知後は 1分間通電
   - 電源供給は 5V/1A 以下にする必要あり
   - 電源供給機能のみでデータ転送は不可
   - 手動での ON/OFF は不可
   - USB接続は Type-A
   - ケーブル長 22.5cm

## 実際に使って試す
それでは、実際に試してみます。

お試し用に使うものとして、前に以下の記事に書いた「USBテープ COBライト（COBラインテープLED）」を使いました。
※ この時に入手していたテープLED は、5V/1A で動作するくらいの長さのものを入手していました

●USB接続で簡単に使える「USBテープ COBライト（COBラインテープLED）」や LEDテープの情報のメモ #LEDテープ - Qiita
　https://qiita.com/youtoy/items/f1587b5f23ef015e0676

動作させた時の様子は、以下のとおりです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/tdNKfhFcBk8?si=O-qrDqXFrP9F_9r-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

この距離で撮影していると、時間センサーがずっと反応し続けてしまうため、このお試しではセンサーまわりを覆い隠すようにしました。

そして、1回目に反応させる時は、その覆い被せていたものを取り外しました。
2回目は、覆いはそのままで、センサーが反応しそうな位置に手をもっていきました。

動画では途中を省略してますが、センサーを 1度反応させてから、センサーまわりを覆ったあとは約1分後に LED が消灯しました。上で書いた仕様通りの動作をしてそうなことが確認できました。

## この後に試したいこと
とりあえず、想定通りに動作するのを確認できました。

この後は、USB給電で動く Wi-Fi搭載の機器を使って IoT的な方向のことと人感センサーとを組み合わせてみたり、外部モジュールを制御できて USB給電で動くデバイスで、人が近づくと何かが起こるような試作をやってみたいと思っています。
（元々、そういう方向で活用できそうかを確かめるために、まずは 1つだけ買って試したというのがありました）

### 【追記】 IoT的なことができるデバイス関連
M5Stack系のデバイスで、USB に直差しできる ATOM U を組み合わせると、接続も楽で、人に反応する／人がいる時だけ動作する IoT な何かが作りやすそうかもしれないです。

https://twitter.com/youtoy/status/1737117294306926999

## おわりに
今回、ダイソーで買った USB接続の人感センサーケーブルを軽く試してみました。
USB給電のデバイスに、手軽に人感センサーの機能を付け足すことができて、とても便利に使えそうなデバイスでした。

### 【追記】 合わせ買いしたケーブルについて
その後、USB接続の人感センサーケーブルと合わせて買っていた、スイッチ付Type-Aケーブルについても記事を書きました。

●ダイソーで買ったスイッチ付Type-Aケーブルを手持ちのアイテムと組み合わせて試す【完走賞ゲット-21】 #ダイソー - Qiita
　https://qiita.com/youtoy/items/a9c84b87399cd0cc0345
[Laravel]脱FatController

## はじめに
こんにちは。この記事は[ラクス Advent Calender 2023](https://qiita.com/advent-calendar/2023/rakus-partners)  19日目の記事です。
エンジニア歴1年で、現在はPHPのLaravelを使用して個人開発を行っています。
今までは何もわからず全てのコードをControllerに書いており、いわゆる典型的なFatControllerで修正のしにくいコードでした。
そこで、SkinnyControllerを目指すことにしました。

## FatControllerとは
文字通り太った(記述量が多い)Controllerのことを指します。
Controllerはただ一つの責任だけを持たないといけないのに、複数の責任を持ってしまっている状態です。

これの何が問題なのかというと、「コードの可読性が落ちる」ことです。
コードが長すぎると、どこに処理を書いたのかがわからなくなります。
また、同じ処理を至る所で書いている場合が多く、改修漏れが生じやすくなってしまいます。
以下が今まで書いていたFatControllerの一部抜粋です。

```php:PlayerController.php
public function index()
    {
        ...
        
        $player = Player::with('position')->orderBy('name')->get();


        return view('index', compact('player'));
    }

    public function select(Request $request)
    {
        ...

        $select = $request->select;

        if ($select == 1) {
            $player = Player::with('position')->orderBy('name')->get();
        } else if ($select == 2) {
            $player = Player::with('position')->orderBy('uniform_number')->get();
        }

        ...

        return view('index', compact('player'));
    }
```
このように同じコードを2回も書いてしまっています。

## FatModel、SkinnyController化してみる
- DBに関するロジックはModelクラスに入れる
```php:Player.php
class Player extends Model
{
    public function getNamePlayer()
    {
        return $this->with('position')->orderBy('name')->get();
    }

    public function getUniformPlayer()
    {
        return $this->with('position')->orderBy('uniform_number')->get();
    }
}
```
- ビジネスロジック(if文など)はServiceクラスを独自で作成し、その中に入れる
```php:PlayerService.php
class PlayerService
{
    private $player;

//インスタンス化はコンストラクタに記入
    public function __construct()
    {
        $this->player = new Player();
    }

    public function selectPlayer($request)
    {
        $select = $request->select;

        if ($select == 1) {
            return $this->player->getNamePlayer();
        } else if ($select == 2) {
            return $this->player->getUniformPlayer();
        }
    }
```

- メソッドをControllerで呼び出す
```php:PlayerController.php
public function index()
{
    return view('index', ['player' => $this->player->getNamePlayer()]);
}

public function select(Request $request)
{
    return view('index',['player' => $this->service->selectPlayer($request)]);
}
```
それぞれのメソッドが一行で書けるようになりました。
name順に並んだplayerを取得したい場合に
```
$this->player->getNamePlayer();
```
を書くだけでどのControllerからも呼び出すことができ、nameではなく、別のカラムでsortしたい場合はModelクラスのメソッドのみを修正すればいいようになります。

## まとめ
FatControllerを修正したことにより3つの利点があることに気づきました。
- 1つ目は、文字通りControllerがスッキリしたことによりコードが見やすくなったこと。 
- 2つ目は、機能をメソッドごとにまとめることによって同じ機能を別のControllerでも使用できること。
これにより何回も同じコードをいろんなところで書かなくて良くなります。
- 3つ目は、改修漏れを減らすことができること。
同じコードを何度もいろんなところで書かなくて済むことによって何か修正があった際にそのメソッドのみを変更するだけで済みます。

今回、脱FatControllerをしていく中で、コードがスッキリする以外にも改修漏れを減らせることを知りました。
今後も開発をする上でSkinnyControllerを意識しながらコードを書くようにしていきたい...!
Terraformのベストなディレクトリ構成

Terraformのディレクトリ構成は色々あり、どれも長所短所ありますが、規模が大きくなってくるとある程度形が決まってきます。

私が良いと思うディレクトリ構成を紹介します。

## ①環境ごとにフォルダを分ける

一番多いのがこのパターンだと思います。ディレクトリ構成のベストプラクティスとして検索すると大抵これです。分かりやすいですよね。各環境フォルダに入って`terraform`コマンドを叩きます。

```
root
  |--modules
  |--envs
      |--development
          |-- main.tf
          |-- outputs.tf
          |-- provider.tf
          |-- README.md
          |-- terraform.tf
          |-- variables.tf
          |-- README.md
      |--staging
          |-- main.tf
          |-- outputs.tf
          |-- provider.tf
          |-- README.md
          |-- terraform.tf
          |-- variables.tf
          |-- README.md
      |--production
          |-- main.tf
          |-- outputs.tf
          |-- provider.tf
          |-- README.md
          |-- terraform.tf
          |-- variables.tf
```

### メリット

- 分かりやすい
- 文献が多い

### デメリット

- 環境ごとにファイルを作成するため差分が出てきやすい
- 階層が（少し）深い

## ②環境ファイルで分ける

環境を丸々ディレクトリで分けるのではなく、環境変数のみを分けて、それを呼び出します。そのため、リソース名などが環境変数できっちり分離されます。

```
root
  |--main.tf
  |--outputs.tf
  |--provider.tf
  |--README.md
  |--terraform.tf
  |--variables.tf
  |--modules
  |--envs
      |--development
          |-- terraform.tfvars
          |-- backend.tfbackend
      |--staging
          |-- terraform.tfvars
          |-- backend.tfbackend
      |--production
          |-- terraform.tfvars
          |-- backend.tfbackend
```

## メリット

- root直下で実行可能（なので移動が楽）
- 最低限の設定ファイルだけを各環境用のディレクトリにおけば良い

## デメリット

- コマンドが長くなる
- 環境ごとに柔軟な構成を作ることが難しくなる
    - `terraform init -backend-config=envs/development/backend.tfbackend`
    - `terraform plan -var-file=envs/development/terraform.tfvars`

## 個人的な見解

特にこだわりがなければ、「①環境ごとにフォルダを分ける」にするのが良いと思います。ディレクトリごとに環境が分かれていて分かりやすかったり、Terraform Cloudで環境ごとにワークスペースを作成して実行できるからです。ただし、環境差分が出ないように注意しましょう。

また、Terragruntを利用するのもありですが、学習コストなどが発生するため周りと相談するのが良いです。
Specification of Vehicle Update and Configuration Management, AUTOSAR 1090, R23-11, AP

Specification of Vehicle Update and Configuration Management, AUTOSAR 1090, R23-11, AP
https://www.autosar.org/fileadmin/standards/R23-11/AP/AUTOSAR_AP_SWS_VehicleUpdateAndConfigurationManagement.pdf



<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

# Release Overviews
Classic Platform Release Overview, AUTOSAR No.0 ,R23-11, CP
https://qiita.com/kaizen_nagoya/items/8468435185e109189ead

Foundation Release Overview, AUTOSAR 781, R23-11, FO
https://qiita.com/kaizen_nagoya/items/f249bdb8c313d8bff883

Adaptive Platform Release Overview, AUTOSAR 782, R23-11, AP
https://qiita.com/kaizen_nagoya/items/13a104606a34fe24fcf7
# Terms
|terms(Acronyms and abbreviations)| Description|
|:--|:--|
DM|AUTOSAR Adaptive Diagnostic Management
UCM|Update and Configuration Management
V-UCM|V-UCM is distributing packages and coordinating an update cam- paign in a vehicle (former name was UCM Master)
Backend|Backend is a server hosting Software Packages
OTA Client|OTA Client is an Adaptive Application in communication with Backend Over The Air
Vehicle Driver Application|Vehicle Driver Application is an Adaptive Application in communication with Vehicle Driver Human to Machine Interface
Application Error|Errors returned by UCM
Boot options|Boot Manager Configuration
VCI|Vehicle Communication Interface
MVCI|Modular Vehicle Communication Interface
D-PDU API|Diagnostic Protocol Data Unit Application Programming Interface
RDF|Root Description File
MDF|Module Description File
integrity check|verification method proving there has not been any alteration of the artefact content
dependency check|verification method proving that all configured dependencies will be fulfilled after finishing the activation.


# Reference
[1] Glossary AUTOSAR_FO_TR_Glossary
https://www.autosar.org/fileadmin/standards/R23-11/FO/AUTOSAR_FO_TR_Glossary.pdf
[2] General Requirements specific to Adaptive Platform AUTOSAR_AP_RS_General
[3] Explanation of Adaptive Platform Software Architecture AUTOSAR_AP_EXP_SWArchitecture
[4] Requirements on Vehicle Update and Configuration Management AUTOSAR_AP_RS_VehicleUpdateAndConfigurationManagement
[5] Specification of Update and Configuration Management AUTOSAR_AP_SWS_UpdateAndConfigurationManagement
[6] Explanation of Adaptive Platform Design AUTOSAR_AP_EXP_PlatformDesign
[7] Specification of Manifest AUTOSAR_AP_TPS_ManifestSpecification


# 補足資料（Additions）

2023 Countdown Calendar 主催・参加一覧
https://qiita.com/kaizen_nagoya/items/c4c2f08ac97f38d08543

CountDownCalendar月間　いいねをいただいた記事群　views　順
https://qiita.com/kaizen_nagoya/items/583c5cbc225dac23398a

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.

# 文書履歴(document history)
ver. 0.01 初稿 　20231218
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
BigQueryのGCS外部表に列レベルセキュリティを設定する方法

GCSに配置したCSVファイルなどをBigQueryの外部表として設定するときに、列レベルセキュリティを使って列単位で閲覧制限をかけたい場合の設定方法を説明します。

# GCS外部表の2つの形式
具体的な設定を説明する前に、GCSに配置されたオブジェクトをBigQueryの外部表として参照するには2つの方法があることを説明します。

１つ目がCloud Storage external tableで、2つめがCloud Storage BigLake tableです。

https://cloud.google.com/bigquery/docs/external-data-cloud-storage

https://cloud.google.com/bigquery/docs/create-cloud-storage-table-biglake

この2つはできることがほとんど同じなため、違いを意識せずに使っている人も多いかと思います。
実際に自分も1年前くらい前までは違いがわかりませんでした。
しかし、列レベルセキュリティを使う場合はこれらの違いを理解することが重要です。

前者のCloud Storage external tableは昔からある方法です。
BigQueryでSELECT文を実行したとき、実行者自信がGCSのオブジェクトを読み出す権限を持っている必要があります。
そのため、ファイル単位でしか権限管理ができず、ファイル内の特定の列だけを読み出す権限を与えるということはできません。
これはGCSの権限の最小単位がファイルである以上しかたないです。

一方で後者のCloud Storage BigLake tableはBigQueryからGCSを読み出すためのリソースであるConnectionというものを作成し、このConnectionに紐づくService AccountにGCSの読み出し権限を与えます。
そのため、SELECT文の実行者にはGCSの権限を一切付与しなくても良いです。
権限管理はBigQueryテーブルでのみ行うために、こちらの方法では列単位で権限を与えることもできます。

# Terraform
先程の議論を踏まえて、terraformでCloud Storage BigLake tableを作成していきます。
まずはConnectionを作成します。

```terraform
resource "google_bigquery_connection" "gcs-resource" {
  connection_id = "gcs_resource"
  location      = "US"
  description   = "Connection for GCS Resource"
  cloud_resource {}
}
```

そして、ConnectionのServiceAccountがGCSからデータを読み出せるような権限を付与します。
`cloud_resource` が配列になっているのがやや気持ち悪いですが、そういうものだと思いながら `[0]` します。

```terraform
resource "google_storage_bucket_iam_member" "static-data-table-connection-grant" {
  bucket = "バケット名"
  role   = "roles/storage.objectViewer"
  member = format("serviceAccount:%s", google_bigquery_connection.gcs-resource.cloud_resource[0].service_account_id)
}
```

最後に以下のようにスキーマを記述したJSONファイルを指定してテーブルを作成します。
どの列に列レベルセキュリティをいれるかはJSONファイル中で指定します。
複数個のPolicyTagを指定できそうな雰囲気をしていますが、2つ以上指定するとエラーになってしまいます。

```terraform
resource "google_bigquery_table" "static-data-table" {
  project    = "プロジェクトID"
  dataset_id = "データセット名"
  table_id   = "テーブル名"
  schema     = jsonencode(file("スキーマを記述したJSONファイルのパス"))

  deletion_protection = false

  external_data_configuration {
    # このあたりのオプションは各自の環境で変える
    source_format = "CSV"
    compression   = "NONE"
    autodetect    = false
    connection_id = google_bigquery_connection.gcs-resource.id

    source_uris = [
      "読み込みたいファイルのパス"
    ]
  }

  # Ignore connection_id because the difference will appear even though the connection_id has not changed.
  # https://github.com/hashicorp/terraform-provider-google/issues/12386
  lifecycle {
    ignore_changes = [external_data_configuration[0].connection_id]
  }
}
```

```json
[
  {
    "name": "col1",
    "type": "STRING",
    "mode": "NULLABLE"
  },
  {
    "name": "col2",
    "type": "INTEGER",
    "mode": "NULLABLE",
    "policyTags": { "names": ["ポリシータグ"] }
  }
]
```
LangChainでFAISSのドキュメントを一括取得してID指定で削除する

タイトルの方法です。

それぞれ `a.txt` には大文字の`A` が入っているようなシンプルなテキスト3つを用意してロードします。

```python
from pprint import pprint
from langchain.document_loaders.text import TextLoader
doc_a = TextLoader("./data/a.txt").load()
doc_b = TextLoader("./data/b.txt").load()
doc_c = TextLoader("./data/c.txt").load()

pprint((doc_a,doc_b,doc_c))
```

```python
([Document(page_content='A', metadata={'source': './data/a.txt'})],
 [Document(page_content='B', metadata={'source': './data/b.txt'})],
 [Document(page_content='C', metadata={'source': './data/c.txt'})])
```

これらをDBに取り込みます。

```python
from langchain.vectorstores.faiss import FAISS
db = FAISS.from_documents(documents=doc_a,embedding=llm)
db.add_documents(doc_b)
db.add_documents(doc_c)
```

まずDBのデータを検索でなく、一括取得する方法です。（ `_` 始まりの変数なのですぐ変更になってしまう可能性も高いです）

```python
pprint(db.docstore._dict)
```

ここで出力される`e5ef500d-1e31-467d-af14-55f156debac5`のような Keyとなっている部分がDocumentのIDとなります。

```python
{'1a0abd38-3059-46d0-9ded-9082ad25f876': Document(page_content='C', metadata={'source': './data/c.txt'}),
 '53892d26-24b8-4288-999f-266336f902b5': Document(page_content='A', metadata={'source': './data/a.txt'}),
 'e5ef500d-1e31-467d-af14-55f156debac5': Document(page_content='B', metadata={'source': './data/b.txt'})}
```


このIDを指定して `delete()` メソッドを利用すればDocumentをDBから削除可能です。

例えば以下のようにすると `B` のDocumentを削除可能です。

```python
# 削除前の検索
print(db.similarity_search("b",k=1))
# -> [Document(page_content='B', metadata={'source': './data/b.txt'})]

# Bのドキュメントを削除
db.delete(ids=["e5ef500d-1e31-467d-af14-55f156debac5"])

# 削除後の検索
print(db.similarity_search("b",k=1))
# -> [Document(page_content='C', metadata={'source': './data/c.txt'})]
```


`ids` は複数していできるので、上記で `db.docstore._dict` の結果をmetadataでフィルタして指定するなども可能です。
機会がなければ作ればいいじゃない式「組織変更シミュレーションのワークショップ」

[クラウドワークス Advent Calendar 2023](https://qiita.com/advent-calendar/2023/crowdworks) の18日目の記事です。

はじめまして、「クラウドログ」でエンジニアをしています武田です。
今回は開発合宿で行った「組織変更シミュレーションのワークショップ」について、簡単な紹介と感想を共有してみたいと思います。

# はじめに
クラウドログでは半年に１回くらいの頻度で開発合宿を開催しています。
その中の取り組みとして、開発組織の方針や課題に関するワークショップを実施したいと考えていたところ、「もっと開発組織全体を意識して行動を促す方法はないだろうか？」と思い、「組織変更シミュレーションのワークショップ」を実施することにしました。
意外と楽しみつつも、属人化や組織課題について洗い出せる効果があるのでは？と感じたため、記事にしてみることにしました。

# ぜひ読んで欲しい方
![対象者.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335934/fa978685-cf6d-6446-7bcd-ed7f1ea28148.png)
* 開発組織全体の課題に対して向き合ってる方
* 良さそうなワークショップを探している方
* クラウドワークス、クラウドログに興味を持っている方


# なぜ、組織変更シュミレーションをやったのか？
「もっと開発組織全体を意識して行動を促す方法はないだろうか？」という考えをベースに、下記のようなブレインストーミングから「組織拡大のシミュレーションワークショップ」の実施へたどり着きました。

1. 開発組織全体を意識して行動して欲しいと思うのは、自分が開発組織全体について考える機会があるからではないか？
1. メンバーレベルで開発組織全体を意識する機会が少ない？
1. 開発組織全体を意識するようなきっかけがあれば、意識しやすくなる？
1. きっかけがないなら、いっそシミュレーションできっかけを作れば面白いのでは？

**組織変更シミュレーションをワークショップとしてやってみよう！**

ということで、組織変更シミュレーションのワークショップを実施してみました。

# 組織変更シミュレーションのワークショップの内容

このような内容で40分程度のワークショップを実施します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335934/26de96cf-8c16-40c8-bb02-bc9937f34102.png)


```
<問題>
* 今後開発組織が拡大していった時のことをイメージして組織体制を考えてください。
* あなたに組織変更の権限がある前提で考えてください。

<前提条件>
* 新しいサービスを立ち上げることになりました。
* 現在のチームに加えて、新しいサービスのチームを立ち上げる必要があります。
* 4名新しいメンバーが増えます。（マネジメント経験なし、若手）

<ゴール>
* 既存・新サービスの組織図
* 組織拡大に伴って生じる課題
* 上記に対しての解決策
```

このワークショップは組織変更と向き合い、現在の組織課題や懸念をディスカッションすることがゴールです。
特に下記のような課題や懸念が発生することを期待しています。
* 人の異動により発生する属人化問題
* マネジメントできるメンバーの配置問題
* 新しいサービスを軌道に乗せるための人員リソース問題

このような課題・懸念は現在の組織における潜在的なものであり、上手く運用できているチーム程現れないものなので、このワークショップを実施することで洗い出すことができます。

# 組織変更シミュレーションのワークショップのやってみた感想

３つのチームで実施しましたが、各チーム毎にフォーカスする課題や懸念が異なり、熱いディスカッションが行われていました。
また、組織変更シミュレーションという普段やらないワークショップを楽しめたという声や、潜在的な属人化や組織課題を実感できたという声もありました。
（中には新チームは私が率いるんだ！と熱くなっていたメンバーも・・・w）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335934/e8f6b9a5-bdc4-606a-e476-14b7a3b01896.png)


# まとめ
機会がなければ作ればいいじゃない！という発想から、まだまだやり方に粗はありますが組織変更に対する考え方をチームで検討するというワークショップの実施ができました。
今後も組織課題をチーム内で洗い出し、同じ方向を向けるようなワークショップを実施していきたいと考えています。
今年もお疲れ様でした！
Dev Containers入門～Dev Containersってなんだ編～

# はじめに
ついこないだPyCon行って、Dev Containersの話を聞いてきました。
すごく良さそうだったんで、今後社内でも展開していきたいと考え
まずはその入り口として調べたことに私なりの補足をして書き残しておきたいと思います。

まだ使い始めなのもあって、具体的な使いかたには触れません。
なんとなく「こんなものだ」を感じ取っていただくためのお話になっておりますのでご了承ください。

# こんな事がありそうな組織ほどDev Containersがマッチしそう
弊社のエンジニアは会社支給のPCをある程度選べるようになっていて多数のMac派、少数のWindows派となっています。

以下はフィクションですが、こんなこと起きてませんか？

```
Aさん(Mac派) ＜ Bさんの開発環境構築手伝ってるけどWindowsだとすごい大変でさぁ。
　　　　　　 　 もうWindowsは世の中から無くして欲しいんだよね。

Bさん(Win派) ＜ は？MacなんてARMアーキテクチャとかいうスマホ用CPUで動くモバイルもどきっしょ？

Aさん(Mac派) ＜ CPUの話にすり替えても勝ち目がない事わかってないなぁ。
　　　　　　 　 Appleシリコンは旧世代のx64アーキテクチャCPUを
　　　　　　 　 コスパやエネルギー効率面で周回遅れにしてっから。
　　　　　　 　 旧世代のCPU載ってるPCはもう旧世代のPCだよね。
　　　　　　 　 Windows PCって歯車でうごいてそう。プー。クスクス。

Bさん(Win派) ＜ ぐぬぬ。。。（エネルギー効率って！MacBookAirの発熱問題とか起きてんじゃんか！！）

神　＜ 開発環境構築の差を切っ掛けにOS戦争をするのは おやめなさい。"Dev Containers"を使うのです。
```

※ もう一度書きますが、上記の言い争いは完全なるフィクションです。私が脳内で何も事実に基づかないノリだけで思いついた会話を書いてます。『どうやら環境構築がめんどうでOS戦争に発展した』とだけ感じ取っていただければ幸いです。私はMacも使いますがWindows派で会社支給PCもWindowsです。（神が仲裁に入る事なんてありえないんで、どう考えてもフィクションです。）

神の思し召し通りにDev Containersを使うと開発環境構築の手順もOSによる差も格段に減る雰囲気があるのがなんとなく感じ取れましたね。

# これまでの開発
以下は、私が関わるプロジェクトの開発環境 ２大パターン。
①、②どちらもですがエディタ/IDEが実行環境を参照して構文チェックをしています。
②に関しては実行環境がContainerにあるので、エディタ/IDEの為にLocal OSにも実行環境を用意することになってしまっています。

①Local OSにコンパイラや実行環境などが全てあるパターン
![Pasted image 20231218190505.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153651/f04073f5-c2eb-05de-a09d-e9392c85a2e2.png)

②コンテナ上にコンパイラや実行環境などがあるが、エディタがコンパイラなどの実行環境を参照しているので、仕方がなく一通りの実行環境をLocal OSにも用意しているパターン
![Pasted image 20231218190943.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153651/1576205a-373d-15a7-10f3-a5313371f907.png)


# Dev Containersを使ってからの開発

Local OSにはVS Code(Dev Containersの拡張機能入り)とソースコードがあれば、Dockerのコンテナ内に展開された実行環境類を使って開発及びアプリの起動までできてしまうようになります。
また、このコンテナImageを共有することで誰もがLocal OSの縛りが無く同じ開発環境となり、一度作ったImageは他社に共有して使えるので、メンバーが増えるたびに再構築することもなくなります。
※ しれっとinteliJの記述を消したのは、inteliJでのDev Containersの詳しい資料を見つけられなかったので、どんな状況かわからずウソや勘違いを減らすために消しました。
![Pasted image 20231218205909.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153651/a989d764-e876-cc91-ed8f-327d8a1dbb8d.png)
参考サイト：
https://code.visualstudio.com/docs/devcontainers/containers

# 最後に
「はじめに」でも触れましたが、まだ使い始めなのもあって自分なりの考えが纏まっているところまでに内容をとどめました。
これからもっとDev Containersの知識を増やしていきたいと思います。

知識も深めて気力が湧いてきたら、この続き（AさんとBさんのケンカの行く末も含めて）書いていきたいと思います。
循環的複雑度を計算してみよう

コードの品質が気になる年頃です。

# 循環的複雑度
https://ja.wikipedia.org/wiki/%E5%BE%AA%E7%92%B0%E7%9A%84%E8%A4%87%E9%9B%91%E5%BA%A6

> M = E − N + 2P
ここで
M = 循環的複雑度
E = グラフのエッジ数
N = グラフのノード数
P = 連結成分の個数

Wikipedia によると、循環的複雑度は上記のように定義されるようです。連結成分内に分岐なしのとき、その連結成分の寄与は 1 になります。制御フロー上に辺が増えるごとに値は 1 増えていきます。

つまり、これはフロー上の全辺被覆テストをする際に必要な最小の試行回数に等しいです。

# 計ってみよう
ちょうどいいライブラリがあります。`pip` で簡単にインストールでき、シェルや python から使えます。
https://github.com/terryyin/lizard

```sh
pip install lizard
lizard {計測してみたいプログラムのパス}
```

閾値を設定してあげると、循環的複雑度が閾値を超えたらプログラムが失敗するようになります。デフォルト閾値は 15 です。

## 注意点
node_modules ディレクトリは除くようにしましょう。ありえないほど時間がかかります。
```sh
lizard -x "{node_modules のパス}/*"
```
上記のような形で除外パスの指定ができます。

# おわり
CI に入れたら捗るかも！？