OmniAICreator/Qiita-1.07M huggingface dataset:
アニメ『ダンダダン』から学ぶ開発

最近、僕は『ダンダダン』っていうちょっと不思議な雰囲気のアニメ（元はマンガでめっちゃ人気がある作品なんだけど）にどハマりしてるんですよ。基本的にはオカルトとかUFOとかがてんこ盛りで、常識ぶっ飛んだ展開がガンガンくるんですけど、その中に爽やかなラブコメ要素もあって、なんだかクセになるんですよね。

で、そんな世界観とは全然関係なさそうなところなんだけど、僕自身はWEBエンジニアで、日々開発したり、サービスを改善したりしてる中で、この『ダンダダン』からも仕事に役立つようなヒントを感じるんです。「えっ、あのカオスなオカルトラブコメから何を学ぶの？」って思うかもしれないけれど、意外と学べることがあるんです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88756/e542f4ca-bd78-acc9-388f-598aa0a4caa7.png)

## 1. いろんな要素のミックスが新しい価値を生む

『ダンダダン』は、オカルト、SF、ラブコメといった異なるテイストがごちゃ混ぜになっています。でも、その混ざり方が絶妙で、まったく新しい世界観を生み出している。これってウェブ開発でも同じで、デザイン、機能、ユーザビリティ、パフォーマンス、セキュリティ…いろんな要素をバランスよく混ぜることで、ユーザーにとって新鮮で価値のあるサービスが提供できるんですよね。  
「関係ない」って思える要素同士を組み合わせたとき、ちゃんとバランスが取れてれば面白い価値を生むんだなって、『ダンダダン』を観てると感じます。


## 2. 柔軟性が成功の鍵

物語では、想定外の怪現象や不思議な存在が頻繁に登場します。でも、登場人物たちは「なんだこれ！？」と戸惑いつつも、最終的には状況を受け入れ、新しい作戦を考え出して前進していくんですよね。  
WEBエンジニアとしても、仕様変更や突発的な問題は日常茶飯事。「予定外」の出来事に対してガチガチに構えるより、「お、こうきたか。じゃあこっちで行こう」と柔軟に対応するマインドはとても大事です。『ダンダダン』のキャラクターたちは、まさにそうやって常識外の状況に向き合い、前へ進んでいく。これってアジャイル的な開発姿勢にもつながりますよね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88756/a54973eb-73a5-a35e-1945-c2ff713a5b75.png)


## 3. 多様な才能が掛け合わさると最強

作品中には、いろんなタイプのキャラクターが登場します。物理的に強い奴、オカルトに詳しい奴、精神的な面で不思議な力を発揮する奴…。バラバラな能力を持っているからこそ、単体ではできない問題解決が可能になるんです。  
同じように、エンジニアリングチームでも、バックエンドが得意な人、フロントエンドが得意な人、インフラやセキュリティ、UI/UXが得意な人…といった多様なスキルが集まることで、チーム全体としてより強いパフォーマンスを発揮できます。『ダンダダン』は、多様性が生み出すパワーをわかりやすく教えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88756/dd61e40c-f9b6-1fc4-402e-d749655dece9.png)


## 4. 人間関係の根っこはやっぱり「信頼」と「共感」

奇想天外な設定が目を引く『ダンダダン』ですが、キャラクター同士が支え合っているからこそ、物語に厚みが出ています。不思議な現象に巻き込まれても、一人じゃどうにもならないとき、信頼できる仲間の存在が大きな助けになる。  
WEBエンジニアが働く環境も、人同士の信頼や共感がプロジェクト成功の土台になります。ツールやプラクティスは大事だけれど、人間関係がうまくいっていないと、どんなに技術力があっても成果は限定的。『ダンダダン』を見ていると、結局「人」なんだよなぁ、と再認識させられます。

## まとめ

アニメ『ダンダダン』は、いろんなジャンルをミックスして常識外の物語を紡いでいるのに、なぜか「開発現場にも通じるなあ」と思える要素がたくさんあります。バランス感覚、柔軟な発想、多様な才能の組み合わせ、そして人間関係の大切さ。これらはどんなプロジェクトにも必要なエッセンスです。  
異色の作品から得たヒントが、あなたの開発プロセスやチームワークをちょっとだけ豊かにしてくれるかもしれません。『ダンダダン』は、そんな意外な学びが詰まった作品なんですよ。

みんなアニメ見てね！ [TVアニメ『ダンダダン』](https://anime-dandadan.com)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88756/9882bc40-5cf4-1017-ac9c-d9501bc6883b.png)
Canvaで星空の画像作成にチャレンジしてみた

こんにちは、ふるすです。  
自他ともに認める(？)Canva大好きマンな私。  
たまには新しい技術をインプットするぞ！ということで…

**新しい画像作成に挑戦します！**

参考にしたのはこちら。
[配色もアプリにお任せ・オリジナルパターン（柄）の作り方](https://banner-template.com/2023/10/12/23418/)


作成するのは、上記サイトにもあるような「夜空」をイメージしたパターンにします。

![夜空イメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/8eeefb38-6d6b-c3b6-940b-3560700afdce.png)
こんな空、どこかで見ることができるのかなぁ～

**では早速スタート！**


1. **白紙のプレゼンテーションを用意**

    ![白紙プレゼン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/3d2e8f52-901f-48e9-ac19-677954fdccaa.png)
　　
2. **参考画像からスポイトで色を抽出してグラデーションを作る**

    ![グラデーション作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/ea47f8e0-7c22-b4c8-82c4-5e109d9d3db2.png)

    ちなみにカラーコードは、#363857と#a67f79の２つで作りました。
    朝と夜の間のような、素敵な空の色になりました！
    　　
3. **アプリの「Confetti」を選び、Typeやサイズなどを調整**

    ![Confetti調整](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/723a6b8b-bc99-877a-01df-a729ec18aaf2.png)
　　
4. **さらにアプリの「Shade」を使って色を調整**

    ![Shade調整](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/c3ee527b-3896-921a-c85c-31e69d7dcf9c.png)

    元の画像がピンク色の星を基調とした感じだったので、#D44FEDをメインにカラーパレットを作成して星の色を作成！
　　
5. **何回か「Confetti」での生成をして重ねてみたりして…**

    ![星重ね](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/ff4b9b62-db06-8474-eb07-5dd7ab1f35dc.png)

    目立つ大きな星も真ん中あたりに配置して、**完成！**

![完成品](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/3e6e9ba3-2f6c-905d-582d-2b470e211cb9.jpeg)

わーい！きれいにできました:hugging::sparkles:

簡単にきれいなパターン柄を作成できたので、ほかにもいろいろなアプリを試してみたくなりました！
DjangoでHTMLを使って画面を表示する

### 1.前提条件
リンク先の作業を完了させてください。

https://qiita.com/ruruchan_nanodesu/items/32d13d80015085d58621

ファイル構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/b37cca6e-661d-6e90-405a-fad46f121f54.png)

### 2.TEMPLATESフォルダを作成する

TEMPLATESという名前で、HTMLファイルを格納するフォルダを作成します。
ファイル構成は以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/cd9e1462-3fd0-28df-2a1a-4684435965a7.png)

### 3.TEMPLATEフォルダを紐づける

プロジェクトフォルダのsettings.pyを開いてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/05d88ecc-2763-aafe-38f7-71d46f540a94.png)

2行目に下のコードを追加します。

```python:settings.py
import os
```

55行目TEMPLATESの'DIRS':[ ]を下のように追加してください。
```python:settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], #追加部分
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```

※必ずsettings.pyを更新したあとは、上書き保存をしてください。

### 4. HTMLファイルを作成する

templatesフォルダの下に、任意の名前でHTMLファイルを作成してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/7f1eee74-66b0-b6a1-2599-c35d8775b34e.png)

HTMLファイルの中身を作ります。

```html:index.html
<!DOCTYPE html>
<html lang="ja">

HELLO WORLD

</html>
```

### 5. Djangoのサーバリンクと作成したHTMLファイルを紐づける

アプリフォルダのviews.pyを開いてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/3d37ebbf-af5b-a70e-48e5-ac67473e6e35.png)

下のようにコーディングしてください。

```python:views.py
from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, "index.html")
```

### 6. 作業が成功していることを確認する

terminalでコマンドをうってください。

```
python manage.py runserver
```

リンクを踏み、画像のような画面が表示されていることを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1386677/96ece78a-c8ae-538f-51bd-b51c9e329e7c.png)

うまくいかない場合は、編集した全てのファイルに上書き保存をしてください。

---
次の作業

https://qiita.com/ruruchan_nanodesu/items/c7a2e6ceba4c79807c3c
KPSS検定とは？定常性を測る統計手法をわかりやすく解説

**KPSS検定**（Kwiatkowski–Phillips–Schmidt–Shin検定）は、時系列データが「定常性」を持っているかどうかを判断するための重要な統計手法です。本記事では、KPSS検定の仕組みや数式の解説を、初心者でも理解できるようにわかりやすくまとめました。
※この記事は、ChatGPTの出力を基に作成しています。

---

## **定常性とは何か？**

**定常性**とは、データの統計的性質が時間に依存しないことを意味します。具体的には、以下の条件を満たす場合に「定常」とみなされます：
- 平均値が一定である
- 分散が一定である
- 共分散が時間差だけに依存し、絶対的な時間には依存しない

例えば、平均20度を中心に上下する気温のデータは「定常的」といえます。一方で、時間とともに増加する売上データなどは「非定常的」です。

---

## **KPSS検定の概要**

KPSS検定は、「データが定常的である」という仮定（帰無仮説）を立て、それを検証します。以下がその基本的な流れです。

1. **データのモデル化**  
   KPSS検定では、データ$\ y_t \$ を次のようなモデルとして表現します：
  $ \
   y_t = \alpha + \beta t + u_t + \epsilon_t
   \$
   - \$ \alpha \$：定数項
   - \$ \beta t \$：トレンド成分（時間とともに増加または減少する部分）
   - \$ u_t \$：ランダムウォーク成分（累積的なランダム変動）
   - \$ \epsilon_t \$：ホワイトノイズ（平均0、一定分散のランダム変動）

2. **帰無仮説と対立仮説**  
   - 帰無仮説$\ H_0 \$：データは定常である（ランダムウォーク成分 \$ u_t \$がない）。
   - 対立仮説$\ H_1 \$：データは非定常である（ランダムウォーク成分 $\ u_t \$ が存在する）。

3. **統計量の計算**  
   累積和 \$ S_t \$ を計算し、その二乗和とデータの分散を使ってKPSS統計量を算出します：
   $\
   \eta = \frac{1}{T^2 \sigma^2} \sum_{t=1}^T S_t^2
   \$
   - \$ S_t = \sum_{i=1}^t (y_i - \bar{y}) \$（累積和）
   - \$ \sigma^2 = \frac{1}{T} \sum_{t=1}^T (y_t - \bar{y})^2 \$（分散）
   - \$ T \$：データの総数

4. **臨界値との比較**  
   計算した \$ \eta \$ を臨界値と比較します：
   - \$ \eta \$ が臨界値より小さい → 帰無仮説を採択（データは定常的）。
   - \$ \eta \$ が臨界値より大きい → 帰無仮説を棄却（データは非定常的）。

---

## **データの総数T²を使う理由**

累積和 \$ S_t \$ は、時間が進むほど値が大きくなる性質を持っています。そのため、その二乗和 \$ \sum_{t=1}^T S_t^2 \$ も時間に比例して大きくなります。

分母に \$ T^2 \$ を入れる理由は、次のような「累積効果」を補正するためです：
- 時間が長くなるにつれて累積和の増大を打ち消す。
- 統計量が時間のスケールに依存しないようにする。

結果として、データの総数にかかわらず統一された基準で評価が可能になります。

---

## **まとめ**

KPSS検定は、時系列データが定常性を持っているかを判断するための重要な手法です。その基本的な考え方は：
- **累積和の二乗和** を基にデータの定常性を評価する。
- データのばらつきやスケールの影響を分散や総数 $\ T^2 \$ で補正して標準化する。
- 計算された統計量を臨界値と比較して判定する。

---

**KPSS検定の活用**は、時系列データ分析の第一歩です。データの特性を理解し、適切な分析手法を選択するために、この手法をぜひ活用してみてください！
RemotionをつかってReactで動画を作成してみる

# はじめに

こんにちは、エンジニアのkeitaMaxです。

Remotionを使用してみる

# インストール

以下コマンドでインストールします。

```
npm i --save-exact remotion@4.0.240 @remotion/cli@4.0.240
```

一緒にESLintのプラグインもインストールします。

```
npm i @remotion/eslint-plugin
```
以下のように`.eslintrc.json`に追加しました。

```json
  "plugins": [
    "react",
    "tailwindcss",
    "@remotion"
  ],
  "overrides": [
    {
      "files": ["remotion/*.{ts,tsx}"],
      "extends": ["plugin:@remotion/recommended"]
    }
  ],
```

# ファイル

公式通りにやっていきます。以下のようにフォルダを作成しました。

```
/
└─ remotion
   ├─ Composition.tsx
   ├─ Root.tsx
   └─ index.tsx
```

それぞれ以下のように公式通りに行なっていきます。

```tsx:Composition.tsx
export const MyComposition = () => {
  return null
}
```
```tsx:Root.tsx
import React from 'react'
import { Composition } from 'remotion'
import { MyComposition } from './Composition'

export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="Empty"
        component={MyComposition}
        durationInFrames={60}
        fps={30}
        width={1280}
        height={720}
      />
    </>
  )
}
```
```tsx:index.tsx
import { registerRoot } from "remotion"
import { RemotionRoot } from "./Root"

registerRoot(RemotionRoot)
```

# 実行

以下のコマンドで実行してみます。

```
npx remotion studio remotion/index.ts
```

するとブラウザが開き以下のような画面が表示されます。

![スクリーンショット 2024-12-18 20.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/9bdb15af-da74-9c8f-59aa-4de173ebca1c.png)

#　少しいじってみる

```tsx:Root.tsx
import React from 'react'
import { Composition } from 'remotion'
import { MyComposition } from './Composition'

export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="Test" // 変更
        component={MyComposition}
        durationInFrames={60}
        fps={30}
        width={1280}
        height={720}
      />
    </>
  )
}
```

```tsx:Composition.tsx

export const MyComposition = () => {
  return (
    <div>
      <h1>テスト</h1>
    </div>
  )
}
```

こんな感じにすると以下のように出てきます。

![スクリーンショット 2024-12-18 20.24.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/ef89502f-873d-a099-0cfb-1b06ad8768a4.png)

# もう少しいじってみる

テストという文字をだんだん消したいと思います。

以下のように修正しました。

```tsx:Composition.tsx
import { interpolate, useCurrentFrame } from "remotion"

export const MyComposition = () => {
  const frame = useCurrentFrame()
  const opacity = interpolate(frame, [0, 30], [1, 0], {
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  })

  return (
    <h1
      style={{
        opacity,
      }}
    >
      テスト
    </h1>
  )
}
```

すると、以下のように時間経過で消えていくものができます！

![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/0c979040-85ea-a52b-5f2e-249341e48d01.gif)



# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://www.remotion.dev/docs/brownfield

https://zenn.dev/tellernovel_inc/articles/47bbc13b899db0
【ExcelVBA】VBAを書いてもらったら高速化もお願いする【ChatGPT】

ExcelVBA高速化の手法の一つに、セルに代入する時は1セルずつ代入するのではなく、代入する値を配列に入れて一度に代入するという手法がある。

http://officetanaka.net/excel/vba/speed/s11.htm

GPT-4にExcelVBAを書いてもらうと、だいたい初めは1セルずつ代入するマクロを提示してくる。処理する件数が少なければそれでも特に問題はないが、処理が遅いと感じたら「高速化してください」と依頼し配列に書き直してもらおう。

### 例 

「`セル範囲A1:E10に、各セルの列番号と行番号を掛けた値を入力するマクロを書いてください。`」と依頼すると書いてくれるマクロがこちら。この程度の件数なら何も問題ないが、セルへの書き出しは1セルごとに行っている。

```VB
Sub FillMultiplicationTable()
    Dim ws As Worksheet
    Dim rowNum As Long, colNum As Long

    ' 現在のアクティブシートを取得
    Set ws = ActiveSheet

    ' A1:E10の範囲をループ
    For rowNum = 1 To 10
        For colNum = 1 To 5
            ' セルに列番号と行番号の積を設定
            ws.Cells(rowNum, colNum).Value = rowNum * colNum
        Next colNum
    Next rowNum

    ' 完了メッセージ
    MsgBox "A1:E10の範囲に値を入力しました。", vbInformation
End Sub
```

「`より高速に動作するように改良できますか？`」と要望すると、画面描画の停止に加え、配列で一度に出力するよう書き直してくれる。最初からこちらで書いてほしい気もするが、可読性を優先しているのかもしれない。

```VB
Sub FillCellsWithProductOptimized()
    Dim ws As Worksheet
    Dim rowNum As Long
    Dim colNum As Long
    Dim dataArray(1 To 10, 1 To 5) As Long
    
    ' アクティブシートを対象
    Set ws = ActiveSheet
    
    ' 高速化設定
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    ' 配列に計算結果を格納
    For rowNum = 1 To 10
        For colNum = 1 To 5
            dataArray(rowNum, colNum) = rowNum * colNum
        Next colNum
    Next rowNum
    
    ' 配列を一括でセルに反映
    ws.Range("A1:E10").Value = dataArray
    
    ' 高速化設定を解除
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub
```
[iOS] 実機デバッグ時、デベロッパアプリの実行を許可してもアプリがクラッシュする

# 詰まったこと

https://qiita.com/kanatatsu64/items/bd33c85fbf890743cfc5

基本的に上記を参考にさせていただきながら手順を踏んでいたが、[8. iPhoneでアプリの実行を許可する](https://qiita.com/kanatatsu64/items/bd33c85fbf890743cfc5#8-iphone%E3%81%A7%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E5%AE%9F%E8%A1%8C%E3%82%92%E8%A8%B1%E5%8F%AF%E3%81%99%E3%82%8B) を行っても対象アプリを開いた瞬間にクラッシュしてしまう

# 解決策

https://ayousanz.hatenadiary.jp/entry/2020/09/24/Unity%E3%81%8B%E3%82%89iOS%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E3%83%93%E3%83%AB%E3%83%89%E3%81%97%E3%81%9F%E6%99%82%E3%81%AB%E3%82%A8%E3%83%A9%E3%83%BC%E8%A7%A3%E6%B6%88%E3%83%A1%E3%83%A2%E3%80%90iOS

上記を参考にさせていただき、Xcodeで実機のデバイスを指定して再ビルドしたところアプリが開けるようになった

単純なことだけど備忘録的にメモしとく
Liberty REST APIでのJMS接続の検証手順

#### 下記の環境で検証します
https://qiita.com/keniooi/items/f72a7a6d6d2e7c2871dd

server.xmlは以下です。
https://github.com/pdprof/jms/blob/d629b98a460b4f2eebaa9da10436242a50226f61/jms-docker/config/server.xml.jms-mq#L21

#### 1. 下記ページに記載の設定をします（DB接続のテストの記事です。JMS接続のテストも同様の設定になります。）
[Testing database connections in Open Liberty apps with REST APIs - OpenLiberty.io]
( https://openliberty.io/blog/2019/09/13/testing-database-connections-REST-APIs.html )

元のserver.xmlに以下を追加します。
```
$ vi /opt/ibm/wlp/usr/servers/defaultServer/server.xml
```
```
  <featureManager>
    <feature>appSecurity-2.0</feature>
    <feature>restConnector-2.0</feature>
  </featureManager>

  <keyStore id="defaultKeyStore" password="Liberty"/>
  <quickStartSecurity userName="blogAdmin" userPassword="blogAdminPassword"/>
```  

#### 2. JMSのQueueConnectionFactory
認証別名を指定してアクセスします。
https://hostname:9443/ibm/api/validation/jmsQueueConnectionFactory?auth=container&authAlias=appAuth

結果：
```
[
   {
      "uid": "jmsQueueConnectionFactory[default-0]",
      "jndiName": "QCF",
      "successful": true,
      "info": {
         "jmsProviderName": "IBM MQ JMS Provider",
         "jmsProviderVersion": "8.0.0.0",
         "jmsProviderSpecVersion": "2.0"
      }
   }
]
```

#### 3. JMSのConnectionFactory
検証のためserver.xmlにConnectionFactoryを構成します。QCFと同様に構成して、認証別名を指定してアクセスします。
https://hostname:9443/ibm/api/validation/jmsConnectionFactory?auth=container&authAlias=appAuth
```
[
   {
      "uid": "jmsConnectionFactory[default-0]",
      "jndiName": "CF",
      "successful": true,
      "info": {
         "jmsProviderName": "IBM MQ JMS Provider",
         "jmsProviderVersion": "8.0.0.0",
         "jmsProviderSpecVersion": "2.0"
      }
   }
]
```
【Rustのまほう2】#19 イベント

今回はBevyのイベントという機能について解説していきます。


# イベントとは

Bevyではシステムの集合としてゲームを定義しますが、複数のシステムで使われる共通の処理というものもあります。このとき、同一部分のコードはもちろん関数として切り出せばいいわけですが、ただの関数として共通部分を切り分けるのには欠点があります。たとえ共通の処理を関数としてくくりだしたとしても、システムパラメータは呼び出し元のシステムから受け取らなければならないのです。

たとえば、効果音を再生する関数を定義したとしましょう。この関数は魔法攻撃を行うシステムからも使われますし、UIのシステムでボタンを押したときなど、さまざまなシステムから使われます。効果音再生関数は音声データのリソースや、現在の音量を表すリソースなどを引数で受け取るため、呼び出し元のシステムにはシステムパラメータの追加も必要です。システムに機能を追加すると、この調子でシステムパラメータもどんどん増えていきます。そうすると、どのシステムパラメータが何の処理のために使われているのかわかりづらくなってしまいます。

このようなとき、効果音の再生機能をただの関数ではなく**イベント**をトリガーとする別システムとして定義すると、効果音の再生を別のシステムに切り出すことができます。魔法攻撃のシステムから効果音再生システムを呼び出すというイメージです。

# イベントの定義

イベントは具体的には`Event`を導出した構造体です。次のように新たなイベント`SEEvent`を定義してみます。

```rust
#[derive(Event, Clone, Copy)]
pub struct SEEvent {
    se: SE,
    position: Option<Vec2>,
}
```

あとは`app_event`でイベントを登録しておきます。

```rust
app.add_event::<SEEvent>();
```

# イベントの送信

イベントを送信するには、`EventWriter`というシステムパラメータを参照します。たとえば、キャラクターが魔法を使うときの`fire_bullet`というシステムは、次のように`EventWriter<SEEvent>`というシステムパラメータをとります。

```rust
pub fn fire_bullet(
    ...
    mut se_writer: EventWriter<SEEvent>,
    ...
) {
    ...
}
```

あとは、効果音を鳴らしたいときに`send`を呼ぶだけです。

```
se_writer.send(SEEvent::pos(SE::Fire, spawn.position));
```

これで、`send`を呼ぶたびにイベントキューにイベントが溜まっていきます。


# イベントの受信

イベントキューにたまったイベントを取り出すには、`EventReader`というシステムパラメータを参照します。それで`read`を呼べば、イベントキューに溜まったイベントをひとつづつ処理できます。ここで実際に効果音を再生する処理を行えばいいわけです。

```rust
fn se_events(
    ...
    mut reader: EventReader<SEEvent>,
    ...
) {
    for event in reader.read() {
        ...
    }
}
```

これで、効果音を鳴らしたい側のシステムは、`EventWriter<SEEvent>`というシステムパラメータだけを追加すれば効果音を鳴らせるようになります。


もしここでイベントではなくただの関数で共通コードをまとめようとすると、効果音を鳴らしたいシステムは、音声データを格納するリソースや、音量設定を格納するリソース、カメラを取得するクエリなどの他の複数のシステムパラメータが必要でした。それが`EventWriter<SEEvent>` ひとつだけを追加すればよくなり、コードの見通しがよくなりました。

効果音を再生するのになぜカメラのクエリをするのか？と思うかもしれませんが、カメラの位置から遠い場所で発生した出来事の効果音は小さい音量で再生するようになっているからです。それは効果音再生システムの実装の都合でしかありませんが、イベントを使うことでこのあたりの実装の詳細も隠蔽できるわけです。




# 参考文献

今回書いた内容はcheatbookにも同じようなことが書いてあります。

https://bevy-cheatbook.github.io/programming/events.html
middleware.tsが実行されない問題【Next.js】

# はじめに
表題の通り、Next.jsのプロジェクトでmiddleware.tsが実行されない事象が発生しました。

# 問題
以下の通り格納しているmiddleware.tsが実行されないという問題が発生しました。

```
└── app/
    └── middleware.ts
```

# 解決方法
フォルダ構成が誤っていた。なんというケアレスミス。
下記の通り、app配下ではなくappと同階層に配置する必要がありました。。

```
├─── app/
└── middleware.ts   
```

# おわりに
configファイルの設定がおかしいのかなと思い色々漁っていたんですがそんなこともなく、20分近く格闘してしまいました。。

# 参考

## JISOUのメンバー募集中🔥
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！👇

https://projisou.jp/
UiPathコミュニティ最大の年次イベント「UiFes」準備の裏側と3DCG制作の挑戦

UiPathコミュニティ最大の年次イベント「UiFes」は、例年10月か11月に開催されますが、その準備は早い段階から始まります。特に、海外のUiPathサイトを活用して情報を集めることが重要です。日本の公式サイトはタイムラグがあり、情報が新鮮ではないため、常に最新情報を把握するために海外サイトをチェックすることにしています。

:sunny:3月
イベント情報収集とシナリオ作成のための準備
例えば、3月19日に開催された「UiPath AI Summit」の資料や動画は、イベントの方向性を理解し、シナリオのヒントを得るための貴重な資源となります。このようなイベントから得た知識を元に、半年先の「UiFes」に向けたストーリーを構築します。重要なのは、イベント当日にはすでに周知されている情報が多くなるため、情報が色褪せないように、先行してストーリーを作り込んでいくことです。

:sunny:4月
3DCG素材の選定と購入
ストーリーに合った3DCG素材の選定は、制作における重要な部分です。これまでに購入した素材から適切なものをピックアップし、足りない部分を補うために新たに購入することになります。しかし、定価で購入するのは制作費が高騰してしまうため、セール価格を待ち続ける方法を取ります。セールの更新は3時間おきに行われるため、頻繁にチェックが必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948589/21a7b905-c3c3-1bb5-8e2d-8a4fe9a54ea4.png)

:sunny:5月
シナリオ修正と制作のアドバイス
シナリオが完成したら、プロのドラマ制作に携わっている友人に添削してもらい、内容の改善点やアドバイスを受けます。この段階でのフィードバックは、最終的な完成度を高めるために不可欠です。

:umbrella:6月
3DCGの実験と技術的挑戦
今回のテーマは「気候変動」です。3DCG制作では、特に雨のシミュレーションや大勢の人が逃げまどうシーンなど、CPUに高い負荷がかかるシーンに挑戦しています。PCの限界を試すためにも、リソースを大量に消費するシーンを重視しています。このような実験を通じて、技術的なチャレンジが浮き彫りになります。

UiPath AI-Powered Automation Summit Tokyoへの参加
6月17日に開催された「UiPath AI-Powered Automation Summit Tokyo」に参加し、UiPathブースでの展示を見学しました。特に、ESGレポートをUiPath製品を使って作成する方法について、新聞記者のように細かく質問をしました。このように、業界の動向をキャッチアップしながら、制作に役立つ情報を得ていきます。

:sunny:7月
生成AIによる楽曲制作と声優探し
最近、生成AIを使った楽曲制作が容易になったため、実際に試してみたところ、2曲の素晴らしい楽曲が生成されました。これを基に、声優さんに台詞パートの他にヴォーカルの依頼を行いました。1曲目はインストゥルメンタルのみで生成されたものに、初音ミクに歌詞を読ませ、声優さんにメロディを理解してもらうという作業が必要でした。この作業は予想以上に難航し、深夜の時間帯に声優さんとのやり取りが集中することに。最終的に、声優さんの不満がつのり価格交渉が難航、何度も降板の申し出がありましたが、必死の引き留めが続きました。

:sunny:8月9月
新たな挑戦と技術革新
昨年のクオリティを越えられないという悩みを抱えながらも、新たに有望な動画生成AIが発表され、さらに制作の可能性が広がりました。これを機に、今年の制作では新たな技術を取り入れ、より高品質なコンテンツを目指して挑戦を続けました。

動画生成AIには、テキストから生成する方法と画像から生成する方法の2種類がありますが、前者は生成される動画の予測が困難であり、作品の統一性を欠く可能性が高いです。そのため、今回は画像から生成する方法を選択しました。

画像から動画生成：3DCGとAIの融合
画像から動画を生成する方法では、最初の1コマ目となる画像を自分で作成しなければなりません。このプロセスは、私自身が持っている3DCG制作のノウハウが活かされる部分ですが、イメージ通りの3DCG素材を所有している必要があります。とはいえ、生成AIを使用した場合、予想外の動画が生成されることが多く、10回試して1回成功するかどうかという結果になります。生成AIはプロンプトをいくら細かく書いてもガチャ要素が多く、まさにお金が湯水のように消えていくギャンブルのような側面があります。

私自身、トータルで300回ほど試してみましたが、最終的に作品に反映できた時間は30秒もないかもしれません。観客の中には、すべての動画が生成AIで作られたものだと思った人もいましたが、実際は逆で生成AIが思うような動画を作れなかったため、3DCGに切り替える方が頻繁にありました。

3DCG制作の手間と時間
生成AIであれば、平日のサーバーが混んでいない時間であれば2～3分で動画を作成できるのに対して、3DCGの場合は素材を組み合わせ、アニメーションを作り、台詞に合わせて口の動きをキャプチャーする必要があります。アニメーション制作は、1秒あたり30枚のフレームをレンダリングし、1秒ごとの動きを作り込んでいきます。この作業は、例えば10秒の映像を作るために、PCが10時間以上唸りっぱなし、下手をすると1週間回しっぱなしという状況になります。作業量が多く、時間がかかるため、非常に負荷の高い作業です。

:sunny:10月
最終的な編集作業とAIによる作曲
最終作業には、Adobe Premiere Proを使用して編集を行いました。レンダリングしたアニメーションに音楽と効果音を付け加えていきます。音楽に関しては、今回は生成AIを利用して作曲したため、ギタリストとの意見の食い違いや口論といった気苦労はありませんでした。この点については非常に効率的で助かりました。

編集作業は複雑な特殊効果を加えることはせず、シンプルに進めたため、1ヶ月で終了し、本番前の配信リハーサルに臨むことができ、大きな指摘もありませんでした。
さて、本番は？イベントメンバーの評価は上々でしたが、一般参加の方の感想が全く分からない状況なので果たして成功だったのか知りたいところです。

結論：生成AIと3DCGの使い分け
今回の制作では、生成AIと3DCGを組み合わせて使うことに挑戦、どちらも一長一短がありました。生成AIの短時間での動画作成のメリットを活かす一方で、3DCGによるクオリティ重視の部分も大切にしなければなりません。どちらの方法にもそれぞれの課題があり、次回の制作ではさらに工夫を凝らしていきたいと考えています。

配信から2週間が経過し英語字幕作成と衝撃の予告映像を追加しています。ナレーションにプロの声優さんを起用させて頂いたお陰でYoutube版は再生数を延ばすことでしょう。
【UE5】パスの変換(エクスプローラー ⇐⇒ UE)

この記事は[Unreal Engine (UE) Advent Calendar 2024 シリーズ2](https://qiita.com/advent-calendar/2024/ue)の20日目の記事です。


今回は、エクスプローラーのパスとUEのプロジェクト内のパスの変換についてです。
Path系のプラグインも追加され、便利になったようで、ちょっと痒いところに届いていなかったので、記事として投稿します。


# やりたかった事

『**エクスプローラーのパス**』と『**プロジェクト内のパス**』に相互に変換する事です。
また、エクスプローラーのパスは、**フルパス**で欲しいという感じです。
[ヒストリアさんの記事](https://historia.co.jp/archives/22947/)で、パスを扱うノードの一覧を作成されていますが、相対パスを返すノードはありますが、フルパスを返してくれるものがなかったので、作成し、関数ライブラリとして扱っています。


# 確認環境
UnrealEngine 5.3.2

# 『エクスプローラーのパス』を『プロジェクト内のパス』に変換する

![Convert To Project Pathのブループリント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/46854efc-ff28-1b80-6893-d76c2abf8b85.png)



# 『プロジェクト内のパス』を『エクスプローラーのパス』に変換する

![Convert To Explorer Pathのブループリント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/c6961783-2f2e-901c-747e-e2e0b46de2fc.png)

動作確認するとこんな結果になります。

![テスト結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/90e099cd-e006-ef95-b415-2b23936882f5.png)

明日は、**Sig**さんです。よろしくお願いいたします！
ポートフォリオを諦めて作ったもの置き場にしたら気楽になった

お疲れさまです、みやもとです。

今年はハンズオン含めあれこれ作ってみた年でした。
ほぼLINEBOTばっかりですが、GitHubに登録したはいいもののすっからかんだった時期を思えば頑張った気がします。

今日の記事ではあれこれ作れるようになるまでのことも含めて振り返ってみたいと思います。

# ポートフォリオってなんだ
おそらく前回の転職活動前後から、周囲で「ポートフォリオ」という言葉をちょこちょこ耳にするようになりました。
[レバテックさんとこに説明があった](https://career.levtech.jp/guide/knowhow/article/31009/)ので引用します。
>ITエンジニアの転職で必要なポートフォリオとは、経験やスキルが分かるよう、成果物をまとめたものを指します。ポートフォリオは、直訳すると「紙挟み」や「書類かばん」という意味です。
ポートフォリオに具体的に記載する内容は、携わったプロジェクトや業務外で制作したアプリ、Webサイト、ソースコードなどが挙げられます。実際の成果物を掲載することで、自分のスキルや強みをアピールできます。つまり、ITエンジニアの転職において、ポートフォリオは自己アピールするための重要な手段です。

最初に見たときは正直めちゃくちゃ他人事でした。
なにせその時点でポートフォリオに書けるようなものが何もない。

その後「GitHubとかで作るといいですよ」とアドバイスをもらったりしたものの、今ひとつピンと来なくて放置していました。

# 自分でハードルを上げていた
なぜ作れなかったのか？
今にして思えば「資料に載せるからにはすごいものを作らなくては」という気持ちがあったのだと思います。

唐突に自己分析に入りますが、私は0→１より1→10の方が得意な自覚があります。
要はアイディアを出したり新しいものを見出したりするより、そこにあるものに手を加えたりするのが得意。
よって何かを作るにしても、お手本をもとにちょっと何か足したり変えたりするぐらいのものになります。

「わざわざ作ったことを公表するからにはちゃんとしたものを作らないといけないのでは？」
「すでにあるものと似たり寄ったりのものを出しても仕方ないのでは？」

どうしてもそんな感覚がぬぐえず、ちょっとコードを書いてもそれをポートフォリオに載せる気になれませんでした。

# 意識転換
転機になったのは今年に入って作ったLINEBOTです。
機能としては特にめずらしくはない、ランダムでおみくじを返すだけのもの。
自分で「こういうものを作ろう」と決めて作ったのはおそらく初めてだったのでテンションも上がっていたのだと思います。

また、少し前にGitHubを勉強しようと思ってアカウントを作っていたのも影響しました。
勉強用に作ったアカウントは以降何に使うでもなくすっからかんのまま。
「せっかく作ったんだから何かに使いたい…」という貧乏性から、作ったものをとりあえず突っ込んでおく物置にすることにしました。

# 「見せなくてもいいや」の開き直り
ひと様に見てもらうのが前提の「ポートフォリオ」から基本自分が見るだけの「作ったもの置き場」に考え方が変わった結果、拍子抜けするほど何か作って入れていくのに抵抗がなくなりました。
一応プロフィールに紐づけたりしているのでたまにどなたか見てくださっている可能性はありますが、「別に見てもらうようなすごいものじゃないし…」という理由で躊躇することがなくなりました。[^1]

私が変に見栄っ張りなせいもあるでしょう。
他人からどう見られるかを意識することも時には必要でしょう。

でも、楽しく何かを作る上でそういう意識が邪魔をするなら、一度「見せること」を忘れるのも大事なのかなと思うのでした。
[^1]:Qiitaとかに記事を書くのは、「『こんなの見せていいのか？』という自意識＜体験を整理するために書きたいという目的＋書くこと自体楽しい気持ち」なので気にならない。
M&Aによる開発チームの統合経験を振り返って

:::note info
この記事は クラウドワークス グループ [Advent Calendar 2024](https://qiita.com/advent-calendar/2024/crowdworks) シリーズ1の20日目の記事です。
:::


# はじめに
こんにちは。[クラウドログ](https://www.crowdlog.jp/)の開発チームでエンジニアをしている @tera4ma です。
今回は初めてM&Aした会社の開発チーム統合を経験した話をしようと思います。

# 始まりは突然に
突然、M&Aで合流することになった会社の開発チームとの統合が決まり、その担当となりました。噂は聞いていたものの、まさか自分が深く関わるとは思っていなかったため、正直焦りました。

開発チームのリーダーとして動いてはいたものの、これまでは自チーム内でのやり取りが中心でした。そのため、文化や価値観が異なる新しいチームとうまく統合できるかな...と**不安MAX**でした。

# トライしたこと
泣き言を言っても始まりません。新しいチームになってから、さまざまなことにトライしました。
- **ナレッジのドキュメント化**による属人化の排除
- **Scrum開発の導入**による開発プロセスの統一
- **問い合わせ業務の効率化**
- **クラウドログで工数記録**を開始し、振り返りに利用するためのデータ蓄積
- **タスク管理方法の改善**による業務透明性の向上

他にも色々実施しましたが、これらの中でも、個人的には**Scrum開発の導入**が最も効果的でした。具体的なメリットを以下に紹介します。

### コミュニケーション機会の増加
新しいチームとクラウドログの開発プロセスを統一するため、Scrum開発を導入しました。

もちろん、今後の機能開発の効率を高めるという目的もありましたが、それ以上に**コミュニケーション機会が増える**という点に大きなメリットを感じました。

これまで関わりがなかった人とスムーズに仕事ができるかと問われたら、僕は**No**と答えます。相手の性格や接し方がわからないと、ただ話すだけでも緊張しちゃいます。（人見知り）

しかし、Scrum開発では**強制的にコミュニケーション機会が生まれます**。これによって、新しいメンバーのことを知る機会が自然と増え、会話の心理的ハードルが下がりました。

### 文化と価値観の確認
Scrum導入を通じて、文化や価値観の確認も進めることができました。

開発プロセスを統一すると言っても、完全に統一したわけではありません。チームの成熟度やメンバーの性質（個性）を把握してスタートラインを決める必要があります。

そこで、Scrumで活用できる以下の項目についてチーム内で議論をして完成させました。

- **やらないことリスト**
- **トレードオフスライダー**
- **完成の定義**

内容はもちろんScrumで活用できるため有益なのですが、その副産物として、完成させるにあたって **「譲れる点・譲れない点」や「メンバーの考え方」** を知ることができました。
これが個人的には重要で、「この人はどんな部分なら妥協できるのか？」「この人にとっては何が重要なのか？」を知ることができ、その後のコミュニケーションがスムーズになったと感じています。

### 会話の心理的安全性の上昇
Scrumでは定期的に振り返り（レトロスペクティブ）を行いますが、その機会を活用して会話の心理的安全性をあげることができたと感じています。

振り返りでは、以下のルールを徹底しています。
- **問題や意見は率直に話す**
- **責めるのではなく、改善に向けたポジティブな対話をする**

当たり前ではありますが、これらに慣れてくれば率直な意見を出すことが日常的な習慣になります。そして、それは普段の会話にも生きてきます。

ある程度知った者同士でしたらそこまでハードルは高くないかもしれません。しかし、初めましてで会って１、２ヶ月そこらの人に対して、いきなり「率直に意見をぶつけましょう！」と伝えてもなかなか習慣化させることは難しいと思います。

なので、定期的に行われ、かつ率直に意見をぶつけるべき場である振り返りを利用して慣れてもらい、それが普段の会話にも反映されれば良いと考えて実践しました。

結果として、初期と比べて普段の会話でも率直に意見を言っている機会が増えたと感じています。

# 苦労したこと
最も苦労したのは **DD（Due Diligence）に参加していなかったから事前情報がなかった点** です。DDにはインサイダー情報が含まれるため、私は情報が公開されるまで関わることができませんでした。

もし最初から参加できていれば、
- どれくらい属人化した状況なのだろう？
- 開発体制や技術スタックはどうなのだろう？
- 改善すべき点はなんなのだろう？

を先回りして整理することができ、スタートダッシュを切れたと思っています。

しかし、今回は事前情報が全くない状態で統合を任されたため、**キャッチアップに時間** がかかってしまいました。


# 最後に
色々書きましたが、今回の経験を通して感じた**M&Aによる開発チーム統合をする上で大事なこと**は２つです。
- **コミュニケーション機会を増やして相手を知れ！**
- **チーム統合を担当するメンバーには、DD（Due Diligence）の段階から参加してもらえ！**

知識や技術スキルも大切ですが、やはり**メンバーとの繋がりをまずは大事にする**という点が基本であり最も大切だなと改めて感じました。
大変なこともありましたが、初めてイチからチームビルディングをすることができ、非常に勉強になりました。ここで学んだことを活かしつつ、これからも精進してきたいと思います。
文字列比較、正規表現、Procを使ってフィルタリング

#### Procを使ってフックをフィルタリングする
>### Filtering hooks using a Proc
```rb
RSpec.configure do |config|
  config.before(:example, :foo => Proc.new { |value| value.is_a?(String) } ) do
    invoked_hooks << :before_example_foo_bar
  end
end

RSpec.describe "a filtered before :example hook" do
  let(:invoked_hooks) { [] }

  describe "group without matching metadata" do
    it "does not run the hook" do
      expect(invoked_hooks).to be_empty
    end

    it "does not run the hook if the proc returns false", :foo => :bar do
      expect(invoked_hooks).to be_empty
    end

    it "runs the hook if the proc returns true", :foo => 'bar' do
      expect(invoked_hooks).to eq([:before_example_foo_bar])
    end
  end

  describe "group with matching metadata", :foo => 'bar' do
    it "runs the hook" do
      expect(invoked_hooks).to eq([:before_example_foo_bar])
    end
  end
end
```
* callメソッドでfalseが出力される
```
Run options: include {:full_description=>/a\ filtered\ before\ :example\ hook/}
4 examples, 0 failures, 4 passed
```
#### 正規表現を使ってフックをフィルタリングする
>### Filtering hooks using a regular expression
```rb
RSpec.configure do |config|
  config.before(:example, :foo => /bar/ ) do
    invoked_hooks << :before_example_foo_bar
  end
end

RSpec.describe "a filtered before :example hook" do
  let(:invoked_hooks) { [] }

  describe "group without matching metadata" do
    it "does not run the hook" do
      expect(invoked_hooks).to be_empty
    end

    it "does not run the hook if the value does not match", :foo => 'baz' do
      expect(invoked_hooks).to be_empty
    end

    it "runs the hook if the value matches", :foo => 'bar' do
      expect(invoked_hooks).to eq([:before_example_foo_bar])
    end
  end

  describe "group with matching metadata", :foo => 'bar' do
    it "runs the hook" do
      expect(invoked_hooks).to eq([:before_example_foo_bar])
    end
  end
end
```
#### 文字列比較を使ってフックをフィルタリングする
>### Filtering hooks using string comparison
```rb
RSpec.configure do |config|
  config.before(:example, :foo => :bar ) do
    invoked_hooks << :before_example_foo_bar
  end
end

RSpec.describe "a filtered before :example hook" do
  let(:invoked_hooks) { [] }

  describe "group without matching metadata" do
    it "does not run the hook" do
      expect(invoked_hooks).to be_empty
    end

    it "does not run the hook if the coerced values do not match", :foo => 'baz' do
      expect(invoked_hooks).to be_empty
    end

    it "runs the hook if the coerced values match", :foo => 'bar' do
      expect(invoked_hooks).to eq([:before_example_foo_bar])
    end
  end

  describe "group with matching metadata", :foo => 'bar' do
    it "runs the hook" do
      expect(invoked_hooks).to eq([:before_example_foo_bar])
    end
  end
end
```

https://rspec.info/features/3-13/rspec-core/hooks/filtering/

### 感想
文字列比較や正規表現、メタデータなどでもフィルタリングができるが、使い分けも気になるがそれは後にしよう。
Clojure: DuctでRSSリーダーを作る - ルーティング

![advent_calendar_2024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/f4cd8ce0-6352-a1d8-4cae-f39dd44f4def.png)

[*Advent Calendar 2024 Day 20*](https://qiita.com/advent-calendar/2024/clojure)

昨日はDuctでプロジェクトのセットアップをしました。

今日は`ataraxy`のルーティングを実装してみます

## Ataraxy

`Ataraxy`は、ClojureのWebアプリケーション開発においてリクエストのルーティングやレスポンスの管理を簡潔に行うためのライブラリです。

`Duct` のプロジェクトをセットアップする際に簡単に追加できます

```bash:例
$ lein new duct example-api +api +ataraxy
```

## ルーティングの実装

プロジェクトを起動すると、プロジェクトの設定が書いてある`config.edn`は以下のような状態だと思います

```clojure:config.edn
{:duct.profile/base
 {:duct.core/project-ns example-api

  :duct.router/ataraxy
  {:routes {}}}

 :duct.profile/dev   #duct/include "dev"
 :duct.profile/local #duct/include "local"
 :duct.profile/prod  {}

 :duct.module/logging {}
 :duct.module.web/api
 {}}
```

この中のルーティングの設定部分は

```clojure
  :duct.router/ataraxy
  {:routes {}}
```

この部分です。

この部分に`GET /v1/feeds`というパスを追加してみます

```clojure
  :duct.router/ataraxy
  {:routes
   {[:get "/v1/feeds"] [:clojure-rss-reader.handler.feeds/get]}}
```

このように指定してみました。

これは、`/v1/feeds`にGETリクエストが来た時に、`clojure-rss-reader.handler.feeds/get`というコンポーネントで処理するという設定です。

また、この`clojure-rss-reader.handler.feeds/get`というコンポーネントの初期化の設定も必要です

```clojure
  :duct.router/ataraxy
  {:routes
   {[:get "/v1/feeds"] [:clojure-rss-reader.handler.feeds/get]}}

  :clojure-rss-reader.handler.feeds/get {}
```

これで初期化できました。

これは`clojure-rss-reader.handler.feeds/get`というコンポーネントの初期化じに空のマップを渡すという意味です

では、`clojure-rss-reader.handler.feeds/get`のコンポーネントを実装してみます

## コンポーネントの実装

```clojure:handler/feeds.clj
(ns clojure-rss-reader.handler.feeds
  (:require [ataraxy.response :as response]
            [integrant.core :as ig]))

(defmethod ig/init-key ::get [_ _]
  (fn [_]
    [::response/ok {:message "OK"}]))
```

ここでは`ataraxy.response`と`integrant.core`をインポートしました。

- `ataraxy.response`
    - `ataraxy`のレスポンスを簡潔に作成するライブラリ
- `integrant.core`
    - `integrant`は、構成をデータとして定義し、管理する[ライブラリ](https://github.com/weavejester/integrant)


また、レスポンスに関しては `Ataraxy`の一部である`ataraxy.response`を用いて実装しました。

これで実際にリクエストを送ってみます

今回はREPLで起動します

```bash
$ lein repl
user=> (dev)
:loaded
dev=> (go)
:duct.server.http.jetty/starting-server {:port 3000}
:initiated
```

`(dev)`で開発環境をロードし、
`(go)`で起動します

port `3000`で起動したようなので、`v1/feeds`にリクエストを送ってみます

```bash
$ curl localhost:3000/v1/feeds
{"message":"OK"}
```

無事レスポンスが返ってきました。

明日はDBに接続していきます
app、helperオブジェクト

# コンソール上からアクセスできる
>2.3.1 appオブジェクトとhelperオブジェクト
bin/rails consoleの実行中、appオブジェクトとhelperオブジェクトにアクセスできます。
>
>appメソッドを使うと、`名前付きルーティングヘルパーにアクセスできます。リクエストを投げる`こともできます。
```rb
irb> app.root_path
=> "/"

irb> app.get _
Started GET "/" for 127.0.0.1 at 2014-06-19 10:41:57 -0300
...
```
>helperメソッドを使うと、`Railsのアプリケーションヘルパーと自分が実装したヘルパーにアクセス`できます。
```rb
irb> helper.time_ago_in_words 30.days.ago
=> "about 1 month"

irb> helper.my_custom_helper
=> "my custom helper"
```
https://railsguides.jp/command_line.html#:~:text=2.3.1%20app%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88,my%20custom%20helper%22
【GPTプロンプト講座基礎編④】悪いプロンプトを避けよう

# §プロンプトエンジニアリング基礎編④
※本記事は執筆にあたり生成AIツールを使用している箇所があります
※プロンプトの基礎部分は生成AIで作成し、具体例や体験談を自分の視点で補完しています

こんにちは。ゆずかきです。

前回は、特定の目的に合わせた応用的なプロンプトの使い方についてお話ししましたね。今回は、プロンプトエンジニアリングを実践する際に押さえておきたい注意点や、さらに最適化を進めるための具体的なテクニックをご紹介します。

# §プロンプトエンジニアリングにおける注意点

プロンプトエンジニアリングを成功させるためには、以下のポイントに注意することが大切です。

- 曖昧な指示を避ける
AIは与えられた情報に基づいて動作するため、曖昧な表現では意図しない結果が返ってくる可能性があります。
　
- 偏りを防ぐ
プロンプトの内容によっては、特定の視点に偏った回答が生成されるかもしれません。公平性を意識したプロンプトを設計しましょう。
　
- 過剰な情報を与えない
プロンプトが長すぎると、AIが重要な情報を正しく把握できなくなる場合があります。必要な情報だけを簡潔にまとめることが重要です。

　
**結局、今のAIって「何でも出来る万能ツール！」じゃないんです。**
**AIの限界と得意を知り、人間がどう使うか？が大切だと思います。**


# §プロンプトの最適化テクニック
私が考えている具体的なテクニックについて触れていきますね。

- フィードバックループを活用する
AIから返ってきた回答を分析し、意図と合わない場合はプロンプトを微調整します。このプロセスを繰り返すことで、徐々に精度を高めることができます。
　
- テストを行う
同じプロンプトを複数回試し、回答が一貫しているか確認します。一貫性がない場合は、プロンプトの内容や指示形式を見直しましょう。
　
- 出力形式を明示する
「箇条書きで答えてください」「段落形式で書いてください」など、具体的な出力形式を指定することで期待通りの結果を得やすくなります。
　
- 背景情報を提供する
「次の条件をもとに」といった形で文脈を提供すると、AIがより的確な回答を生成します。前提の共有をいかにするか、報連相が大切なのは人間と同じです。
　
- 短いステップに分解する
複雑な指示は、複数のシンプルなプロンプトに分解することで精度を上げることができます。


# §実践例

以下は、注意点や最適化テクニックを活用したプロンプトの例です。

- 曖昧なプロンプト①
「AIの基本について教えてください。」
　
- ⇒改善案：具体的なプロンプト
「AIの基本的な概念を、初心者向けに200字以内で説明してください。」
　
- 曖昧なプロンプト②
「AIの活用例を教えてください。」
　
- ⇒改善案：背景情報を含めたプロンプト
「企業がAIを使って効率化を図る方法を、事例を挙げながら簡潔に説明してください。」
　
- 曖昧なプロンプト③
「この内容をまとめてください。」
　
- ⇒改善案：出力形式を指定したプロンプト
「次の文章を要約し、箇条書きで3つのポイントにまとめてください。」


# §まとめ

プロンプトエンジニアリングを効果的に進めるには、注意点を押さえた上で最適化を図ることが重要です。曖昧さを避け、出力形式や背景情報を工夫することで、AIの応答精度を大幅に向上させることができます。
　
**🔑 この記事のポイントまとめ（今回ちょっと長いです)**
**曖昧な指示を避ける → 具体的な内容や出力形式を指定せよ。**
**偏りを防ぐ → 公平性を意識したプロンプト設計を行うこと。**
**過剰な情報を与えない → シンプルかつ必要な要素に絞ること。**
**フィードバックループを活用 → 回答を分析しプロンプトを改善！。**
**テストを行う → 同じプロンプトで一貫性のある出力を確認せよ。**
**出力形式を明示する → 箇条書きや段落形式など具体的に指示せよ。**
**背景情報を提供 → 前提条件や文脈を共有せよ。**
**短いステップに分解する → 複雑な指示はシンプルなタスクに分けるべし。**
　
次回は、さらに発展的なテーマとして、プロンプトエンジニアリングを活用した高度な応用例について解説していきます。どうぞお楽しみに！

ご訪問いただきありがとうございました！
日本語プログラミング言語Mindに欲しい機能 2024

Mindに欲しい機能を今年も議論したいと思います。

GUIはまもなくMind v9 でTcl/Tk を使って実装予定と聞いています。この他にもあると良い機能について優先度・実装方法などを検討し、Mind作者の @killy さんに提案していきたいと思いますので、よろしくお願いします。

他の言語で作成されてソースが公開されているものは、それをMindに書き換えることも可能な場合もあると思いますのでお知らせください。

Mindをまだお使いでない方は　[Mind ダウンロード　ページ](https://www.scripts-lab.co.jp/mind8download/download.html)　から無料でダウンロードできます。[Mind プログラミングマニュアル](https://www.scripts-lab.co.jp/mind/ver8/doc/index.html)　を参考にしてください。
[Mindサポート掲示板](https://www.scripts-lab.co.jp/support/public/html/mind.cgi?tframe+035+-s+F001)　に結果を集約できたらと思います。

昨年のアドベントカレンダーでは
[日本語プログラミング言語Mindに欲しい機能](https://qiita.com/ITvision/items/19b3749e015aabd0c331)では、
・文字列関係関数
・EXCEL対応レベル
・jsonパーサ
・小技集
・データベース操作
・乱数

[mindの研究　その41-mind 良いところ、悪いところ](https://qiita.com/ohisama@github/items/1970e6c7967733008542#comment-58673685ec664f54e364)では、
・jsonパーサが無い。
・正規表現エンジンが無い。
・ソケットが弱い。
・guiが無い。> V9（近日中公開）で対応予定
・ActiveXが呼べない。
・データーベースが無い。

などが挙げられています。

上記に優先順位を付けていただいても良いかなと思います。
私は、「データベース操作」に１票を入れたいと思います。
・文字列関係関数、・小技集はV9公開後にみんなで充実して行けば良いかなと思います。
Azure Blob Storageでコードからサブフォルダを作成する方法

## Azure Blob Storageでコードからサブフォルダを作成する方法

Azure Blob Storageでは、サブフォルダを作成するために何かしらのファイルをアップロードする必要があります。以下のコードは、C#を使用してAzure Blob Storageにサブフォルダを作成するサンプルです。あんまり調べても出てこなかったので備忘も兼ねて書きます。

### 必要なパッケージ
まず、Azure Blob Storageを操作するために必要なパッケージをインストールします。

```c#:
dotnet add package Azure.Storage.Blobs
```
### コード例

以下のコードは、`BlobService`クラスを定義し、サブフォルダを作成するためのメソッド作ります

```c#:BlobService.cs
using Azure.Storage.Blobs;
public class BlobService
{
    private readonly BlobContainerClient _containerClient;

    public BlobService(IConfiguration configuration)
    {
        //環境変数から取得する
        //AppService等使ってる場合はマネージドIDからDefaultAzureCredentialsで取ってきたほうがベター
        var connectionString = configuration["AzureBlobStorage:ConnectionString"];
        var containerName = configuration["AzureBlobStorage:ContainerName"];
        var serviceClient = new BlobServiceClient(connectionString);
        _containerClient = serviceClient.GetBlobContainerClient(containerName);
    }
    //サブフォルダを作るメソッド
    //なんでも良いのでファイル入れる必要があります
    //ここではcreate.txtを作成しています
    public async Task CreateSubFolderAsync(string subFolderName)
    {
        var blobClient = _containerClient.GetBlobClient($"yourFolder/{subFolderName}/"+"create.txt");
        await blobClient.UploadAsync(new MemoryStream(), overwrite: true);
    }
}
```
こんな感じで使います
```c#
        [HttpPost]
        public async Task<IActionResult> CreateFolder(string folderName)
        {
            if (!string.IsNullOrEmpty(folderName))
            {
                await _blobService.CreateSubFolderAsync(folderName);
            }
            return RedirectToAction("Index");
        }
```
### 説明

1. **BlobServiceクラスのコンストラクタ**:
    - `IConfiguration`を使用して、Azure Blob Storageの接続文字列とコンテナ名を取得します。
    - `BlobServiceClient`を作成し、指定されたコンテナのクライアントを取得します。

2. **CreateSubFolderAsyncメソッド**:
    - 指定されたサブフォルダを作成するために、`create.txt`という名前のファイルをアップロードします
    - Azure Blob Storageでは、空のフォルダを作成することができないため、何かしらのファイルをアップロードをする必要があります
    
### まとめ

Azure Blob Storageでサブフォルダを作成するためには、空のファイルをアップロードする必要があるよ～ということです。
ちなみにこの記事の8割は手元のコードに対してGithub Copilot君にQiitaの記事を書いてと投げて生成されたものです。便利ですね。
剰余類

　ガロア理論の本を読むと、余りの数で分類したグループを
 「剰余類」と呼んでいる。たとえば１００を５で割ると、余りが
 １，２，３，４，０（５で割り切れる）の５つのグループに分かれる。
 今回は、この「剰余類」を取りあげ、「群論」の話に触れる。

●１．素数は貴重！素数２，３，５だけ取り上げる話をする。
６を因数分解すると、
　　1, 2, 3, 4, 6
が因子になる。この中で、６と最小公倍数が同じもの、つまり
２と３と６を除くと、１と５だけが残る。この１と５を「既約剰余類」と呼ぶ。
つまり、「素数」と１だけ残る。（１は約数が１つなので、素数ではない。）

それに対して、５を因数分解すると、
　　1, 5
になる。「素数」と１だけになる。なぜかというと、５が「素数」だからだ！

素数のすごさが分かる。

●２．既約剰余類
この商の６や５をｎと置く。
ｎと互いに素であるものを選び、群にする
（Ｚ／ｎＺ）＊
この＊は、因数が入ってないことを意味する。
ｎに６を入れると、１と６だけ（「既約剰余類」だけ）選んでくれる。
（２，３，４は＊マークが、省いてくれる。）

剰余類には、割り切れる、つまり余り０のグループがある。しかし、０のグループは
省きたいので、以下の表現をする。
　　Ｚ/5Z-{0}

「演算表」に、＋に関して、または×に関してを左上に表記する。
「演算表」で、行（縦）と列（横）の交差するところに、１で割り切れるグループを探す。この行と列のお互いを、「逆行列」の関係という。例えば、５で割った余りが２のグループは、余りが４のグループの逆元である。

●３　互いに素
　kx+ny=1
の例題を説く。高校の数学Ｂの問題。
この問題は、「剰余類」の「逆元」と関連する良問である。解き方は割愛する。

●４　（Ｚ／ｎＺ）＊　は巡回群である。

巡回群は、ｎが素数だとありがたい。

(Z/pz)*は、位数p-1の巡回群に同型である。
(Z/pZ)* と Z/(p-1)Z　は同型である。

この同型を探す数学が、「群論」である。
たとえば、カレンダーは７日すると、また日曜日になります。
この「同型」は、３６５を７で割った余りのグループ（これが曜日になっている）
ですね。一見違うものをじっくりみて、同じ性質を探すのが、群論です。
その手掛かりが、ｎで割った余りのグループに着目して、そのｎが素数だといろいろありがたいことが起きるのです！

参考文献）
「ガロア理論の頂を踏む」
石井敏全　著　ベレ出版
Ｐ．３３からＰ．８６
pythonでfunctoolsのlru_casheのまねごとをした

# こんな感じで作った
```python:my_cashe.py
def my_lru_cache(func):
    precomputed = dict()
    def wrapper(*args, **kwargs):
        tmp = (args,tuple(kwargs.items()))
        if not tmp in precomputed.keys():
            precomputed[tmp] = func(*args, **kwargs)
        return precomputed[tmp]
    return wrapper
```
lruは実装していない
講義の一環で作る機会があったから投稿してみた
ReactでQiitaみたいにマークダウンで書いたものを左にプレビューを表示させる

# はじめに

こんにちは、エンジニアのkeitaMaxです。

ReactでQiitaみたいにマークダウンで書いたものを左にプレビューを表示させようと思います。

# インストール

以下コマンドで`react-markdown`をインストールします。

```
npm install react-markdown
```

また、`remark-gfm`もインストールします。

```
npm install remark-gfm
```

これをインストールするとマークダウンの拡張機能を追加することができます。
```
~~two~~
```

例）上記が以下のように表示されます。

![スクリーンショット 2024-12-18 19.25.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/7571e33b-9da6-4e03-18d9-1de1ca55eb93.png)

# 実装

以下のように実装しました。

```tsx:index.ts
import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

export const AddArticleTest = React.memo(function AddArticleTest() {
    const [markdown, setMarkdown] = useState<string>('');

    return (
        <div className="flex h-screen">
            {/* 左側のエディタ */}
            <div className="w-1/2 p-4">
                <h2 className="text-xl font-bold mb-4">Markdownエディタ</h2>
                <textarea
                    className="w-full h-full p-2 border rounded-md"
                    placeholder="ここにマークダウンを入力してください..."
                    value={markdown}
                    onChange={(e) => setMarkdown(e.target.value)}
                />
            </div>

            {/* 右側のプレビュー */}
            <div className="w-1/2 p-4 border-l overflow-y-auto">
                <h2 className="text-xl font-bold mb-4">プレビュー</h2>
                <div className="prose prose-lg max-w-none">
                    <ReactMarkdown
                        remarkPlugins={[remarkGfm]}
                    >
                        {markdown}
                    </ReactMarkdown>
                </div>
            </div>
        </div>
    );
});

export default AddArticleTest

```



これをStorybookで起動してみると以下のような画面になります。

![スクリーンショット 2024-12-18 19.28.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/32fa7494-da4c-c55f-b0b9-2be6d623b1d7.png)

# 色々してみる

実際にしっかりマークダウンとして認識されるかを確認します。

```
## 見出し2
### 見出し3
#### 見出し4
`インラインコード`
**強調**


| a | b  |  c |  d  |
| - | :- | -: | :-: |
```

上記を入れてみると、

![スクリーンショット 2024-12-18 19.32.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/289ce3c1-3901-a4ee-e4e1-1bf8aef33455.png)

このようにしっかりとプレビュー画面ができていることがわかります。

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://github.com/remarkjs/react-markdown

https://github.com/remarkjs/remark-gfm

# 次の記事

https://qiita.com/keitaMax/items/5bf9416995b6d8abf162
ポートフォリオ作成時メモ　part11 ~PostモデルとMapInfoモデルのリレーション問題

## はじめに
こんにちは、未経験からエンジニア転職を目指しているものです。
オンラインスクールで本格的に学習して7ヶ月目に入りました。
PHP,Laravelを学習しポートフォリオを作成中です。
Postモデルに紐づいているMapInfoモデルのリレーションに悪戦苦闘したため、解決までの内容を整理しました。

## 概要
Laravel Sailを使った開発環境で、Google Maps APIを利用して地図を描画しました。
新規投稿作成画面に無事、地図情報が反映されるようになりましたが、
PostモデルとMapInfoモデルが紐づいた事で、新たな問題が発生しました。

**1. 　投稿した内容が、投稿一覧に反映されず、〇〇のエラーが発生**
**2.　 1.の解決後、投稿編集画面を作成したが、updateが機能しない**

＊2.については別投稿で説明予定






## 投稿した内容が、投稿一覧に反映されず、エラーが発生
ディレクトリ構成としては下記になります
- post.blade.php  : 新規投稿画面
- index.blade.php  :投稿一覧画面

処理の流れは下記になります。
- post.blade.phpでform内容を投稿　
- PostControllerのstoreメソッドが機能
- データベースに保存
- PostControllerのindexメソッドが機能　
- index.blade.phpへ遷移し正しく表示される

しかし、投稿ボタンをクリックしたら添付のエラーが発生してしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846051/54656601-1fac-4020-789c-ec73d912e37e.png)


## 原因の特定に向けた検証 part1
データベースには確かに投稿の内容が保存されていることを確認
PgAdminのクエリツールで以下を実施し確認
```bash
SELECT * FLOM posts;
SELECT * FLOM map_infos;
```

→このことから、PostControllerのstoreメソッドは機能している事を確認

## 原因の特定に向けた検証　psrt1
PostControllerのstoreメソッドが機能していないと仮説。

**実行内容：**
PostController.phpのindexメソッド内を return "Post Index is working."; に変更
**結果：**
ブラウザ上に Post Index is working　と表示された(下記の状態)
**考察：**
indexメソッドが機能していない訳ではない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846051/88f00210-9187-d1cd-96df-5a00381e8415.png)

## 原因の特定に向けた検証　psrt2
検証ツールのネットワーク画面で302のエラーと失敗の表示を確認
失敗の表示は何度もされる

**仮説：**
- indexメソッドがデータサーバーからアクセスするときに何かしらのエラーが起きている

→上記と、今回の事象が見られるようになったのが、PostモデルとMapInfoモデルのリレーションが成功しだしてからである事から、モデル部分に重点をおいて再検証を実施

**原因解明：**
- protected $with = ['mapInfo'];をコメントアウトして無効化を実施
- Eager Loading（関連データの自動読み込み）を無効にし、PostモデルをロードするときにMapInfoモデルのデータを自動的に取得させないように変更
- 上記実行後、無事にindex.blade.phpへ遷移し、投稿一覧画面が表示されるように。

## 原因の考察
Postモデルに関連するMapInfoデータが存在しない、もしくは正しく紐づいていない状態でEager Loadingを実行すると、Laravelが関連データを探しに行き、データベースに無駄な負荷がかかる。データが不完全な場合、サーバーがタイムアウトしたり、例外がスローされる可能性がある。
今回のケースでは、map_infosテーブルにある一部のデータがpost_idと正しく紐づいていない（nullの値がある）ことが原因で、Eager Loadingが期待通りに動作していなかったと考えられる。


## まとめ
データベースでリレーションが絡むと、問題が複雑になる。
どの動きの過程で問題が起きているかを、一つずつ洗い出す事が大切である。


最後まで、ご視聴頂きありがとうございます。
DNSの働き

### IPアドレスの切り替えにもDNSは使われる
>もし、会社がWebサーバーを違うIPアドレスのマシンに変更していたら、新しいIPアドレスを伝える必要がある。
　WebサイトをあるIPアドレスから別のアドレスに移動することはあまりないように思われるかもしれないが、実際には負荷分散のために非常に頻繁に起きる。最近の多くのWebサイトは、コンテンツを複数のマシン(多くの場合は、地理的に分散したクラスタ)に配置している。コンテンツを提供している組織としては、クライアントからの通信をあるWebサーバーから別のWebサーバーに"移動”したい場合がある。DNSはこのための最も便利な方法である。

### DNSとは
#### DNSを使う前は
>ファイルhosts.txtがすべてのホストと対応するIPアドレスをリストし、毎夜、すべてのホストがそのファイルを、保持するサイトからとっていた。
#### 階層的な名前づけとその名前づけを実装する分散データベース・システムからなる
>DNSは、階層的な名前づけとその名前づけを実装する分散データベース・システムからなる。DNSは主にホスト名をIPアドレスにマッピングするのに利用されるが、他の目的にも利用できる。DNSは、インターネットのプロトコルの中で最も活発に開発が進んでいるものである。

### DNSは再帰探索を行い任意のIPアドレスを見つける
>DNSは次のように動作する。まず、名前をIPアドレスに変換するために、アプリケーション・プログラムはライブラリを呼び出し、この関数に名前をパラメータとして渡す。このプロセスをスタブ・リゾルバ(stub resolver)と呼ぶ。スタブ・リゾルバは、名前を含んだクエリ(query)をローカルDNSリゾルバ(local DNS resolver)に送信する。ローカルDNSリゾルバは、ローカル再帰リゾルバ(local recursive resolver)または単にローカル・リゾルバ(local resolver)とも呼ばれる。ローカルDNSリゾルバはその後一連のDNSリゾルバに対して再帰探索(recursive lookup)を実行する。ローカル再帰リゾルバは、最終的には、対応するIPアドレスを含むレスポンスをスタブ・リゾルバに返す。クエリ・メッセージとレスポンスメッセージはUDPパケットとして送信される。

### スタブリゾルバからローカルリゾルバからDNSサーバーへクエリを発行して待つ
>通常、スタブリゾルバは、ローカル・リゾルバに対して再起的なクエリを発行し、ローカル・リゾルバからのレスポンスを単に待つ。一方、ローカル・リゾルバは名前階層の各部分について、それぞれのDNSサーバーに一連のクエリを発行する。階層構造の特定の部分を担当するDNSサーバーは、そのドメインの権威サーバー(authoritative name server)と呼ばれる。

https://bookplus.nikkei.com/atcl/catalog/23/03/16/00728/
QRコードを3Dプリントしてみよう

# QRコードを3Dプリントする

![1000007052.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991231/ad012410-2186-4d0e-e814-bc9234aba9b9.jpeg)



## はじめに
QRコードはいろんなところで活用されていますが、自分のプロフィールなどをQRコードにして相手に読み取ってもらう機会も少なくないかと思います。
そういう場面では紙媒体に印刷されていることが多いかと思うのですが、3Dプリンタを使って立体的に印刷されていると読み取る側も読み取ってもらう側もちょっとだけ気分が上がっていいのではないかと思い、その作成手順についてメモを残しておこうと思います。

## サマリ
おおまかな手順は２つ

    1. 任意のQRコードをSVGファイルに変換する
    
    2. SVGファイルからSTLファイルを作成する（CADソフトに読み込んで作成)

:::note info
CADソフトをお持ちでない場合は、QRコードを直接STLファイルに変換してしまうのもいいでしょう。直接STLファイルを生成してくれる無料webサービスがいくつかありますので、そちらを利用すると手っ取り早いかと思います。ただし3Dモデルの細かな調整はできません。
:::

## QRコード/SVGファイルの準備
QRコード作成自体は比較的簡単なので既に画像ファイルとしてお持ちかもしれません。ただその画像ファイルがSVGファイルへうまく変換できるとは限らない点に留意しておいたほうがいいでしょう。

私自身はQRコード自体の図形にこだわりがありませんので、以下のサイトでQRコード生成し、そのままSVGファイルをダウンロードしています。QRコード作成サイトによっては、QRコード画像のオプション（訂正強度や形状、枠線など）が選べたりしますので、お好みで選んでください。
https://genqrcode.com/

![GenQRCode_-_The_Free_STL_QR_Code_Generator_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991231/c4532ffb-d911-5f79-b71a-b0edaf03bea3.png)

:::note info
上記の画像ではQRコードにテキストを指定していますが、URL等を指定することもできます。
:::

## CADツールでSVGファイルを読み込み、編集する
私はCADツールに Fusion360 を利用しています。Fusion360では作成したSVGファイルをスケッチに読み込ませることができるので、読み込ませたQRコードのスケッチを押し出して3Dモデル化しています。
ちなみにQRコード部分はあまり高さをつけすぎない方がカメラ読み取りしやすいです。（自分は高さ 0.5mm くらいにしています）
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991231/d1fdb086-b8e1-196b-ffb5-02fd845b980d.jpeg">
土台となるベース部分は 2mm の厚さにしています。

3Dモデルが完成したらSTLファイルを出力し、スライサーソフトを経て3Dプリントで印刷してください。


## スマホカメラで読み取りやすくするために
QRコードを3Dプリントする場合、QRコード部分を濃色にしておくとカメラでの読み取りが楽になります。3Dプリント自体の出力で下地の色とQRコードの色とを分けるには、3Dプリンタで多色印刷をします。多色印刷の手順については、利用する3Dプリンタによってさまざまなので本記事では割愛します。PLAフィラメントで単色印刷した場合は、黒の油性ペンで直接塗ってしまうのも手っ取り早いです。
<img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991231/8a99c9e7-b4b1-044e-5321-da3a58bc7a9a.jpeg">
（雑にサインペンで塗りましたが、スマホカメラで読み取りは出来ています^^;）




## CADソフトを使わずに作りたい方へ
QRコードのSTLファイルは次のようなサイトで直接作成できます。　（実は同じサイト）
他にも直接STLファイル生成できるサイトはありますので、検索して試して比較してみるのもいいかもしれません。
https://genqrcode.com/generator/stl

## おわりに
意外と簡単に作れますので、ぜひいろんなQRコードを物理印刷して活躍させてみてください。
もし他にもっと良さそうな手順をご存知でしたら、ぜひ教えて下さい！

ありがとうございました。
elixirの束縛について

```elixir
1.
a = 1

2.
1 = a

3.
2 = a
 (MatchError) no match of right hand side value: 1
    (stdlib 6.1.2) erl_eval.erl:652: :erl_eval.expr/6
    iex:3: (file)
```

3.においては2と1.で束縛されたaの値である1が＝でつながれてしまっているためエラーが出力されている。
表現すると3.は2 = 1となっている。
束縛は左辺に対して行われるため2 = aの式においてaの値が新規に束縛されるわけではない。



参考資料
プログラミングElixir 第2版