OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Glueを使用したS3からRDS（MySQL）へのデータ取り込み3

## Crawlersの設定

RDSに接続できるようになったら、クローラーの設定を行う。
自分なりの解釈だが、GlueがETL処理を行うために、書き出し先の構造を取得する処理と考えている。

GlueのDatacatalog→Crawlers→Create crawlerボタンを押下する。（オレンジのやつ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/57ab4209-2695-c4c4-ed3b-2381e4a08ec8.png)

### Step1
クローラーの名前と説明を書く画面。
好きな内容を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/6d27e592-c312-32b7-13ae-48556cb0faf8.png)

### Step2
これは初めて作るので、Not yetを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/e59327ee-3acd-075b-1843-050159c7d990.png)

「Add a data source」ボタンを押下。

Data source：JDBS
Connection：接続対象のインスタンスを選択
Include path：MySQLの場合は「接続対象のDB名/%」を入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/3179e597-db38-da19-e587-17e04f223705.png)

### Step3
Glue用に作ったIAMロールを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/57d92326-cf9c-5173-851b-d23942f12c03.png)

### Step4
Target database：接続対象のデータベースを選択する
今回は自動更新しないので、スケジュールはOn demandにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/731f0631-2e25-8cb3-4c32-3805ce5492a9.png)

### クローラーの実行
対象のクローラーを選択して、Runボタンを押下する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/be70a184-942d-f001-d7c4-a3d2aba1a527.png)

成功すると、Databasesに新たな行ができる。
Nameのリンクを押下すると、データベース内のテーブル一覧を見ることができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390179/78665ca4-d008-1add-d324-42fb197193cb.png)

これでやっとETLの準備完了。
今まで用意したものを使ってジョブを作成する。
読書記録をつけよう

この記事は [一分で読める小ネタのカレンダー | Advent Calendar 2023 - Qiita](https://qiita.com/advent-calendar/2023/raki) の１９日目

# 読書のすすめ

- 今月、今年、どれだけの本を読んだか
- 読書習慣の大切さは今更語らない
- ちなみに、ビジネス書でも技術書でも小説でも雑誌でも、極論漫画でも、読む本はなんでもいいと思っている派
- 読書で得た知見や感想をいつどのように活かすかは人それぞれだと思うので
- 大事なことは読書を楽しむことかな（建前

# 読書方針をつくる

- 例だよ。自分にあった読書習慣をつくろうね
- 最初から最後まで読まなくてもいいし、流し見したって構わない
- 年に一冊くらい守備範囲外、今まで読んだことのない方向の本を読んでみよう
    - 新しい何かを発見するの楽しいよ
    - 分野の辞典とか図鑑から入ると枠組みが理解しやすくて楽だよ
- 半年に一冊くらいは既存の分野を更新する本を読もう
    - IT系は特に定期的な更新が役に立つよ
    - 正確には既存に関連している別のもの、くらいの
    - 今まで触っていなかったフレームワークとか、ツールとか
- 月に一冊くらいは趣味の本を読もう
    - IT系の月刊誌の休刊が多くて困るね
- 週に一回は目を通す癖を作ろう
    - リーダブルコードの目次を読み返すだけでも
    - 積読の１節を消化するでも

本文はここまで。以下は時間外

# 読書記録をつける

- ブクログ, 読書メーター等の専門サービス
- Notion などのデータ管理（もできる）サービス
- ScrapBox 等の（なんでも）記録サービス
- Obsidian, OneNote 等の基本的にはローカルなノート
- git 等（読む本をissueにして感想をPRにするとか、登録フォームをテンプレにするとか、ラベル管理とか）
- til に読んだ本のタイトルを書いてもいいけど、毎日書くのは正直だるくなる。。。ｗ

# 読書の損益

- 本を読む前に一瞬考えると集中力が変わるので試してみて
- 読書で得られるものといえば
    - 今後ずっと使える知見（賢者は歴史に学ぶって言うしね）
    - リフレッシュ（漫画やラノベで気分転換になるならいいよね）
    - 考える力（他にも挙げられると思うけど、そういったの全部含めて培った考える力だよね）
- 逆に失うものといえば
    - 時間（よし！速読だ！ｗ）
    - お金（当たり外れはあるよね）

# 読書で思考を（システム開発の方向に）広げるテスト

- 要は自分で作るならどんなものを作るか
- 読書の履歴を残す時に必要なもの
    - 本のタイトル
    - 読んだ日時
    - とりあえずこの２つがあれば履歴としてのテイはできる
- あるといいもの
    - ISBN（Amazonさんに頼り切るならASINでもいいけど）
    - 書誌情報（今はネットでいくらでも集められるから便利でいいよね）
        - 著者
        - 発売日
        - 出版社等
    - 書誌情報にはないタグ等（分類したり特徴付けしたりユーザ作成）
    - 感想
    - 星（点数的な。複数の項目があるとなお可。）
- 既存にある機能
    - 検索と自動入力（たいていのサービスは本を検索して選択することでベースの情報ができる）
    - 絞り込み
    - SNS連携（個人的には要らないんだけど）
- 自分が欲しい機能
    - 使えるキュレーション（複数の方法からおすすめできるとなお可。売りたい本の押し付けはいらぬ）
    - 毎日、または毎週でも見る、触る価値があるコンテンツ
- データ構造を考える
    - ER図的な
    - RDBではないものも使う？
- アプリケーション構造を考える
    - API（モバイル） ファースト
    - SPAにするか、レガシーにサーバーサイドレンダリングするか
    - 表示データのほとんどがキャッシュ（CDN）に乗るべき
    - コストも踏まえて
    - セキュリティも忘れないで
- みたいなことを読書以外のことにも当てはめて考える癖を作ると、世の中ってすごいなぁってｗ

# 改善依頼

- 面白かった本を教えてください
- 技術書の良書があったらぜひ
システム障害対応実践ガイドを読んで備えておく

この記事は、株式会社カオナビ　Advent　Calendar　2023　シリーズ2の２日目です。

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

株式会社カオナビでプロダクトディベロップメント本部技術基盤部サービスオペレーションGでマネージャーやってます。

前職のSIerでも最初から保守運用要員でエンジニア人生をスタートしているせいか、気がついたら障害対応やインシデントの中に身を置くことに何も抵抗がない体になってしまいました。

2023年9月19日に刊行されました『3カ月で改善！システム障害対応 実践ガイド インシデントの洗い出しから障害訓練まで、開発チームとユーザー企業の「協同」で現場を変える』が、とても良かったので紹介しておきます。

https://www.amazon.co.jp/dp/479817890X/

この本に興味を持って手を取る人には、なんだか歩んできた道のりに近しい属性を感じます。

## 珍しい障害対応ガイド本

細かい目次は読んでいただくとして大きく３つのパートに分かれています。

1. 障害対応とその改善を見つめ直す
1. 障害対応の成否を分けるものを知る
1. 障害対応の改善を実践する

さらに各パートで分かれているので、自分達に今必要なものはなにかというの考えた上でポイントで読んでいくことも可能です。
個人的には２つ目の「障害対応の成否を分けるものを知る」は、どんな人でも読んでおいた方が良いのではないかなと思います。

## ここが参考になると感じたところ

個人的にはCHAPTER8第5週の「システム障害発生時のアクション定義」です。例として

1. ユーザーへの初訪連絡
1. 関係者へのエスカレーション
1. サーバー・プロセスの再起動
1. モジュールの切り戻し
1. 技術チームへの支援要請

が挙げられています。　特にシステム障害対応をしていると1と2がおざなりになってしまうケースがあるので、忘れずにプロセスに組み込むなりワークフローに組み込むなりをした方が良いかなと思ってます。

カオナビでもインシデントが発生したときのワークフローは整備されていて、一報をどこに出すとかSlackのどこのチャンネルで関係者に周知するのか、といったものがSlackのワークフロー上で実装されています。

## 定期報告は大事

もう１つ忘れがちなのが定期報告及び一報の内容の更新です。ワークフロー上で書道の報告のタイミングはあれど、その後定期的に報告をするというのは忘れがちなので、30分毎や1時間毎に状況の確認と報告内容のアップデートはかかさないように仕組みを作っておくことが重要だと思います。

## アクションを整理するだけでも良し

第7週「「アクション実行の役割と権限の定義」もとても参考になると思います。インシデント自体はいつ起こるかわからないもので、いざ起きたときが最初に体験する実践体験ということも少なくないと思います。

その時に何をすれば良いのかわかっていないと状況だけが進んでいってしまうため、整理できていることがとても重要です。

特に判断する人、実行する人を決定するポイントもまとまっています

1. できる人ではなく、やるべき人を選択する
2. 急を要する事態の場合は、判断する人と実行する人を同じにする
3. 役職者が判断者となる場合は、アクション内容・判断情報・判断基準を意識してもらう

自分も一応役職者なので、特に3番目はめちゃくちゃ欲しい情報で頷けます。
個人的には判断者も待っているだけではなくて積極的に動いて情報収集するべきかなと思います。

## いざという時に困らないために

他にも『システム障害対応の教科書』もとても参考になります。

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

事前にこういった書籍で情報を知ることができるのは大変ありがたいので、いざ本番で起きたときに困らないように、事前に『システム障害対応 実践ガイド』を読んで備えておきましょう。

![IMG_5863.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29845/797e7fb8-b79b-6f03-f81d-5b2b0a8497f6.jpeg)
VIRUSTOTALで、フィッシングサイトかどうか確認する

# 概要

仕事をしている途中、以下のような迷惑メールがまぎれることがある。

```
拝啓 @会社のメールアドレス、

お使いのxxxアカウントはアップグレード段階に達しました。引き続きご利用いただくために、ユーザーのメールを確認していただく必要があります。

この手続きはアカウントの安全性を確保するために重要です。以下のリンクをクリックして手続きを進めてください：

フィッシングサイトと思われるリンク。

この重要事項への速やかな対応、誠にありがとうございます。

よろしくお願いいたします。

敬具、

```
こういった内容は明らかに日本語の文面からもおかしいと思われるが、フィッシングメールと確定させるために以下のような内容を確認してみる。

# メールの送信元をGoogleで検索

まず単純に、メールの送信元をgoogleで検索してみる。
この時""でくくるのを忘れないように。ここから、企業など世間体のあるグループ宛てのメールであれば、ある程度ここからヒットしてくると思われるが、たいていはでてこない。

# メールのヘッダーを確認

メールを選択した状態で、ファイル/プロパティを開いて、インターネットヘッダーから、
メールのヘッダーを確認することが可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/323e0559-069b-c343-891a-311d1f401610.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/9859cc33-7ff1-474b-9e25-ce181841b638.png)

その中から、`received from~~`と記載のある中のIPアドレスを確認してみる。
```
Authentication-Results: spf=pass (sender IP is 210.236.36.2)
 smtp.mailfrom=po.cnet-sb.ne.jp; dkim=none (message not signed)
 header.d=none;dmarc=bestguesspass action=none
 header.from=po.cnet-sb.ne.jp;compauth=pass reason=109
Received-SPF: Pass (protection.outlook.com: domain of po.cnet-sb.ne.jp
 designates 210.236.36.2 as permitted sender) receiver=protection.outlook.com;
 client-ip=210.236.36.2; helo=ns.cnet-sb.ne.jp; pr=C
Received: from ns.cnet-sb.ne.jp (210.236.36.2) by
 TYCJPN01FT026.mail.protection.outlook.com (10.118.160.109) with Microsoft
 SMTP Server id 15.20.7046.24 via Frontend Transport; Wed, 29 Nov 2023
 23:25:52 +0000
Received: from [127.0.0.1] ([20.194.237.25])
略
```
メールで見るときは、一番下が送信元で、上に向かうにつれて転送されていく。
なので、一番下のIPアドレスを適当なLinuxサーバにて、whoisコマンドを実行して試してみる。
```
Organization:   Microsoft Corporation (MSFT)
RegDate:        2017-10-18
Updated:        2021-12-14
Ref:            https://rdap.arin.net/registry/ip/20.192.0.0



OrgName:        Microsoft Corporation
OrgId:          MSFT
Address:        One Microsoft Way
City:           Redmond
StateProv:      WA
PostalCode:     98052
Country:        US
RegDate:        1998-07-10
Updated:        2023-11-17
```
特に見るべきなのは、
- `OrgName`
- `Country`

である。これを見るとどこから送信されたかが分かる。ここではアメリカから送信されているらしい。


# (タイトル回収)VIRUSTOTALにて確認。
以下のリンク先にアクセス。

https://www.virustotal.com/gui/home/search

その後、フィッシングサイトのURLになっている所のリンクを貼る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/b1a89c00-342c-b738-c0b8-ee81949196a2.png)

危険性のあるリンクを貼った場合は、0/90の部分の分子が赤色になる。
ちなみに今の写真のものに関しては、OutLookが自動で安全なものに変換してくれるため0になっている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/43844efa-527d-5905-332d-e6c9283d4062.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/2ed52452-cb02-c281-56d8-b7df9081b873.png)



参考サイト

https://www.kitasato-u.ac.jp/knc/mail/download/info_mail_header_v2.pdf
OpenStreetMap ベースのガイガーカウンター測定マップを umap で考える(放射線測定マップの作成 Ⅱ)

2022年〜2023年はザポリージャ原子力発電所の状況が注目されましたね。
最近あまり話題になっていませんが、2023年12月2日現在の様子は・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/0e8c975a-e272-6b29-cf1b-37f9c43b5c1f.png)

このマップはウクライナの OpenStreetMap ベースの環境マップです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c76b69e8-7673-d6b4-5424-4814956670cf.png)

こういったのをやりたい! ということで、マッピングの方法で使えそうなものを調べ、試してみました。

# 要件

- 無料で使える
- アカウント失効などで無効にならない
  - 災害時イザ! というときに使うのが前提でそういったときにいつのまにかアカウント失効で機能停止していたということがないようにしておきたいです。
- スケールできる
- IoT でデータを自動登録
  - 目下行っているガイガーカウンターをHackでインターネットに接続可能になっています。これを接続を前提とします。とはいえ、直接マップサービスに接続するのではなくゲートウェイ、ストレージサーバ、グラフ化などは別ホストで賄う予定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/190edcc5-14ca-2a12-556b-8e5acc8fbc69.png)


# 既存のサービス

IoTでマッピングできるものは ambient など既に多々あります。しかしながら10 年 20 年放置で使えるものを考えてみると、有料サービスの無料枠は経験上規約の突然の変更などで継続性があまり無いなという気がしています。



# タイルサーバ

今回は OpenStreetMap ベースでやっていきます。

タイルサーバを自前で構築しようと考えていましたが、調べていくと uMap というのがあることがわかりました。2013年ごろからずっと継続的に使われているようです。


https://umap.openstreetmap.fr/ja/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5449f356-f20f-736d-4db3-2a50a8ffb2f1.png)

定番のサービスのようです。有料サービスの無料枠と同様、サービス停止の危険がありますが、以下の観点を見越して、これを使うことにしました。


- 10年以上同様に使えている
- 完全無料
  - アカウント失効による利用停止の危険が少ない 
- github でレポジトリが公開されている
  - これを使うと同様のサービスを自前で用意できるのかな? 

https://github.com/umap-project/umap

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2e8ff843-d4fd-7dbf-6070-109128fced44.png)

# 使ってみる


アレコレ触って、こんな吹き出しが表示できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/9f8a2136-f84d-e36c-ae97-05d01a0fc69c.png)

この吹き出しのグラフは、Google Spreadsheet で作ったデータのグラフです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/71aeec58-6092-98bc-ffbc-b15fe055b819.png)


これを切り出して、ここ (Qiita) に貼り、この URL を使用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/9cf0624c-f915-25bb-325c-29ff65594f9a.png)

このイメージURL を uMAP の吹き出しの概要に貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/17a9cbab-a711-4338-111f-5b36cc5ac200.png)

今回は、全部手で作業をしましたが、この仕組みを元に自動でアップデートなどができるようにしていきます。
【SwiftUI】スクロール可能な横に長いテキストの初期表示位置を右端にする！

こんにちは。[ymurao2](https://twitter.com/ymurao2)です！

カテゴリを表示するときなど、スクロール可能な横に長い文字列を表示する際、初期表示位置を右端にしたいときがあると思います（例えば、以下のような画面）

![参考](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529173/e9a7926f-28c9-214f-5384-314009083d6f.jpeg)

今回はこのようなViewをScrollViewを使って実装する方法を紹介します！

# 実装
```swift
var body: some View {
    HStack {
        Text("カテゴリ")
        ScrollViewReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                Text("長いテキスト>長いテキスト>長いテキスト>長いテキスト>長いテキスト>")
                    .lineLimit(1)
                    .id("scroll")
            }
            .onAppear {
                proxy.scrollTo("scroll", anchor: .trailing)
            }
        }        
    }
}
```
:::note info
ScrollViewReaderを使用し、onAppearでscrollToメソッドを呼ぶのがポイントです！
:::

:::note warn
色など余分な情報はコード上から削除しています
:::

こんな感じで初期表示位置を右端にできました！
![IMG_0226.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529173/a28ac15c-feed-8799-e215-40b78ce79b1b.jpeg)
DjangoのCreateViewの実装の仕方を理解する

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

前回DjangoのFormViewとmodel、HTMLのform要素について理解を深めていきました。
今回はその学びの中で出てきた『FormViewではなくてCreateViewでも同様に実装できる』ということを確かめるためにコーディングをしてみました。

https://qiita.com/ohtsuka-shota/items/3f87d8fbc6a375bd1e5d

# github
以下にコード一式を格納しております。

https://github.com/ohtsuka-shota/publicDjangoStudy/tree/main/createTestPJ

# 環境構築
## 環境イメージ
今回は以下の環境で構築しております。createTestPJという名前のプロジェクトとMyCreateという名前のアプリを作成しています。
構成要素は以前のFormViewを継承させた環境と殆ど同じです。違いとしては、forms.pyを用意していないことです。
![django-ページ10.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8fe6955e-d262-cfe3-28db-ce72c3ac17ef.png)


## 個人的に重要そうだと思う部分のメモ
### MyCreate/views.py
```MyCreate/views.py
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import MyCreateTable
 
class MyCreateView(CreateView):
    template_name = "MyCreate.html"
    model = MyCreateTable
    fields = ('username', 'password', 'email', 'memo')
    success_url = reverse_lazy('MyCreate:MyCreatePage')
```

- FormViewを継承する時はviewsでmodelを定義することはなかったですが、CreateViewを継承する時はここで定義するようです。また、fieldsもここで定義するようです。

# 実行結果
入力フォームは以下となっております。
上からユーザ名、パスワード、メールアドレス、メモですね。
Try MyCreateボタンを押下してみます。
![image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/54bfd713-9a7a-04b9-4dfb-b04350136dd8.png)
success_url = reverse_lazy('MyCreate:MyCreatePage')との記載から元の場所に戻されます。
![image02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/56c281ab-b79b-4107-01f6-b12293064d0a.png)
admin管理画面を確認してみます。正常に作れているようですね。formsを別途用意しなくていいことから、CreateViewを継承したほうが簡単に実装できそうだなと思いました。
![image03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/dcb3e1aa-b505-473a-d490-37059e49ae14.png)
![image04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/00e66dea-0e46-239e-160b-402a92f7d514.png)
GCPで動かしているコンテナでPermissionError: [Errno 13] Permission denied: '/root/google_vm_config.lock' が出たときの対処法

# PermissionError: [Errno 13] Permission denied: '/root/google_vm_config.lock' が出たときの対処法

GCPのコンテナで機械学習の処理を動かしていると遭遇したエラーについてメモです。

## 結論

`lib/python3.10/site-packages/bitsandbytes/cuda_setup/env_vars.py`
のパスにある`ignorable`の中に`GOOGLE_VM_CONFIG_LOCK_FILE`を加えることで解決できます。

以下のように記述します。

```py
def to_be_ignored(env_var: str, value: str) -> bool:
    ignorable = {
        "PWD",  # PWD: this is how the shell keeps track of the current working dir
        "OLDPWD",
        "SSH_AUTH_SOCK",  # SSH stuff, therefore unrelated
        "SSH_TTY",
        "HOME",  # Linux shell default
        "TMUX",  # Terminal Multiplexer
        "XDG_DATA_DIRS",  # XDG: Desktop environment stuff
        "XDG_GREETER_DATA_DIR",  # XDG: Desktop environment stuff
        "XDG_RUNTIME_DIR",
        "MAIL",  # something related to emails
        "SHELL",  # binary for currently invoked shell
        "DBUS_SESSION_BUS_ADDRESS",  # hardware related
        "PATH",  # this is for finding binaries, not libraries
        "LESSOPEN",  # related to the `less` command
        "LESSCLOSE",
        "GOOGLE_VM_CONFIG_LOCK_FILE", # ここだよ!!
        "_",  # current Python interpreter
    }
    return env_var in ignorable
```


env_vars.pyの場所は環境によって異なると思うので、findコマンドを使用するなどして、自分がライブラリをインストールした先のenv_vars.pyを編集するようにしてください。

## 参照

https://github.com/TimDettmers/bitsandbytes/issues/620#issuecomment-1666014197
書籍「はじめてのNode-RED MCU Edition」のアップデート情報（アドベントカレンダー2023）

# はじめに

2023年4月27日に「はじめてのNode-RED MCU Edition」の書籍が発売されました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/62486664-cb9a-af88-3a25-8ca3466e1fc3.jpeg" width="30%">

https://www.kohgakusha.co.jp/books/detail/978-4-7775-2249-1

実はその前に、技書博7で「Node-RED MCU Edition入門」というタイトルで技術同人誌を頒布しました。

https://gishohaku.dev/

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/88006456-59be-fb90-ec09-bc4e2b84fd78.png" width="30%">

https://norahack-led.booth.pm/items/4317877

商業本は技術同人誌の内容がベースになっていますが、技術同人誌はmacOSを使用した内容に偏っていました。Qiitaの記事を見て、他のOS(Windows、Linux)でNode-RED MCU Editionを試してくれた方が現れ、その方( @mshioji @NWLab )に声をかけて一緒に商業誌の執筆を始めました。

# 技術書典で更新情報をまとめて発信

商業本の原稿〆切は2023年2月/末でした。それ以降のアップデートは書籍に反映されないので、変更内容を定期的に情報発信していく必要があります。
選択肢として商業本のサポートページへ掲載する方法がありましたが、情報量が多く、出版社の方の手を煩わせてしまうので、結果的に技術同人誌イベントで頒布する方法を取りました。

## 技術書典14

2023年5月15日時点の情報にもとづいてアップデートをまとめました。

https://norahack-led.booth.pm/items/4789615

## 技術書典15

2023年10月31日時点の情報にもとづいてアップデートをまとめました。

https://norahack-led.booth.pm/items/5244795

ハッカソンでNode-RED MCUを使った作品を見つけ、声をかけて技術同人誌の執筆者に加わっていただきました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3c060bca-3e9f-2db4-f1ee-98eeeb75f19d.png" width="50%">

# Node-RED Con 2023

2023年11月10日に行われたNode-RED Con 2023で、これまでの経緯をまとめて「商業誌を出すまでの話と出した後の話」というタイトルで発表しました。

(動画アーカイブ)

https://www.youtube.com/watch?v=fhx2nGKeZUg&t=1553s

(登壇スライド)

https://www.slideshare.net/kitazaki/20221110noderedcon2023kitazakiv1pdf

# Moddable SDK 4.2でエラーが出るようになった

2023年10月12日にリリースされたModdable SDK 4.2で、ESP32マイコンデバイスの開発環境がESP-IDF 4.4.3からESP-IDF 5.1.1に変更されました。その影響で商業誌に掲載した手順ではエラーが出力されるようになってしまいました。
影響が大きかったので、エラーの対応方法についてはサポートページに掲載しました。
困っている方はぜひご覧ください！

http://www.kohgakusha.co.jp/support/node-red-mcu/index.html
プリザンターを便利に使う小ネタ

本記事は、[OSSのノーコード・ローコード開発ツール「プリザンター」 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/pleasanter) の2日目の記事です。

## はじめに
皆さま「プリなま」は、ご存知でしょうか？
今年の3月から始まった、お悩み解決生配信、と題してYouTubeにて毎月行っている配信です。皆さまから頂いたプリザンターにまつわるお悩み事を毎月解決しており、先日の配信でついに解決したお悩みが100件を越えました！
今月は12月27日(水)に配信予定ですが、ついに10回目の配信となります。皆さまのお悩みを解決するために作成したスクリプトやスタイルなどのサンプルコード、サイトパッケージもダウンロードできますので是非試してみてください。プリザンターを便利に使える小ネタも沢山あります！

[ノーコード・ローコード開発「プリザンター」ch \- YouTube](https://www.youtube.com/@Pleasanter)

この記事では、そんな「プリなま」で取り上げたお悩みの中から、便利そうな小ネタをご紹介します！

## フィルタを便利にするボタン
プリザンターのフィルタ機能はビューと合わせて使うと、とても便利に使えます。でも、ビューって結構見落とされがちな気がしますがとても便利なので是非使ってみてください。
[テーブルの管理：ビュー \| Pleasanter](https://pleasanter.org/manual/table-management-view)

まあ、ビューは関係無いんですけど。
私の場合、「昨日」登録された情報を確認するというケースが結構あるのですが、そんな時にちょっと便利な小ネタです。
「受注予定日」欄の横に「明日」というボタンが追加されています。この場合は、今日+1日、という条件でフィルタしているわけですが、今日-1日にすれば当然「昨日」にも出来るわけです。スクリプトで1文字変えるだけです。
![FireShot Capture 029 - プリザンター - demo.pleasanter.org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/834556/a6758e87-6295-c912-b1dd-97410c6d74b8.png)

プリザンターお悩み解決生配信 #2 - YouTube
https://www.youtube.com/watch?v=ewXjTKrRNj0&t=275s
①日付で「今日」「明日」などのフィルタを作成できませんか？

こちらは上記の配信で解説しており、サイトパッケージもダウンロードできますので是非試してみて下さい。
テーブルの管理→スクリプト、で実際のスクリプトを確認できます。
```dt.setDate(dt.getDate() + 1);```
ここを-1にすれば「昨日」にできます。

## サインを手書きしてみる
手書きのサインを登録したいというのは、結構需要があったりしますが、実は結構簡単に対応できたりします。
プリザンターはレスポンシブ対応していますのでスマホやタブレットでも便利にお使いいただけますので、いろいろな場面でご活用いただけます。こちらもサイトパッケージをダウンロードできますので、インポートすればすぐにお使いいただけます。
![FireShot Capture 030 - プリザンター - demo.pleasanter.org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/834556/8b2d0bfd-a93e-f986-2ff2-4dd9c44f91be.png)

プリザンターお悩み解決生配信 プリなま #6 - YouTube
https://www.youtube.com/watch?v=Jx25ZifR-zw
②手書きサインを登録できますか？

## 地図を表示してみる
便利。
プリザンターに登録された住所(正確には緯度・経度)をもとにマップにピンを打って表示できます。プリザンターでオフィス近くのグルメマップとか作れちゃうわけです。
実はこれ、一覧画面でマウスが乗っている行(レコード)の場所が地図上で強調されるようになっているのでお店の名前なんかも出せるんですよ。画像だと住所が表示されている吹き出しの部分はプリザンターに登録されている情報を表示しているだけなので簡単に変更できます。
![FireShot Capture 028 - プリザンター - demo.pleasanter.org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/834556/34d050b3-9da1-6366-3dbd-f6504ed5aa4b.png)

プリザンターお悩み解決生配信 プリなま #8 - YouTube
https://www.youtube.com/watch?v=CEj2I_Udi5k
⑦GoogleMapを表示して特定の場所にピンを打つ方法はありますか？

頂いたお悩みとしてはGoogleMapだったのですが、今回はOpenStreetMapを使わせてもらっています。とても便利なのでこちらも是非使ってみて下さいね。
[OpenStreetMap](https://www.openstreetmap.org/#map=19/35.71091/139.66506)

## おわりに
プリなまで取り上げたお悩みを3つほど紹介してみましたが、いかがでしたでしょうか？
他にも便利に使えそうな小ネタが沢山ありますので、もしまだご覧になられていない方は是非ご視聴ください！
今月は27日(水)18:30からです！

[ノーコード・ローコード開発「プリザンター」ch \- YouTube](https://www.youtube.com/@Pleasanter)
サンプルコードを1行修正するだけでslコマンドができちゃった話

この記事は[Spresense Advent Calendar 2023](https://qiita.com/advent-calendar/2023/spresense)の1日目（12/1分）です。

# この記事は何?
slコマンドをSpreseneで簡単にできたことを共有する記事です。

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">どうも。<br>自称・spresense芸人です。<br><br>spresense SDKで動いているspresenseでslコマンドが動きました。<br><br>チュートリアルでPDCursesのサンプルプログラムがあったのでslコマンドの移植できるかなぁ、と思ったら割と簡単にできました。<br><br>だからなんだ？という感じですが、楽しいので良しとしましょう。 <a href="https://t.co/yhQTldi76y">pic.twitter.com/yhQTldi76y</a></p>&mdash; k-abe@組み込まれた猫使い🧙‍♂️ (@juraruming) <a href="https://twitter.com/juraruming/status/1643951051526270976?ref_src=twsrc%5Etfw">April 6, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# コード
コードはGitHubリポジトリに置きました。

https://github.com/grace2riku/spresense_sl


# slコマンドを確認するモチベーション
マイコンボードでLチカが確認できたら何をしていますか?
私の場合、つぎのステップとしてslコマンドを試してみることが多いのでSpresenseでも試してみました。


# 確認環境
## ハードウェア
つぎのハードウェアで確認しました。

* Spresenseメインボード
* Spresense拡張ボード
* LCD ILI9341

## ソフトウェア
Spresense SDKで確認しました。

* [spresense SDK v3.0.0 (2023/03/13)](https://developer.sony.com/develop/spresense/docs/release_sdk_ja.html)


# 確認手順
つぎの手順で確認します。

## 環境構築
### Spresense SDK 開発ツールのセットアップ
事前にSpresense SDKでの開発 -> Spresense SDK スタートガイド (CLI 版) -> [2. 開発ツールのセットアップ](https://developer.sony.com/spresense/development-guides/sdk_set_up_ja.html#_%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を実施し、開発環境を構築しておきます。

### ユーザアプリの追加
Spresense SDKでの開発 -> Spresense SDK スタートガイド (CLI 版) -> 6. ユーザーアプリの追加方法 -> [6.3. ツールを使用する](https://developer.sony.com/spresense/development-guides/sdk_set_up_ja.html#_%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B)を参照し、ユーザアプリを追加します。

今回はつぎのコマンドでユーザアプリを追加しました。

```
tools/mkappsdir.py sl “sl command”
tools/mkcmd.py -d sl sl “sl command”
```


## コンフィグレーション
spresense/sdkディレクトリで次のコマンドを実行します。

```
tools/config.py examples/pdcurses
```

Macの場合、次のディレクトリでした。
```
/Users/ユーザ名/spresense/sdk
```

## ソースコード準備
slコマンドのソースコードはオリジナルのslコマンドを流用させてもらいます。

オリジナルのslコマンド GitHubリポジトリ

https://github.com/mtoyoda/sl

sl.c, sl.hをslディレクトリにコピーします。

### Makefileの変更
sl/MakefileのMAINSRCをsl.cに変更します。

```
include $(APPDIR)/Make.defs
include $(SDKDIR)/Make.defs

PROGNAME = $(CONFIG_SL_SL_PROGNAME)
PRIORITY = $(CONFIG_SL_SL_PRIORITY)
STACKSIZE = $(CONFIG_SL_SL_STACKSIZE)
MODULE = $(CONFIG_SL_SL)

ASRCS =
CSRCS =
MAINSRC = sl.c

include $(APPDIR)/Application.mk
```

## コード変更
sl.cのヘッダーファイルインクルードをつぎのように変更します。

```diff_c
-#include <curses.h>
+#include "graphics/curses.h"
#include <signal.h>
#include <unistd.h>
#include "sl.h"
```

コード修正が終了したらmake、コードをflashします。
NuttXのプロンプト（nsh）からslとタイプすると冒頭の動画のようにslコマンドが実行できます。


# なぜ簡単にslコマンドができたのか考察
オリジナルのslコマンドから1行の変更でSpresenseでslコマンドが実行できました。
なぜこんなに簡単にslコマンドができたのか考察します。

## Spresenseでcursesが使えるため
オリジナルのslコマンドはcursesを使っています。
cursesのWindows向け実装PDCursesがNuttX（※）にポーティングされており、今回はPDCursesを使いました（コンフィグレーションでexamples/pdcursesを指定したところ）。

※Spresense SDKはNuttXのうえで動作しています。

今回はslコマンドでしたがcursesを使っているOSSであればSpresenseで割と簡単に移植ができるかもしれません。
AIｽﾀｯｸﾁｬﾝをSDを使わずにWi-Fi設定する方法

1.AIｽﾀｯｸﾁｬﾝ、実はSDが無くてもWi-Fi設定出来るんです。AIｽﾀｯｸﾁｬﾝの電源を入れてしばらくすると####…と表示されるので、その時スマホアプリのESPTouchでWi-Fiの設定ができます。アプリはiOS、Android版の両方有ります。![BD118EFD-1D31-4D3D-83E6-A28B98326D55.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633340/b2052441-fc84-48cb-e681-71493b3ce0d6.jpeg)

2.スマホは事前に2.4Ghzのアクセスポイントに接続しておく必要があります。
ESPTouchアプリを立ち上げると
メニュに”ESPTouch“と”ESPTouch v2”が出てきますが、”ESPTouch“の方を使います。

3.ESPTouchの使い方はWi-FiのPasswordを入れて1番下の“Confirm”を押すだけです。あまりの簡単さに感動ものです。![D3EA65C3-E95C-4297-8E1F-01FC189AC5C2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633340/41b40497-b7e1-5040-4901-ea8582f7aa28.jpeg)

4．Wi-Fiに接続できたらAIｽﾀｯｸﾁｬﾝのIPアドレスにこのようにアクセスするとAPIキー設定画面が出ます。
http://xxxx.xxxx.xxxx.xxxx/apikey 

xxxx.xxxx.xxxx.xxxxはAIｽﾀｯｸﾁｬﾝ起動時に画面に表示されるIPアドレスです。![8DE8796C-DDB4-4EFA-95A5-15D885C2CA57.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3633340/b4aaa3cb-b6cb-9665-e11d-8f1426aa1564.jpeg)
[Swift] カリー化・部分適用とは？

# はじめに
カリー化や部分適用は、もともとは関数型言語から輸入された概念ですが、**Swiftを含む様々な言語で使うことができるテクニック**です。
少し難しいので、まずは具体的な例を使って説明しましょう。

# 具体例
既存の関数として、次のような関数があるとします。
```swift
/// `text`を`count`回反復した文字列を返す関数。
func repeatText(_ text: String, count: Int) -> String {
    String(repeating: text, count: count)
}
```
使ってみるとこんな感じ。
```swift
repeatText("Hey", count: 3) // -> "HeyHeyHey"
repeatText("Hey", count: 5) // -> "HeyHeyHeyHeyHey"
repeatText("Hey", count: 2) // -> "HeyHey"
```
しかし使ってるうちに、「最初の引数の値を固定して使い回せないかな」と思うようになりました。
```swift
let repeatHeyFor = { count in repeatText("Hey", count: count) }
repeatHeyFor(3) // -> "HeyHeyHey"
repeatHeyFor(5) // -> "HeyHeyHeyHeyHey"
repeatHeyFor(2) // -> "HeyHey"
```
これで、引数`text`の値を固定することで、2つあった引数を1つに減らすことができましたね。
これを**部分適用**と言います。

さらには、`text`に色んな値が固定できるように、こんなのを定義してみました。
```swift
let repeatTextWithText = { text in
    { count in repeatText(text, count: count) }
}
let repeatHeyFor = repeatTextWithText("Hey")
let repeatYeahFor = repeatTextWithText("Yeah")

repeatHeyFor(3)  // -> "HeyHeyHey"
repeatYeahFor(2) // -> "YeahYeah"
```
少し複雑そうに見えますが、クロージャを2重にしているだけです。

それでは、元の関数`repeatText`と、`repeatTextWithText`を比較してみましょう。
```swift
before: repeatText("Hey", count: 3)
after:  repeatTextWithText("Hey")(3)
```
いっぺんに渡す必要があった2つの引数を、1つと1つに分割して渡せるようになっていますね。
この変換のことを**カリー化**と言います。

ちなみに元の関数には`count:`のように引数ラベルが付いていますが、カリー化するとクロージャなので消えます。代わりに変数名で引数の情報を補うと良いでしょう。(この例の`-WithText`や`-For`のように)

# カリー化と部分適用の違い
より一般化して書くとこんな感じです。
```swift
// 元の関数    引数                戻り値
let f:       (A, B)           -> C
// 部分適用の操作
let partial: ((A, B) -> C, A) -> (B) -> C
// カリー化の操作
let curry:   ((A, B) -> C)    -> (A) -> (B) -> C
```
部分適用は、一部の引数の値を固定して、引数の数を減らした関数を作ること。
カリー化は、複数の引数を持つ関数を、分割して渡せるような関数にすること。
`f` をカリー化して `A` を渡す操作は、部分適用になります。

# どういう時に便利か
関数を利用する際に、他の引数の値は変わるけど、特定の引数の値は一度決まったら基本的にコンスタントだなぁという時には、部分適用やカリー化を検討してみると良いかもしれません。


# 参考
https://en.wikipedia.org/wiki/Partial_application

https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96
GitHubでリポジトリを始める方法

# 

## ローカルリポジトリにファイルがない場合
### 1.自分のGitHubアカウントを開き、リポジトリの作成を開始する
### 2.「README.md」にチェックを入れ、作成する
### 3.自分のローカルリポジトリを開き、以下のコマンドを実行する
  `git clone https://github.com/(自分のGitHubのアカウント名)/(リポジトリ名).git`
  `git config --global --add safe.directory '(ローカルリポジトリのアドレス)`

## ローカルリポジトリにファイルがある場合
### 1.自分のGitHubアカウントを開き、リポジトリの作成を開始する
### 2.「README.md」にチェックを入れないで作成する
### 3.自分のローカルリポジトリを開き、以下のコマンドを実行する
  - リポジトリの初期化を行う
    `git init`
  - README.mdファイルを作成する
    `echo "# (リポジトリ名)" >> README.md`
  - READMEをaddする
    `git add README.md`
  - READMEをcommitする
    `git commit -m "upload README.md"`
  - mainブランチに切り替える
    `git branch -M main`
  - リモート接続する
    `git remote add origin https://github.com/(アカウント名)/(リポジトリ名)`
  - pushする
    `git push -u origin main`

## 最初のpushが完了した後、コミットする場合
  - addする
    `git add (ファイル名)`
  - commitする
    `git commit -m "(コミットメッセージ)"`
  - pushする
    `git push`
wslでnerves その33

# 概要
wsl(wsl2じゃない)でnervesやってみる。
Nervesを説明してみた。


# Nervesについて
Nervesは、組み込みLinuxです。
Nerves Project によって開発されている、Elixir で組込みソフトウェアを開発するためのフレームワークです。
Linuxカーネルと、busyboxなuserlandで、boot後elixir(erlang VM)を立ち上げます。
Erlang および Elixir の特徴である高いスケーラビリティおよび耐障害性を備えた、IoT システムを構築できます。
Livebook、Phoenix と連携して、サーバと IoT デバイスとの通信制御を容易に行うこともできます。
ブートローダおよび、Erlang VM を含むルート・ファイルシステムが二重化されており、
システムレベルで障害が発生しても、ファイルシステムの切替えのみでシステム全体の復旧を速やかに行えます。
想定しているボードは、ラズパイなどです。



以上。
Ruby芸160チャレンジ(#8)ログの集計

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
https://github.com/shellgei/shellgei160/blob/master/answer/8.md

```bash
$ awk -F: '{print $(NF-2)}' access.log | awk '$1<"12"{print "午前"} $1>="12"{print "午後"}' | sort | uniq -c
```

ログの中で時間のフィールドだけを抜き出し、その時間が午前か午後かを判別し、それぞれの個数をカウント・表示する。

## 解
```ruby
logs = File.open('qdata/8/access.log', 'r').readlines

# am? receives a record including 02/Jun/2016:15:04:05 +0900 time format
def am?(record)
  re = %r{\[\d{2}/[a-zA-Z]{3}/\d{4}:(\d{2}):}
  h = record.match(re)[1].to_i
  h < 12
end

n_am = logs.count { |log| am?(log) }
n_pm = logs.size - n_am
puts "午前: #{n_am}\n午後: #{n_pm}"
```

## 所感
- 正規表現にマッチした部分文字列を`match(パターン)[1]`で抜き出せるのね。
- 午前か午後かを別のarrayに納めて、array.count(午前 or 午後)にしてカウントしても良かったかも。
SES企業から自社開発に転職するまで

## 転職の理由
転職の理由は、SESという業態が合わなかったからです。
プロダクトに対して思い入れがなければ、面白みもないので、やりがいというのがわからない状態で働いていました。

### SESで働く上でのメリット
- **様々な技術に触れられる。**

→ PHP,Python,Vue.js,Nuxt.js...など現場によって色々なプログラミング言語や技術を扱えて開発ができたので、
これは今後のエンジニア人生によって非常に良い経験になったと思います。

- **現場をたくさん経験できるので、幅広いタイプの開発手法と出会える。**

→ ウォータフォール型の開発を進める企業とアジャイル型の開発を進める企業を経験しましたが、扱うツール・工数・コミュニケーションを取る頻度・上長のプログラミング経験有無など、
全く違いました。

- **現場にもよるが、比較的定時に上がれることが多かった。（※これは本当に案件によるので、私個人の見解です）**

→ こちらは納期が決まっている上にすでに炎上案件に参画された時以外は、ほぼ定時上がりでした。タスクに対して期限は設けられていて、逐一確認されるので、比較的大幅に期限を跨ぐケースは少なく、余裕を持って開発すれば、大体定時には上がれてました。

### SESで働く上でのデメリット

- **やりがいがない、責任感が持てない**

→これは転職する理由としては一番大きかったです。自分は1年半しか所属していませんでしたが、このままSESに3年、5年といたとしてもやりがいや責任感というのは持てないと感じました。理由としては、サービスや開発を誰のためにやっているのかわからないまま作業しているため、長い目で見た時に自分には合わないなと思いました。

- **帰属意識が薄れていく**

→これはSESのデメリットに必ずと言っていいほどあがります。自社でエンジニアとして雇用されていても、案件先で働いていると自分の本来の所属かわからなくなります。何度か自社での雇用は不要で、案件先で雇ってもらった方が良いのでは？という考えにもなります。それくらい自社との関わり度合いは少なくなって行きます。

- **良くも悪くも案件ガチャ**

→SESは基本的に案件先で働くので、案件によっては開発の規模、体制、プログラミング言語などが異なります。同じ案件先に長く働くケースもありますが、短い場合は1ヶ月〜3ヶ月などもあります。

## 転職する前の準備
①**今までの経歴・職歴（開発内容・期間・個人学習の内容など）の洗い出し**
まずは今までどういう職歴や経歴があるかを、職務経歴書と履歴書に書き出しましょう

②**findy,wantedly,LAPLAS,転職ドラフトに登録**
基本的にはスキル転職がおすすめです。経歴だけでなく技術力やアウトプット力も見てくれるので、総合的に判断してもらえると思います。ちなみに自分はfindyで自社開発の会社に行きました。

③**カジュアル面談からスタート**
いきなり面接はハードルが高いので、カジュアル面談からスタートしましょう。カジュアル面談だけでは判断しにくいでしょうが、たくさん受けていく中で自分の中で基準ができると思うので、カジュアル面談はたくさん受けておいて良いかと思います。


## 転職中
### 転職面接
基本的には一次面接は技術的な質問が多めで、二次面接以降はどれくらい会社理解があるかと将来的な話をして、志望度やマッチ度合いを確認されていると思います。面接をたくさん入れてしまうと対面面接などもあり、時間に余裕がなくなるので、余裕を持ったスケジュールで挑みましょう。

## 転職後
内定が決まったら、新しい技術を習得する必要がある場合は、勉強しましょう。あとは自社開発であれば、同じ業界の競合他社を把握したり、他社サービスを利用してみて、どうやったら自社のサービスが良くなるか考えてみると、入社後にスムーズに業界の理解が得られると思います。

## まとめ
記事を見ていただきありがとうございました。
自分もまだまだ開発に関しては学ぶことが多いですが、新しい環境で働くことでキャリアは大きく変わりますし、自分自身のやりがいにつながります。今ある環境にこだわるだけでなく、やりがいや見合った環境かどうか確認してみることも大事だと思いました。
【iOS】Sign in with apple 初回以降のサインインでユーザー情報を取得できない

# 状況
SwiftUIにて、Signin with Appleのトライしていたところ、初回サインインではユーザー名やemailを取得できたのですが、それ以降のサインイン後はnilが返ってくるという現象が起きました。調べた結果を備忘録として書いておきます。

# 試したコード
こんなコードで試しました。
```swift: AuthScreen.swift
struct AuthScreen: View {
    @State var givenName: String?
    @State var familyName: String?
    @State var email: String?
    
    var body: some View {
        VStack {
            Text("givenName: \(givenName ?? "is nil")")
            Text("familyName: \(familyName ?? "is nil")")
            Text("email: \(email ?? "is nil")")

            SignInWithAppleButton(.signIn) { request in
                    request.requestedScopes = [.fullName, .email]
                } onCompletion: { authResults in
                    switch authResults {
                    case .success(let authResults):
                        guard let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential
                            else { return }
                        if let fullName = appleIDCredential.fullName { 
                            self.givenName = fullName.givenName
                            self.familyName = fullName.familyName
                        }
                        self.email = appleIDCredential.email
                    case .failure(let error):
                        print(error.localizedDescription)
                    }
                }
            .signInWithAppleButtonStyle(.black)
            .padding(.horizontal, 16)
        }
    }
}
```

初回サインイン後はこのように`givenName` `familyName` `email`が取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633746/76e0329e-68da-052a-a291-95ddb104d7a5.png)

その後サインアウト状態から再度サインインすると`givenName` `familyName` `email`がnilで返ってきてしまいます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633746/9f0353f7-cd84-30d0-8bc8-7c9ac60ab190.jpeg" width="250">

# 原因
同じ現象についてのフォーラムを見つけました。

https://developer.apple.com/forums/thread/121496

>ユーザ情報は最初のユーザ登録時にのみ ASAuthorizationAppleIDCredential に送信されます。その後、同じアカウントでSign In with Appleを使用してアプリにログインしても、ユーザ情報は共有されず、ASAuthorizationAppleIDCredentialにユーザ識別子が返されるだけです。アカウントがサーバに正常に作成されたことを確認できるまで、ユーザ情報を含む最初のASAuthorizationAppleIDCredentialを安全にキャッシュすることをお勧めします。

要は、`ASAuthorizationAppleIDCredential`から`givenName` `familyName` `email`が返されるのは<font color="Crimson">**最初のサインアップの時のみ**</font>です。

必要な情報は、初回にきちんとセキュアに（サーバーサイドに）キャッシュしておこうね、ということですね。

# じゃあサインアップ履歴を削除したい

ユーザー情報のキャッシュが未実装だけどとりあえずユーザー情報を確認したい、という場合は以下の手順でサインアップ履歴を削除してリセットできます。

（1）ここにログインします
https://appleid.apple.com/account/manage

（2）「サインインとセキュリティ」を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633746/5b6af1cd-5263-75e7-dcb2-8123156feb39.png)


（3）「Appleでサインイン」を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633746/dfa5e37f-587b-4b0b-02e3-b78d4faa46ae.png)

（4）該当のアプリを選択し、「Appleでサインインの使用を停止」を押します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633746/010733a1-cd99-c041-b41b-ea2cd9674309.png)

これで次のサインインが初回扱いになり、ユーザー情報を取得できます。

# おわりに
Signin with Appleは必須の技術なので、目瞑ってても実装できるようになりたい
HackyPiで遊んでみるの巻_1

ずいぶん前に届いてはいたが、ようやく触る気が起きた。
どうも日本語記事が少ない様なのでチョロチョロっと遊んでみる。

:::note warn
この記事で紹介する方法は、教育目的や研究目的でのみ使用してください。不正な目的で使用する場合、著作権法や不正アクセス禁止法などの法律に違反する可能性があります
:::
# Hackypiとはなんぞや
<img width="400" alt="IMG_6068.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/8cf501dd-d0f0-25f3-7ecd-2cd59efa1a3f.jpeg">

- [KickStarterプロジェクト](https://www.kickstarter.com/projects/diytech/hackypi-your-diy-tool-for-learning/description)
- セキュリティやコーディング教育用のUSBデバイス
- RaspberryPiベースで作られており、PCに接続すると自動でプログラムを走らせてくれる
- 小さいLCDが付いていてかわいい
# セットアップ
基本的には[公式のREADME](https://github.com/sbcshop/HackyPi-Software)を読むのが早い
流れとしては...
1. HackyPiにCircuitPythonのファームウェアをインストール
1. 編集用のIDEを準備
1. 動作確認

#### 1. HackyPiにCircuitPythonのファームウェアをインストール
https://circuitpython.org/board/raspberry_pi_pico/
- まずは上記をダウンロード
- 側面についているブートボタンを押しながらPCに接続
- 認識されたデバイスにダウンロードしたファームウェアをドロップする
<img width="600" alt="スクリーンショット 2023-12-02 13.07.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/f4387bf8-a50b-9b37-4519-618e538a35a6.png">

- デバイスの中身が上記になれば完了
#### 2. 編集用のIDEを準備
https://thonny.org/

- OSに合ったThonny IDEをインストール
- IDEを起動し、`preferences` → `インタプリタ`から以下を設定
    - **インタプリタ**: CircuitPython(ジェネリック)
    - **ポート**: HackyPiを接続しているポート
<img width="600" alt="スクリーンショット 2023-12-02 13.15.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/560c2848-458c-91d8-ca14-2b510457417b.png">

#### 3. 動作確認
まずは本当に動くかを見てみる
```py:python
import time
import os
import usb_hid
import board
import terminalio
from adafruit_hid.keyboard import Keyboard, Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS

try:    
    keyboard = Keyboard(usb_hid.devices)
    keyboard_layout = KeyboardLayoutUS(keyboard) 
    time.sleep(1)
    keyboard.send(Keycode.COMMAND, Keycode.SPACE)
    time.sleep(0.3)
    keyboard_layout.write('terminal')
    # pcによってはエンター押下に'terminal'入力が間に合わない事があるのでtime.sleepを挟む
    time.sleep(1)
    keyboard.send(Keycode.ENTER)
    time.sleep(1.2)
    keyboard_layout.write('echo "hello world"')
    time.sleep(1)
    keyboard.send(Keycode.ENTER)
    keyboard.release_all()
except Exception as ex:
    keyboard.release_all()
    raise ex

time.sleep(1)
```
上記を実行し、以下の様に`hello world`されればOK
<img width="800" alt="hackypi_hello.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/6451bc66-0d71-b5c0-8c14-ed240e0590e0.gif">
次はUSBを接続した際に、自動でプログラムが走るところを見てみる。
まずは上記プログラムをHackyPIへ`code.py`というファイル名で保存
<img width="600" alt="hackypi_hello.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/0be64e20-59b7-0fe4-0beb-776fa3396e9e.png">
<img width="600" alt="hackypi_hello.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/528ffed5-ea6a-8598-2e03-1af068c600c1.png">
一旦HackyPIを取り出し、再接続
<img width="400" alt="hackypi_hello.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649647/52f834af-1d7e-5a36-4d97-d35001d3fbba.gif">
上記の様に自動でターミナルが起動、`hello world`されてて嬉しい(画像アップロード制限でガビガビ画質)
# 終わりに
とりあえずセットアップと接続した際のプログラム自動起動まで動いた。
次回はもうちょっとハッキングぽい事を試してみるという気持ち。
Ruby芸チャレンジ(#7)少し複雑な条件分岐

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
https://github.com/shellgei/shellgei160/blob/master/answer/7.md

```bash
$ cat kakeibo.txt | awk '{tax=($1<"20191001"||$2~"^*") ? 1.08 : 1.1; print $0,tax}' | awk '{print int($3*$4)}' | numsum
```

日付やその他条件から消費税を決定し、消費税をかけた後の家計簿上の合計金額を出す処理。

## 解
ワンライナー感は狙わず、分かりやすく書いてみる。せっかくなのでarray.reduceとかも使ってみよう。

```ruby
def food?(item_name)
  item_name.start_with?('*')
end

def tax_rate(date, item_name)
  return 0.08 if date < '20191001'

  food?(item_name) ? 0.08 : 0.1
end

def taxed_price(date, item_name, price)
  price = price&.to_i
  tax = (price * tax_rate(date, item_name)).floor
  price + tax
end

lines = File.open('qdata/7/kakeibo.txt').readlines

total_price = lines.reduce(0) do |sum, line|
  fields = line.split(' ')
  raise 'invalid record' if fields.size != 3

  sum + taxed_price(*fields)
end

puts total_price
```

## 所感
- reduce(0)の0は初期値
- sum + taxed_price(*record)の`*`は配列を引数へと展開しているよ。（覚え書き）
Ruby芸160チャレンジ(#6)For文

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
https://github.com/shellgei/shellgei160/blob/master/answer/6.md

```bash
$ seq 5 | awk '{for(i=1;i<$1;i++){printf " "};print "x"}' | tac
```

次のような文字列を表示する処理です。

```bash
    x
   x
  x
 x
x
```

for文で徐々にスペースを開けるようにしながら、最後に`tac`で上下を反転させています。

## 解

```ruby
n_lines = 5
puts (1..n_lines).map { |i| "#{' ' * (i - 1)}x" }.reverse
```

## 所見
- ワンライナー感ありますね！こういう処理を書くにはRuby完結で良き。
GPTsで通訳さんを作ったらDeepLよりも高性能な翻訳アプリになった

## はじめに

先日、GPT Plusのユーザに向けてリリースされたGPTsを使ってみました。とってもシンプルですが、便利な用法を見つけて活用しているので紹介したいと思います。

この機能を使って、新たなGPTを作りました。
その名も「通訳さん」
このGPTは、日本語の文章を入力すると英語に翻訳してくれ、英語の文章を入力すると日本語に翻訳してくれます。

## プロンプト例
以下に例を示します。
### 日本語入力の例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/ce6b7204-04a2-ccbe-edf8-334b25039a3c.png)


### 英語入力の例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/af41dca1-ae61-cba8-b76c-65cfbd4c5e5d.png)

## 追加の質問もできる

これまでのChatGPTでもできましたが、ポイントは、英語にして、とか、日本語にしてとかを書かなくて良くなったことです。

また、翻訳してくれた文章の中でわからない表現があれば、そこをピンポイントで質問することで、回答を得ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/99045b43-0ae3-715e-1863-2c9ed12ba377.png)


## GPTsの設定

GPTsでの設定内容は以下の通りで、とてもシンプルです。
この指示の後ろに'単語の説明を追加して'とか、'文法の開発も加えて'とあらかじめ書いておけば、翻訳だけでなく文法的な解説も自動的に出力してくれるようになります。
（説明の内容も分かりやすいです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/b0fedb27-e8b5-e6ee-100d-59b290efa6f4.png)


## まとめ

本日はGPTsの機能を使って、自動的に翻訳をするGPTを作ってみました。
作り方は本当に簡単で、プロンプトを色々と工夫して変えるだけで、いろんなことをしてくれそうな可能性を感じます。

また、APIのアクセスの方でも、同じようにあらかじめプロンプトや呼び出し元のファイルを設定しておき、その設定のエンドポイントを呼び出して同じようなことができるようになっていました。

今回作成したGPTsはこちらにありますので、よかったら使ってみてください。
https://chat.openai.com/g/g-uUR0cGUY7-tong-yi-san
Ruby芸160チャレンジ(#5)スペース区切りのフィールドを持つテキストファイルの扱い

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
https://github.com/shellgei/shellgei160/blob/master/answer/5.md

```bash
$ cat ntp.conf | awk '$1=="pool"' | awk '{print $2}'
```

`ntp.conf`内で1番目のフィールドが`pool`の行について2番目のフィールドを表示します。

## 解
```ruby
lines = File.open('./qdata/5/ntp.conf').readlines

lines.each do |line|
  fields = line.split(' ')
  next if fields.size < 2

  puts fields[1] if fields[0] == 'pool'
end
```

## 所感
- 特になし
Ruby芸160チャレンジ(#4)ファイル中の文字列検索(正規表現)

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
https://github.com/shellgei/shellgei160/blob/master/answer/4.md

```bash
$ grep -l '^10$' -R | xargs rm
```

「10」だけ記載された行があるファイルを削除する処理です。

## 解
```ruby
files = Dir.glob('.tmp/*')

files.each do |file|
  text = File.read(file)
  puts "#{file} has #{text}" if text.match?(/^10$/)
  # 今回は削除は割愛。削除するときはFile.deleteを使う？
end
```

## 所感
- やや慣れてきたやも。readlinesした方が良い時とreadした方が良い時と、適宜使い分けていこうかな。
GASでめちゃくちゃラクチンに"コードを触れない人"に使ってもらえる基本集計を提供する準備

https://qiita.com/mountaincat/private/213d71af01de941c1d31

の続き。

機能の記事のキモはこのとおり。

JavaScript使ってピボットしたり集計したり、あんまり得意じゃないらしいし、コードいじれない人がスプレッドシートから動的に集計の変数いじれるようにしてあげてほしいよね～。

って。

# よろしい、ならばやろう。

スプレッドシートにクエリ関数を同的に運用する仕掛けは可能です。

たとえばこんなシチュエーション。
BOSSからの緊急指令。

:::note 
- ちょっとさぁ、GOOGLEファイナンスでアップルの株価をチャート描画してほしいのよ。
- うーん、開始日付は利用者がきめらえれるようにしてほしいなぁ。
- 例えば、2000年くらいからのチャートも見たいんだけどさ、年平均みたいし、年平均のグラフも長期スパンだったり中期だったり、年単位で選びたいのよね。
:::


かしこまりっ！

![_c_choju64_0015_s512_choju64_0015_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/f398fb62-a8d6-4999-8b2f-be0a88a3b83d.png)

じゃあ以下の手順でやってみう。

1. GoogleFinance()関数でアップルの株価を取得するよ。
1. 開始日を任意にしたいよ。
1. 集計関数で年ごとの平均に慣らしたいよ。
1. なんなら、年月ごとの平均に慣らしたいよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/c77c8061-ad54-df9f-98d2-1a1d4ddc48f6.png)


これでA1セルのNASDAQ上場銘柄の終値を一日ずつとってきてくれます。

株価や銘柄の指定方法は公式のヘルプをみてくださいな。

GASでとってこなくても、基本関数でここまでの動的な疑似スクレイピングは可能です。

んじゃあ、もうちょい長期で2010から取得して、年平均に慣らしてみましょっか。

まずは、D列の横に年と月をarrayformula関数で出します。
死ぬほど便利なarrayformula関数の威力が炸裂。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/bd79b626-5fd7-8768-809a-9058dd557a1f.png)

E2セルにこの式入れたらC列の年をダダダっと出してくれます。

```
=arrayformula(year((C2:C)))
```
同様に月も出すよ。
```
=arrayformula(month((C2:C)))
```

んだらあとは、まずはクエリ関数のベタ打ちで年集計してみます。

```
=query(C:F,"select E, avg(D) where C is not null group by (E) ")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/8377a4c6-bc05-0233-a798-17c1e40f35c8.png)

月平均だとこんな感じ。
```
=query(C:F,"select F, avg(D) where C is not null group by F ")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/5e7e8622-74a4-60de-df7e-a7a95d68cdca.png)


年月平均だとこれ。
```
=query(C:F,"select E,F, avg(D) where C is not null group by E,F ")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/3c33faa7-079d-ab64-5e03-7cbf6d2b0733.png)

じゃあ、これをGASに書くには？になるよね。

GASで書く時には、

銘柄のコード
開始日
平均グループ化の単位（年、月、年月）

これをスプレッドシートに入力した値から取得して
GASで書き込む関数に読み込ませてあれげればよろしい。

すると、スプレッドシートのセルでプルダウンで開始年を選ぶ、
銘柄を選ぶといった動的な株価チャートが描画されるようになる。

適当なセルで年、月、年月をプルダウン選択して、適当なセルにifs関数で
それぞれに合った列を表示させます。

今回なら、こんな感じ。
A3セルにプルダウンを指定して、

A6セルに関数書いてます。

```
=iferror(ifs(A3="年","E",A3="月","F",A3="年月","E,F"),"")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/4157a8c8-c07e-8bad-bb25-41732bf223fc.png)


A2セルにはデータの入力規則で日付型のみを入力するようにしておきます。

で、最後の関数はこうなる。

```
=query(C:F,"select "&A6&", avg(D) where C is not null group by "&A6&" ")
```

クエリ関数でセル参照するときはselect句が始まるダブルクォーテーションで一度閉じて、&でセル参照先を指定して、さらに&のあとにダブルクォーテーションで囲う式に続きを書きます。

このあたり、慣れないうちはA6セルを&で囲うように見えてしまって、式を作る法則性が分からず混乱するから気を付けましょう。

あとは、GASでこれをいい感じにコントロールする。

[昨日の記事](https://qiita.com/mountaincat/items/213d71af01de941c1d31)でお伝えしたように、取得したデータの集計用に、このクエリ関数を文字列としてGASエディタに書けばオッケーです。

この例でいう、A6セルや平均化する列としてD列などを変数としてあれこれいじることもできますし、頭の体操代わりに書いてみてください。

つづく。回答編はまた後日。

:::note warn
GAS書かんのかい！
:::
【PowerDNS,BIND他】 DNSロードバランサーのDNSDistを触ってみる　～その１～

## はじめに
PowerDNS dnsdistは、DNSクエリ向けのロードバランシングソフトウェアです。高トラフィック環境での安定性と効率性を向上させるため、セキュリティ機能やクエリルーティング制御を提供します。

 * PowerDNS DNSdist
   * https://www.powerdns.com/powerdns-dnsdist
 * DNSdist documentation
   * https://dnsdist.org/index.html

DNSクエリによる外部からの攻撃の対策として、dnsdistを既存DNSソフトウェアの上に配置する事でレート制限やクエリルーティング設定を行いサーバ負荷を低減させることが可能です。

## 実行環境、構成
 * OS：WSL2 Ubuntu 22.04
 * dnsdist：1.8.2-1

```
・本記事でのdnsdist構成
Ubuntu22(WSL) --> dnsdist(10053/udp,tcp) --> WSL用ホスト機仮想インターフェース(53/udp,tcp)

→ WSL標準設定のresolvの前段に、dnsdistを配置する構成としています。
==========================================================================
・実環境でのdnsdist構成例
[Internet] --> dnsdist(53/udp,tcp) --> BIND,PowerDNS等(53/udp,tcp)(※注）

※注…dnsdistは多くのレガシーなDNSソフトウェアの前段で使用可能である事が
公式ページに記載がありますが、具体的なDNSソフトウェアのサポート記載について
は存在しないため本番環境で使用する際はご注意ください。
```

## dnsdistインストール
ubuntu 22.04の標準リポジトリではdnsdist 1.4系が含まれていますが、現状のstableバージョンである1.8系をリポジトリサイトの手順に従いインストールします。

 * リポジトリサイト：https://repo.powerdns.com/

ページ下部にある[Ubuntu -> dnsdist - version 1.8.X (stable)]に記載のインストール手順を実施します。
## dnsdistのログディレクトリ作成
```shell
# mkdir /var/log/dnsdist
# chown _dnsdist:_dnsdist /var/log/dnsdist
```
## dnsdist.conf修正
dnsdistインストール後、/etc/dnsdist/以下のdnsdist.confを編集します。
※注…dnsdistの設定はLUAスクリプト言語に基づくため、"--"で始まる行がコメント行となります。

```shell
# vi /etc/dnsdist/dnsdist.conf

-- dnsdistのListenサーバIPアドレス:使用ポート
-- https://dnsdist.org/reference/config.html#addLocal
addLocal("172.26.2.3:10053")

-- DNSクエリのACL設定 
-- https://dnsdist.org/advanced/acl.html
setACL("172.26.0.0/16")

-- DNSクエリのバックエンドIPアドレス:使用ポート、バックエンド名、秒間クエリ制限数
-- https://dnsdist.org/reference/config.html#newServer
newServer({address="172.26.0.1:53", name="dns1", qps=300})

-- バックエンドに適用するポリシー
-- https://dnsdist.org/guides/serverselection.html
-- https://dnsdist.org/guides/serverselection.html#setServerPolicy
setServerPolicy(firstAvailable)

-- ロギング設定
-- https://dnsdist.org/rules-actions.html#LogAction
addAction(AllRule(), LogAction("/var/log/dnsdist/query.log", false, true, false))
```
設定ファイルを編集後、dnsdistをrestartします。
```shell
# systemctl restart dnsdist
```
## 名前解決の動作確認
digコマンドにて、dnsdistを経由して名前解決が可能な事を確認します。

```shell
# dig -p 10053 @172.26.2.3 www.google.co.jp +short
172.217.26.227
# tail /var/log/dnsdist/query.log
Packet from 172.26.2.3:40813 for www.google.co.jp. A with id 65362
```
## おわりに
今回の記事では、dnsdistのインストールおよびバックエンドに関する設定を行いdnsdistを通した名前解決動作を確認しました。次回は実際にdnsdistを使用し様々なクエリルーティングに関する動作を確認していきます。
Community Builders 1年目振り返り

1日目の加我さんがめちゃくちゃいい記事

https://note.com/tkaga/n/n2aab58fa7665

をかいてもらっていて、
かなりライトな二番煎じ感がすごいですが、自分のための振り返り、と
これを読んだ人が少しでもCommunity Builders（以下CBs）に興味を持ってくれますように。

## 筆者の情報（CBs認定前）

- 2021年末よりJAWS-UG SRE支部運営
- JAWS DAYS 2022実行委員

上記コミュニティ活動や2022年の登壇をもとに申請し、
2月末にCommunity Builders (container)に認定いただきました。

https://x.com/saramune/status/1630551084577226752?s=20

## CBsになってよかったこと

何番煎じ感ありますが...

### 最新情報をキャッチできる！！！

NDAを結ぶので、未公開の最新情報をいち早くキャッチできます。
WebinarはだいたいUTC時間なのでAP民にはちょっとつらいけど...

### CBs同士の交流がある！！！

AWS SummitやJAWS FestaではCBsが集まる会があり
そこでまた新しいつながりができたりしました。

### わかりやすい肩書！！！

コミュニティやってる人っていうのがわかりやすくていいですよね。

## 現在までの実績

### Blog Post 3件

AWS x コンテナなBlog記事をぽつぽつ投稿しています。

- https://dev.to/aws-builders/managing-aws-resources-with-ack-and-helmfile-2mo6
  - ACKのはなし
- https://dev.to/aws-builders/creating-network-load-balancer-sg-supported-with-aws-load-balancer-controller-168p
  - NLBにSGがつけれるようになってALBCも変わったよのはなし
- https://dev.to/aws-builders/transforming-aws-liabilities-into-assets-on-a-container-foundation-3iob
  - 細々したスクリプトをコンテナ化してEKSに乗せたら体験がよかったよのはなし
  - 日本語版をAWS x Containerのアドカレ用にさせてもらってます
    - https://qiita.com/saramune/items/9a32c392d23b24674840

### Event Hosting In Person 2件

SRE支部運営としての活動です。最近は冒頭LTでみんなもっと登壇しようぜ！という話をしています。

- JAWS-UG SRE支部 #6「CloudWatchでどこまでいけるか選手権！」
  - https://jawsug-sre.connpass.com/event/280862/
- JAWS-UG SRE支部 #7「AWSでゆるSRE！LT大会」
  - https://jawsug-sre.connpass.com/event/291843/

### Presentation Online 1件

MIXI みてねさんと合同でEKS x Auroraの勉強会を開催しました。
（会場や配信等MIXIさんにおんぶにだっこで、ありがとうございました。）

https://mixi.connpass.com/event/293351/

### その他

- JAWS Festa 2023 当日スタッフ
- 事務局の活動

## 今後チャレンジしたいこと

せっかく海外のCBsとも繋がれるチャンスがあるので、
APあたりのひとを勉強会のゲストに呼べたりしないかな〜とか妄想しています。
（でもまずは英語もっとできるようになれという話でもある）

## まとめ

もともとそこまでたくさんアウトプットするほうではないですが、
CBsになってからは遅筆ながら一定Blog Postするようになったり、いい意味で意識が変わっています。
もちろんアウトプットする人はもっとやってるので正直全然だとは思いますが
自分のペースで、でも着実に少しでもコミュニティに恩返しをし続けれていければなと思っています。