OmniAICreator/Qiita-1.07M huggingface dataset:
空間図形「21年 東京薬大 薬 2(1)」をsympyとFreeCADでやってみた。

...3点A(−1,2,2),B(1,4,2),C(0,4,3) ともう1点P ....
オリジナル

https://kamelink.com/blog/2022/12/12/6-6-21-tokyoyakudai-yaku-2-1/


上と同じです。大学入試数学問題集成＞
未登録


# sympyで(オリジナルのやり方)
勉強中

# sympyで(sympy的?安易なやり方)
10行でした。

```python
from sympy import *
var('x y')
O,A,B,C=map(Point,([0,0,0],[-1,2,2],[1,4,2],[0,4,3]))
P=(A-O)+x*(B-A)+y*(C-A)
OPAB=Eq((P-O).dot(B-A),0).simplify()
print("#(1)",OPAB)
OPAC=Eq((P-O).dot(C-A),0)
ans=solve([OPAB,OPAC],[x,y])
print("#(2)",ans)
print("#(3)",O.distance(P).subs({x:ans[x],y:ans[y]}))
#(1) Eq(4*x + 3*y, -1)
#(2) {x: 3/2, y: -7/3}
#(3) sqrt(3)/3
```
以下の、on line sympyで、上記のソースコードを貼り付けて実行できました。私の環境は,pycharmです。　

https://live.sympy.org/

# FreeCADのマクロで
マクロからsympyを使っています。
？点Pが△ABC平面上に見えません。？
FreeCADのDatumPlaneの使い方を教えて下さい。
![png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/72486965-20a2-b5e9-00c4-a61c4509a1d1.png)

```python
import FreeCAD
import Part
import Draft
import Mesh
#########################################################################################################
from sympy import *
var('x y')
O,A,B,C=map(Point,([0,0,0],[-1,2,2],[1,4,2],[0,4,3]))
P=(A-O)+x*(B-A)+y*(C-A)
OPAB=Eq((P-O).dot(B-A),0).simplify()
print("#(1)",OPAB)
OPAC=Eq((P-O).dot(C-A),0)
ans=solve([OPAB,OPAC],[x,y])
print("#(2)",ans)
print("#(3)",O.distance(P).subs({x:ans[x],y:ans[y]}))
#########################################################################################################
P=P.subs({x:ans[x],y:ans[y]})
#########################################################################################################
# 3D作図
def myXYZ2Txt(A):
    return '(' + str(A.x) + ',' + str(A.y) + ',' + str(A.z) + ')'
def myTxtXYZ(A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)
    P5z=float(A.z)
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = '0.2 mm'
    return
def myTxtXYZ_S(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt(xy_tx[2*i-2]) )
    return
def myLine(A,B):
    Ax,Ay,Az=float(A.x),float(A.y),float(A.z)
    Bx,By,Bz=float(B.x),float(B.y),float(B.z)
    pl = FreeCAD.Placement()
    pl.Rotation.Q = (0.4247081540122249, 0.17592004639554645, 0.33985110062924484, 0.8204732460821097)
    pl.Base = FreeCAD.Vector(-3.9166066876399563, -2.1670824762243774, 1.7495260956243028)
    points = [FreeCAD.Vector(Ax,Ay,Az), FreeCAD.Vector(Bx,By,Bz)]
    line = Draft.make_wire(points, placement=pl, closed=False, face=True, support=None)
    Draft.autogroup(line)
    return
def myLine_S(*args):
    for i in range(1,len(args)):
        myLine(args[i-1],args[i])
    return
myTxtXYZ_S(O,"O",A,"A",B,"B",C,"C",P,"P")
myLine    (A,B)
myLine    (A,C)
myLine_S  (O,P,A)
doc = App.activeDocument()
App.ActiveDocument.addObject("App::Origin", "Origin")
App.ActiveDocument.getObject('Origin').Visibility = True
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")
```
p5.jsでランダムな大きさのハートの図形でデザインを作ってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165847/e1db50dd-778c-c448-f00e-fc248ee967a0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165847/c1437f63-6402-31da-cce6-30bdd1c222d3.png)

```javascript
const TIMES = 20;
let w = 400;
let h = 1.618 * w;

function setup() {
  createCanvas(w, h);
  background(255);
}

function heart(x, y, size) {
  beginShape();     //ハート描画開始
  vertex(x, y);     //頂点座標
  bezierVertex(x - size / 2, y - size / 2, x - size, y + size / 3, x, y + size);  //ベジェ曲線 描画
  bezierVertex(x + size, y + size / 3, x + size / 2, y - size / 2, x, y);  //ベジェ曲線 描画
  endShape(CLOSE);  //ハート描画終了
}

function mousePressed() {
  for (let t = 0; t < TIMES; t++) {
    stroke(random(255), random(255),255,random(255));
    noFill();
    strokeWeight(random([1, 2,4,8]));
    heart(random(0,w), random(0,h), random(5,100));
  }
}
```

ハートではなく四角、円、バツを組み合わせてデザイン。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165847/4a2c7bba-cc6a-cb00-0bf2-1b82598ecd1c.png)

```javascript
const TIMES = 10;
let w = 600;
let h = 1.618 * w;

function setup() {
  createCanvas(w, h);
  background(255);
}

function mousePressed() {
  for (let t = 0; t < TIMES; t++) {
    let offset = random(10);
    let x = random(-offset, width + offset);
    let y = random(-offset, height + offset);

    stroke(random(255), random(255), 255, random(255));

    noFill();
    ellipse(random(0, w), random(0, h), random(0, 50));
    rect(random(0, w), random(0, h), random(0, 50),random(0, 50));

    strokeWeight(random([1, 2]));
    line(x - offset, y - offset, x + offset, y + offset);

    strokeWeight(random([1, 2]));
    line(x - offset, y + offset, x + offset, y - offset);
  }
}
```
ReactのカスタムフックでAPIから非同期で値を取得する


## はじめに

カスタムフックからAPIを呼び出す実装の際、つまずきポイントがいくつかあり大変だったので、忘れないように備忘録を残しましす。

### 前提条件

- React:18.2.0
- HackerNewsのAPIを使用
    - https://hn.algolia.com/api

## 早速コード

```jsx:useNews(カスタムフック)

import { useState, useEffect } from "react";
import { Article } from "../types";

export const useNews = (
  url: string
): {
  articles: Article[];
  isLoading: boolean;
} => {
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [articles, setArticles] = useState<Article[]>([]);

  useEffect(() => {
    const fetchNews = async () => {
      try {
        const res = await fetch(url);
        const data = await res.json();

        setArticles(data.hits);
        setIsLoading(false);
      } catch (error) {
        setIsLoading(false);
      }
    };
    fetchNews();
  }, [url]);

  return {
    articles: articles,
    isLoading: isLoading,
  };
};

```


```jsx:(呼び出し側)
import { useNews } from "../api/getNews";

export default function En() {
  const url = `https://hn.algolia.com/api/v1/search?query=programing`;
  const { articles, isLoading } = useNews(url);
  if (isLoading) {
    return <div>ローディング中</div>;
  }
  return (
    <div>
        {/* articlesを使ったなにか */}
    </div>
  );
}

```


## つまずきポイント１

APIをasync/awaitで呼び出したいけど、カスタムフック`useNews`は同期的に呼びたい

```jsx:(呼び出し側)
// useNewsにasyncを使えない
const { articles, isLoading } = useNews(url);
```

↓

カスタムフック内のuseEffectでasync/awaitを使う

```jsx
useEffect(() => {
    // useEffect「内」でAPI取得関数を定義する
    const fetchNews = async () => {
      try {
        const res = await fetch(url);
        const data = await res.json();

        setArticles(data.hits);
        setIsLoading(false);
      } catch (error) {
        setIsLoading(false);
      }
    };
    // useEffect「内」でAPI取得関数を呼ぶ
    fetchNews();
  }, [url]);
```

## つまずきポイント２

カスタムフックを更新できない

↓

useEffectの配列に更新されるstateを入れる


```jsx
useEffect(() => {
    // 略
  }, [url]);//urlが更新したらカスタムフックが走る
```

## まとめ

カスタムフックを再試行したいときはuseEffectを使おう


## 参考
https://zenn.dev/syu/articles/b97fb155137d1f
FPGAプログラミング大全Xilinx編第2版 Vitisインストール #12

FPGAに再入門しようと思いたち[FPGAプログラミング大全Xilinx編第2版](https://www.amazon.co.jp/FPGA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%A4%A7%E5%85%A8-Xilinx%E7%B7%A8-%E7%AC%AC2%E7%89%88-%E5%B0%8F%E6%9E%97-%E5%84%AA/dp/4798063266/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1S5G3UKPB55O9&keywords=FPGA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%A4%A7%E5%85%A8Xilinx%E7%B7%A8%E7%AC%AC2%E7%89%88&qid=1669893715&qu=eyJxc2MiOiIwLjc2IiwicXNhIjoiMC4wMCIsInFzcCI6IjAuMDAifQ%3D%3D&sprefix=fpga%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%A4%A7%E5%85%A8xilinx%E7%B7%A8%E7%AC%AC2%E7%89%88%2Caps%2C151&sr=8-1)を頭からやっていく12日目

時期的にも良いので一人Advent Calendarで25日続ける

最終的に作ったCPUを使えるようにFPGAプログラミング大全Xilinx編第2版第6章をやってCPU+FPGAシステムに慣れる

### 25日終了時の目標
4004等の実CPUの実装

### 目次
| # | タイトル |
|:-:|:-:|
|   01|  [ツール導入](https://qiita.com/Gazyu/items/8f3797abf4ddc88ecacd) |
|  02 |  [実機テスト下準備](https://qiita.com/Gazyu/items/b59e0a1e023005bc02d5) |
|  03 |  [実機テスト](https://qiita.com/Gazyu/items/23ec4da6c241d95bfa8e) |
|04|[クロック利用](https://qiita.com/Gazyu/items/a653fe87023323f308de)|
|05|[シミュレーション検証](https://qiita.com/Gazyu/items/508370018465c164120b)|
|06|[TD4](https://qiita.com/Gazyu/items/08377deaa0413dd111cb)|
|07|[TD4とりあえず実装](https://qiita.com/Gazyu/items/721967444237a72f04e9)|
|07|[TD4メモリ実装](https://qiita.com/Gazyu/items/f18e19b48becbead6dd8)|
|09|TD4完成|
|10|第6章1|
|11|第6章1-2|
|12|Vitisインストール|
|13|未定|

### 環境
【実装ボード】 [Digilent Artix-7 35T Arty FPGA 評価キット](https://japan.xilinx.com/products/boards-and-kits/arty.html#resources)
【OS】 Windows10
【IDE】 Vivado 2022.2

### 今日のゴール
Vitisインストール

### Vitisのインストール
第6章2を行うためにはVitisが必要だったのでインストールする。
ただ、追加インストールができないので一度Vivadoをアンインストールして再インストールとなる。

インストール手順はVivadoのときとほぼ変わらず

ただ、最小構成にしたのにDLサイズ63G、必要ディスク容量180G超えという洒落にならない容量なので時間のあるときにやるべき
![スクリーンショット 2022-12-12 214517.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45441/4a6cbdf4-a052-a8ca-67de-83a927a4174b.png)



今日はここまで
研修をふりかえろう ~受講報告を楽しもう~

[ふりかえり Advent Calendar 2022](https://adventar.org/calendars/8001) の 12日目の記事です。

## この記事について

会社で外部研修に行った時に
「研修受講報告書を書きなさい」みたいな話、出たことありませんか？  
「報告書、書くの嫌だな」とか、「報告書があるから受講やめようかな」っていう声もちらほら聞きます。

この記事では、こういった研修後の活動に前向きに取り組んでいくためのお話をします。  

端的にいうと、伝えたいことは以下です。
- 自分にとって求めてる形で、研修をふりかえろう。
- やり方にとらわれない。自分にとって一番効果のある方法を考えよう。

「研修のふりかえり」に、前向きに取り組めますように。

## そもそも受講報告って、何のため？

いろんな目的が出てくると思います。パッと思いついたものを挙げてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286147/613466ed-17be-9417-529c-e14bf240d30e.png)

### 受講報告から得られそうなこと

個人の理解を深めるのであれば、以下のような効果があります。
- 受講後に学んだことを整理することで、学習を定着させられる。
- 受講後に改めて実務に照らして考え、理解を深めることができる。
- 研修から得たプラクティスで、明日からできることを選ぶ。

「報告会」の場があるなら、以下のような効果を狙ってみるのも良いです。
- 実践してみたいプラクティスを選んで紹介し、一緒に始める仲間を探す。
- 研修の魅力を伝えて次回受講に誘導し、同じ経験を持った人を増やす。

### 受講報告に時々ある幻想

残念ながら、最近雑談していても以下の幻想を持っている方もいます。
研修内容にもよりますが、難しいことの方が多いのではないかと思います。
- 研修報告をしてもらって、組織全員に研修を受けたのと同等の知識をつけさせたい。(組織の意思)
- フォーマット通りに報告することが研修の一部。 (組織の慣例としてのものをそのまま受け止めてる)


## テキスト報告以外に、こんなやり方やってみよう。

サンプルケースで、たとえばこんな受講報告もありますというのを挙げてみます。  
「自分の目的にあった形」ということで、型にとらわれない例としてご参照いただければと思います。

[サンプルケースとなる研修]
- TDDBC の 動画を見て、チームで 実際に Fizz Buzz を TDD で作る。
    - TDDBC 動画: https://www.youtube.com/watch?v=Q-FJ3XmFlT8

※ 題材は、単に内容をイメージできそうな人が多いので選んでます。

### Small Starfish でやりたいことを出す

研修から「次に活かしたいこと」を書く方式。  
Small Starfish は 「More(もっとやりたい)」「Less(減らしていこう)」「Keep(引き続きやろう)」を
書いていくふりかえり手法です。

冒頭に箇条書きで簡単に概要を挙げた上で、自分に活かせそうなことを書き出してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286147/82d50574-50b3-451a-57af-c3768f54abeb.png)


### グラレコ!

「絵心が！」と敬遠されがちですが、文字だらけになっても意外とそれなりにできたりします。  
(絵を描いてみてますが、文字だけで「グラレコ？」と思いながら作ることもあります)

キーボードにタイプするよりペンで描くことで覚えられる点、後から見た時情報が入りやすい点がおすすめです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286147/caf07e96-0a2f-c9a9-738e-0e82224f0cb3.png)

### 1文字で表現!

字の心得はないのですが、トライしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286147/f82cccd0-6a8b-0712-cfc5-7ffdf7994a32.png)

練、を選んだのは以下の気持ちです。
- TDD は、まずは TODO を作る練度が必要。これは練習！
- 怠けず、RedとGreen を 繰り返し続ける練度が必要。
- 小さく、コードを鍛錬していく！ 飛び級狙わない。Red, Green を繰り返す。 <-- 鍛錬の錬　は 練 じゃなかった...

「繰り返す！」感を出すために、払いとか止めとか、若干「円(ループする)」っぽくしようとしてみました。  
...伝わらないかもですが、そういった気持ちを込めて書けるのが大事だと思います。

## さいごに

「めんどくさいなー」と言われがちな受講報告を、
「どう報告したら、自分に一番得だろう？」という考えにシフトすると、受講報告も楽しめます。

こうした形でなくとも、3行感想でも、動物に例えるでも、得るものがあればなんでも良いと思います。

受講報告が障壁になって「研修やだな」になってる人にとって、この記事が参考にあればと思います。
PagerDuty CLIでscheduleをoverrideする方法

https://github.com/martindstone/pagerduty-cli

を用いてPagerDutyのスケジュールを上書きするやり方の紹介

# 1. インストールする(初回のみ)

```sh
sh -c "$(curl -sL https://raw.githubusercontent.com/martindstone/pagerduty-cli/master/install.sh)"
```

# 2. ログインする(適宜)

```sh
pd login
```

ブラウザが起動してログインできる。SSOも可能。

# 3. overrideする

```sh
pd schedule override add \
  --user_email='your.name@example.com' \
  --name='your-schedule-name' \
  --start='2022-11-23T10:00+09:00' \
  --end='2022-11-23T22:00+09:00'
```

# 4. 確認

```sh
pd schedule override list --name='your-schedule-name'
```

```text
Getting overrides for schedule XXXXXXX 1/1 👍, 0/1 👎... done
ID             Start               End                 User ID User name       
────────────── ─────────────────── ─────────────────── ─────── ─────────────── 
xxxxxxxxxxxxxx 2022/11/23 10:00:00 2022/11/23 22:00:00 XXXXXXX Your Name
xxxxxxxxxxxxxx 2022/12/01 10:00:00 2022/12/01 22:00:00 XXXXXXX Your Name
```

# おわりに

- もともとTerraformでやりたいと思って調べたが、出来なさそうだったのでCLIで妥協した
  - https://registry.terraform.io/providers/PagerDuty/pagerduty/latest/docs
- 複数のスケジュールをまとめて上書きする場合は便利そう
【個人開発】大人の盛り付けcom：盛り付け画像からレシピを探せるサービスを作成しました【暇つぶしWEBアプリ】

# はじめに

こんにちは、
突然ですが、料理って見た目が綺麗だとものすごくテンション上がりませんか。

コロナの影響で家で料理をする機会が増えましたが、
少しの手間をかけてお皿に盛り付けすると目も心も充実します。（イメージ図）

![25030951_s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2866856/ac205876-60b2-a7eb-ecfe-f8cb09df70b9.jpeg)


一方、美味しくても、フライパンからそのままの状態で食べてもいまいち気持ちが盛り上がらないと感じます。（イメージ図）

![25199126_s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2866856/0e84b93e-835d-938b-3d03-d863ef8a3905.jpeg)


### つまり、盛り付けって超大事！！！！！！




そこで、盛り付け画像からレシピを逆算して探せるWEBサイトを個人開発しました。

https://moritsukecom.herokuapp.com/rank/top/




# サービス生み出しの背景

家で料理をすることが増えたが、盛り付けが下手すぎて友人に見せられないと悩んだ作者が、
盛り付けを勉強しつつ料理も学べるサイトを作りたかったため。


# サービス概要

https://moritsukecom.herokuapp.com/rank/top/

![moritsukecomtoppage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2866856/4f3f6dc8-a850-216b-adb5-ec7c8cc5b872.png)


みなさんが投稿した盛り付け画像がTOPPAGEに表示されます。
画像をクリックすると、詳細ページに飛び、さらにクリックするとレシピサイトに飛びます。
レシピサイトだと自分のレシピを記載する必要がありますが、このサイトだと記載する必要はありません。
クラシルでも、クックパッドでも参考になったレシピのURLを登録時に入力するだけ！
※画像はオリジナルのものでお願いします。

![moritsukecommenupage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2866856/f45987d6-dbc4-9cff-79fc-af2d5809d3c4.png)



# 使用技術について

エンジニアスクールで教えてもらっていたDjangoで作成をしました。

＊viewsの文法などは結局初心に戻って入門ブログを参考にしました
https://tutorial.djangogirls.org/ja/django_templates/


https://qiita.com/kaki_k/items/6e17597804437ef170ae

TOPPAGEの画像はピンタレスト風がいいなぁと思って探していた時に
CSSのgrid機能を発見！！！参考にさせていただきました🙏

https://tetsudoulab.com/gazou-2jigen-css/



# 追加の要望

https://blueniport.herokuapp.com/top/


ポートフォリオのお問合せフォームから追加の要望やバグについてなどいただけたら嬉しいです。
よろしくお願いいたします。
ツイッターのDMもOKです。

https://twitter.com/blue_no_uniuni



# 終わりに

今回は前回は医療系のpubmedtransリリースしましたが、
今回は日常でも多くの方が使いやすい【大人の盛り付けcom】をリリースさせていただきました🙏

まだまだプログラミング初心者で至らない点が多いですが、先輩の皆様方にアドバイスやご指導いただけたら幸いです。
Next.js JWT Tokenの保存方法

# 認証のセキュリティについて
localstrage,cookie,インメモリ、Auth0がある。
それぞれメリットデメリットがある。
localstrageは比較的実装が簡単だが、容易に盗むことができる。

https://logmi.jp/tech/articles/324349

# 個人アプリ開発で実施したこと

 NextAuthを実装するか検討したが、実装に時間がかかりそうだったので、localStrageに保存することにした。

# jwt認証

https://zenn.dev/ayumukob/articles/640cbf4a1ff3ed

https://qiita.com/h_tyokinuhata/items/ab8e0337085997be04b1

https://qiita.com/hirohero/items/8199cda2fada7432887e
[小ネタ]スプレッドシートのデータからSQLを泥臭く作るときにRubyを使ってみる

# まえおき

データメンテなどでスプレッドシートをもとにデータメンテ用のSQLを作る場合があります。
その場合元となるスプレッドシートからデータメンテ用のSQLを作ろうとしても、 `スプレッドシート力（≒エクセル力）` が足りずに余計に時間がかかるぅぅぅRubyだったら速攻なのにぃぃぃ…となってしまう、そんな私向けの記事です。

# 作るもの

たとえば、ユーザ毎にメールアドレスがあるシステムで、データメンテで削除するメールアドレスIDを👇のようなスプレッドシートでもらったとしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144344/15fde2ad-ecd4-4050-31f3-f10770862fc1.png)

そこから以下のようなある程度行数の多いデータメンテ用のSQLを作りたいとします。

```sql
--
-- UserID: 100
--

-- 事前確認
select count(*) from emails
where id in (1,2)
  and deleted_at is not null;

-- 更新確認
update emails set deleted_at = now()
where user_id = 100
  and id in (1,2)

  -- 事後確認
select count(*) from users
where id in (1,2)
  and deleted_at is not null;

...次はUeriD: 101で繰り返す...

```

今回の例であればスプレッドシートだけでやるのもそれほど難しくないかもですが、これ以上複雑になると心が折れるのでこういうものはRubyでやりましょう。

# やりかたとコード

めっちゃ単純です。以下のように元データをクリップボードにコピーして…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144344/b0b231a3-f3ba-2147-9b52-7210d9ede026.png)

ただただCSV.newのデータのところに張り付けるだけ。なお、エディタや環境によって列のseparatorが異なるかおしれませんのでうまくいかない場合はcol_sepは環境に合わせて修正してください。ちなみに私が試したWindows11, Chrome+VSC環境だと、タブ区切りでセットされました。

```ruby: コード
require 'erb'
require 'csv'

# スプレッドシートからコピペでデータセットできるように調整する
csv = CSV.new(<<~'CSV', headers: true, header_converters: :symbol, col_sep: "\t")
user_id	email_id
100	1
100	2
101	1
102	1
102	2
102	3
CSV

# 扱いやすいデータ形式に変換
email_ids_by_user_id = csv.group_by { |r| r[:user_id] }
                          .map { |user_id, rows| [user_id, rows.map { |r| r[:email_id] }] }

puts ERB.new(DATA.read).result(binding)
__END__
<% email_ids_by_user_id.each do |user_id, email_ids| %>
--
-- UserID: <%= user_id %>
--
  
-- 事前確認
select count(*) from emails
where id in (<%= email_ids.join(',') %>)
  and deleted_at is not null;

-- 更新確認
update emails set deleted_at = now()
where user_id = <%= user_id %>
  and id in (<%= email_ids.join(',') %>)

  -- 事後確認
select count(*) from users 
where id in (<%= email_ids.join(',') %>)
  and deleted_at is not null;

<% end %>
```

コード的にはシンプルで特筆すべきところは、[DATA定数](https://techracho.bpsinc.jp/hachi8833/2018_06_28/58397)を使って1ファイルで実装しているところくらいでしょうか。でも、スプレッドシートの関数をこねくり回すより、Ruby脳の方のほうが早い方には参考にはなるのかも？

なお、このコードで使っている**DATA定数はirbではつかえない**ので、面倒でもファイルに書き出して実行してください。

実行すれば以下のようなSQLを出力してくれます。

```sql: 実行結果
--
-- UserID: 100
--

-- 事前確認
select count(*) from emails
where id in (1,2)
  and deleted_at is not null;

-- 更新確認
update emails set deleted_at = now()
where user_id = 100
  and id in (1,2)

  -- 事後確認
select count(*) from users
where id in (1,2)
  and deleted_at is not null;


--
-- UserID: 101
--

-- 事前確認
select count(*) from emails
where id in (1)
  and deleted_at is not null;

-- 更新確認
update emails set deleted_at = now()
where user_id = 101
  and id in (1)

  -- 事後確認
select count(*) from users
where id in (1)
  and deleted_at is not null;


--
-- UserID: 102
--

-- 事前確認
select count(*) from emails
where id in (1,2,3)
  and deleted_at is not null;

-- 更新確認
update emails set deleted_at = now()
where user_id = 102
  and id in (1,2,3)

  -- 事後確認
select count(*) from users
where id in (1,2,3)
  and deleted_at is not null;

```

おしまい。スプレッドシート難しすぎるんじゃー
エフェクトが出る向きを調整する（Effekseer）

VCIにEffekseerでエフェクトをつけた時、エフェクトの飛んでく向きが意図した方向にならなくて困ったことがありませんか。私はありました。総当たり的自己流なのでもっと適切な方法があるかもしれません。

# この記事は、こんな人向けに書いています
- Effekseerでエフェクトがいじれる
- Unityを使って自分でVCIを出力できる

# 最初に確認すること
まず最初に確認することは、「１人称視点でそう見えてるだけではないか」ということです。
自分から見て手前から奥に飛んでくエフェクトは倒れて見えます（描画の都合上？）。
一度落ち着いて、他の視点から確認してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935496/7414d74b-4373-d910-c563-d966bbdae73e.png)
一人称視点の見え方（赤っぽい稲妻がエフェクト。本来は自分から見て手前から奥に出て欲しいのに９０度手前に倒れてるように見える）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935496/3e5aafe4-9927-6b7c-6ec3-04cbc4d27ad2.png)
横から見るとちゃんと出てる

# Unityでエフェクトの向きを変える方法
1. Unityでエフェクトの入っているオブジェクトの向き（Rotation）を変えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935496/f4e93986-fe57-5aaf-abb8-79d4bf0b33de.png)
以上。

# Effekseerでエフェクトの向きを変える方法
1. Effekseerの回転させたいエフェクトのなるべく上の階層を選択します（画像ではTestを選択）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935496/4f247a0a-d6ea-b39b-f5eb-456321d5dabe.png)
1. 「回転」タブを選択し、角度（度）に適切な角度を入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935496/1087500f-fe34-58c4-0d8e-159361d304c1.png)
1. もしこれでエフェクトの向きが変わらなかった場合、もっと下の階層の角度を変えてやると変わることがあります（画像だとExpanderというエフェクトの最下層を選択）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935496/20f878b5-d667-f358-744c-1740196f0c9e.png)

以上。
Content Moderationでコンテンツチェック

Alibaba Cloudには、画像や動画、テキストといったコンテンツに対してモデレートするサービスとして、**Content Moderation**があります。

# Content Moderationとは
画像や動画、テキストなどのマルチメディアオブジェクトコンテンツに含まれる内容が、公序良俗に反するものかどうかリスクを即座に検出します。
この検出については、Alibaba Cloudだけでなく、Taobao、Alipayなどで蓄積されたセキュリティテクノロジーと経験に基づいて提供されています。

## 検出される内容
APIを利用して以下の内容が検出されます。

* 画像
    * ポルノコンテンツ
    * テロリストのコンテンツ
    * 広告違反
    * QRコード
    * 望ましくないシーン
        * 画像にコンテンツが無い
        * ピクチャーinピクチャー
        * 喫煙
        * 運転中のライブ配信など
    * ロゴ
* ビデオ
    * ポルノコンテンツ
    * テロリストのコンテンツ
    * 広告違反
    * 望ましくないシーン
        * 黒画面
        * 白画面など
    * ロゴ
    * 音声違反
* テキストスパム対策
    * 広告
    * テロリストのコンテンツ
    * 乱用
    * ポルノコンテンツ
    * スパム
    * 無意味な内容
    * 禁止されているコンテンツ
    * 望ましくないシーン
        * 拝金主義
        * 富の誇示
        * 偶像崇拝
        * 破壊的感情
        * 否定的な誘惑に関連するコンテンツなど
    * カスタム用語

# 料金
料金は従量課金制です。
最初にContent Moderationのサービスを有効にする必要があります。
画像、動画、テキストのそれぞれの課金情報は[こちら](https://www.alibabacloud.com/ja/product/content-moderation/pricing)。
リージョンは、Asia Pacific SE1(Singapore)とChina East2(Shanghai)の２つです。
また、画像や動画の中でもアダルトコンテンツ、暴力やテロリストのコンテンツ、OCR(画像のみ)、ロゴといったカテゴリで料金が分かれているので注意が必要です。

# SDK
Content ModerationのAPIを呼び出すために、SDKが用意されています。
注意点として、SDKではポルノ検出、テロリストコンテンツ検出、OCR、ロゴ検出などの画像モデレーション機能は1つのAPIにカプセル化されています。

## SDK対応言語
Alibaba Cloudの公式としてSDKが用意されている言語は下記の5つです。
* Java
    * Java 1.6以降
* Pyhton
    * Python2.xまたはPython3.x
* PHP
    * PHP5.5以降
* Go
    * Go 1.10.0以降
* .NET
    * .NET Framework 4.5以降または.NET Standars2.0以降
    * C# 4.0以降
SDKのサンプルコードや事前準備に利用するコマンドなど、ドキュメントに記載があるので利用開始は難しくないかと思います。
(対応言語のバージョンの古さは気になりますが・・・)

サードパーティー製のSDKとしてC#、C++、Node.js、Go、Python3.5があるとのこと。
どの様な内容か時間があるときにでもSDKの内容を確認してみたいと思います。

## パラメータ
APIをコールする際に設定するパラメータですが、共通パラメータ(Commonパラメータ)と各操作固有のパラメータがあります。
共通パラメータの仕様は[こちら](https://www.alibabacloud.com/help/en/content-moderation/latest/common-parameters)。

## エンドポイント
APIのエンドポイントによって、サポートされている機能(操作)が異なります。
内部エンドポイントを利用する場合は、インターネット経由のAPIコールと比較すると時間が短縮されます。
[エンドポイントとサポート一覧](https://www.alibabacloud.com/help/en/content-moderation/latest/endpoints)。

## QPS制限
1秒あたり最大50件のリクエストまで対応可能。
過剰な数のリクエストを送信すると、スロットリングが実装されるので注意が必要です。


# まとめ
日本リージョンでの機能展開はまだの様ですが、サンプルプログラムやSDKなどが用意されているのでコンテンツチェックに利用しやすいのではないかと思います。
Azure PipelinesでAzure Container Appsをデプロイしてみる

先日、Azure PipelinesでAzure Container Appsをデプロイできるタスクがプレビューになったので早速触ってみました。

https://azure.microsoft.com/ja-jp/updates/public-preview-azure-pipelines-task-to-build-and-deploy-to-azure-container-apps/

## Container Appsを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/3959554d-95c1-3d4b-8c3c-7345e5495566.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/50bb9ceb-618d-d362-b4f7-d8c172af23f9.png)
「アプリ設定」はクイックスタート イメージを使うで大丈夫です（後からサンプルアプリケーションをデプロイします）

※今回のサンプルを動かす場合、イングレスのターゲットポートは***3500***に設定する必要があります（Dockerfileに指定あり）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/386b53a1-721f-65d9-9bdb-41a2350e5aad.png)


## ACRを作成
ビルドしたコンテナを管理するためにACRを作成します。

## Azure DevOpsにサンプルリポジトリをインポート
今回は公式のサンプルアプリケーションを利用させてもらいます。

https://github.com/Azure-Samples/containerapps-albumapi-csharp

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/6ff20ae6-d6d5-e82e-b387-a9ffb717df52.png)

## Azure DevOpsプロジェクトにAzure Container Apps タスクをインストールする
Azure Container Apps の Azure Pipelines タスクは、現在プレビュー段階です。 タスクを使用する前に、それを Azure DevOps Marketplace からインストールする必要があります。

https://marketplace.visualstudio.com/items?itemName=microsoft-oryx.AzureContainerAppsRC

「Get it free」からインストールするプロジェクトを選択してすぐにインストールできます。
使い方も上記のマーケットプレイスから確認できます。

## Pipelineを作成
azure-pipelines.ymlをプロジェクトルートに作成し、コミットすればデプロイが実行されます。
```yaml
trigger:
  branches:
    include:
      - main

pool:
  vmImage: ubuntu-latest

steps:
  - task: AzureContainerAppsRC@0
    inputs:
      appSourcePath: '$(Build.SourcesDirectory)/src'
      azureSubscription: '<サブスクリプションのサービスコネクション名>'
      acrName: '<ACR名>'
      containerAppName: 'container-app-demo'
      resourceGroup: '<リソースグループ名>'

```

Pipelinesが成功して、ブラウザでアクセスできたらOK

## ここがすごいよAzure Container Apps タスク
- 今までのApp Serviceなどにコンテナアプリケーションをデプロイする際は、①Dockerビルド、②ACRにpush、③App Serviceにデプロイといった工程をPipelinesに記載しなければならなかったが、タスク一つで完結している
- 今回はDockerfileありのサンプルだったが、なくてもいけるみたい（すごい）
    - > タスクでは、appSourcePath 内の Dockerfile を使用してコンテナー イメージがビルドされます。 Dockerfile が見つからない場合、タスクは、appSourcePath 内のソース コードからコンテナー イメージをビルドすることを試みます。
- 特にACRのリポジトリなどを指定しなくても良しなにしてくれる
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/e72d2f71-3c37-80ea-c54d-bf91347e5b4f.png)
- もちろんタグなどは自分でも指定できる（imageToDeployオプション）

## 参考
https://learn.microsoft.com/ja-jp/azure/container-apps/azure-pipelines
ベジェ曲線で遊ぶ

　
この記事は[アドカレ](https://qiita.com/advent-calendar/2022/lua)に参加しています。

# ベジェ曲線で遊ぶ
　多くのソフトでは曲線を描画するのにベジェ曲線というものが使われたりします。三次関数とか制御点とか、めんどくさい言葉が出てきますが、実装はとても簡単です。

## 理論
　なんとなくでも知っておくと楽しいです。

ベジェ曲線の詳しい原理は以下のサイトなどが参考になります。
[ベジェ曲線](https://ja.javascript.info/bezier-curve)
[一から学ぶベジェ曲線](https://postd.cc/bezier-curves/)

## 実装
以下は4点をもとにベジェ曲線を描画するスクリプトです。
核はOrbitという関数で、t(0~1)に対する(x,y)を返します。
```lua
--[[

ベジェ軌道_M.obj
	単純なベジェ軌道です。

]]

--dialog:座標,pos={};


--アンカー
obj.setanchor("pos",2,"xyz")


--p1~p4に、x2,y2,x3,y3を代入(x1,y1=0,0とx2,y2=1,1のような状態と仮定)
local p1,p2,p3,p4=(pos[1]+50)/100,(-pos[2]+50)/100,(pos[4]+50)/100,(-pos[5]+50)/100


--[[ティムさんの関数
	時間t(0~1)と、x2,y2,x3,y3からx,y座標を求める。]]
local Orbit=function(t,x1,y1,x2,y2)
	local s=1-t
	x1=(3*s*s*x1+(3*s*x2+t)*t)*t
	y1=(3*s*s*y1+(3*s*y2+t)*t)*t
	return x1,y1
end


--背景枠
obj.setoption("drawtarget","tempbuffer",106,106)
obj.load("figure","四角形",0x39352e,106,3)
obj.draw(0,0,0,1,0.7)


--背景
obj.setoption("drawtarget","tempbuffer")
obj.load("figure","四角形",0x373737,100)
obj.draw(0,0,0,1,0.5)


--グラフ
local x,y
for i=0,40 do
  obj.setoption("drawtarget","tempbuffer")
  obj.load("figure","円",0x55a75b,4)
  x,y=Orbit(i/40,p1,p2,p3,p4)
  obj.draw(x*100-50,-y*100+50)
end


--現在位置
x,y=Orbit(obj.time/obj.totaltime,p1,p2,p3,p4)
obj.setoption("drawtarget","tempbuffer")
obj.load("figure","円",0xe0d95a,10)
obj.draw(x*100-50,-y*100+50)


--アンカー１
obj.setoption("drawtarget","tempbuffer")
obj.load("figure","円",0x25aeff,10)
obj.draw(pos[1],pos[2])


--アンカー２
obj.setoption("drawtarget","tempbuffer")
obj.load("figure","円",0x25aeff,10)
obj.draw(pos[4],pos[5])


--仮想バッファをロード
obj.load("tempbuffer")


--[[とりあえず、Bのグローバル変数に流す。
	個人で使うぶんにはこれでよいが、
	スクリプトを配布する際は誰も使わないグローバル変数の名前にする。

	あと、イージングスクリプトは作らないほうがいいかも。
	https://scrapbox.io/ePi5131/【やめてくれ】「イージングを使いやすくするため」に新しくトラックバースクリプトを起こすな

	余談ですが、ベジェ系ではこれ好き
	https://youtu.be/B9qRuz_gBgI		]]

B=y


```

## 実装２
テキストボックスに貼り付けて使います。
xy座標が入った一次元配列a(グロ変)からベジェ曲線を描きます。
```lua
<?
local Orbit=function(t,x1,y1,x2,y2)
    local s=1-t
    x1=(3*s*s*x1+(3*s*x2+t)*t)*t
    y1=(3*s*s*y1+(3*s*y2+t)*t)*t
    return x1,y1
end

local function draw_Line(a,b,c,d)
b[1]=b[1]-a[1]
c[1]=c[1]-a[1]
b[2]=b[2]-a[2]
c[2]=c[2]-a[2]

b[1]=b[1]/(d[1]-a[1])
c[1]=c[1]/(d[1]-a[1])
b[2]=b[2]/(d[2]-a[2])
c[2]=c[2]/(d[2]-a[2])

local n=100--[[精度(てきとうなので、本当は計算して調整したほうがいいみたい]]
for i=0,n do
local x,y
x,y=Orbit(i/n,b[1],b[2],c[1],c[2])
x=x*(d[1]-a[1])+a[1]
y=y*(d[2]-a[2])+a[2]
obj.load("figure","円",0xf9de2f,10)
obj.draw(x,y)
end
end

local p={}
for i=0,#a/2-1 do
p[i+1]={a[i*2+1],a[i*2+2]}
end

local e=#p
local c=1

while 1 do
if(c+3>#p)then break end
draw_Line(p[c],p[c+1],p[c+2],p[c+3])
c=c+3
end
?>
```
※(d[1]-a[1])の結果が0になったとき、0除算になってしまうため正常に描画されません。これを防ぐには[github](https://github.com/metaphysical-bard/M_PosSet_plugin/blob/main/auf/draw.hpp)にあるコードのように0の場合に小さい値(0.001とか)を足して近似的に求めるなどの方法が考えられます。

## おわりに
　なんだか、[discord](https://twitter.com/metaphysicalba1/status/1521523370059173890)にあるコードをそのまま貼り付けただけな気がします。手抜き記事ですね！(全部そう

[twitter](https://twitter.com/metaphysicalba1)
pureなjsでGraphQLのrequestを投げる方法（Lambda@Edgeなど）

Lambda@EdgeからとあるエンドポイントにGraphQLのqueryを実行したい場合がありました。
Lambda@Edgeにはレイヤーをアタッチすることができないので、Lambdaのランタイムに組み込まれている方法でhttpリクエストを飛ばす必要があります。
（正確にはコードとライブラリをまとめたzipが1MB以下に収まるのであれば、そのzipをデプロイすることでサードパーティのNodeライブラリも利用することができるようになりますが、実装時点では調査が足らず不可能だと思っていました。詳しくは下のリンクをご参照ください。）

https://aws.amazon.com/jp/blogs/networking-and-content-delivery/leveraging-external-data-in-lambdaedge/#:~:text=Include%20your%20data%20in%20your%20function%20deployment%20package

今回はとある事情から、ランタイムとして`Node.js`のv16系を利用していました。
Nodeのhttpクライアントライブラリとしては`axios`や`node-fetch`などがよく使われますが、Node16にこれらは組み込まれていません。
**`Node.js`のv18系を使えるなら、fetchがデフォルトで使えるためそちらを使った方が良いでしょう。**

`Node.js`のv16系では唯一`https`のみが組み込みで使えますが、それを利用した場合のGraphQLのquery実行の方法が分かりづらかったので、メモの意味合いも兼ねて記事にしようと思います。


# いきなりコードを共有
エラーハンドリングなどは適当な部分もありますので、参考にする際は適宜処理を追加して下さい。
```js
"use strict";

const https = require("https");

const options = {
  hostname: "hogepiyotest.com", // リクエスト先のホスト名を指定
  path: "/",
  port: 443,
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
};

// 実行したいQuery
const infoQuery = `
query Info($id: ID!) {
  info(id: $id) {
    id
    description
  }
}
`;

const getInfo = (operation, id) => {
  const requestBody = JSON.stringify({
    operationName: operation,
    variables: {
      id: id,
    },
    query: infoQuery,
  });

  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      let body = "";
      res.on("data", (d) => {
        body += d;
      });
      res.on("end", () => {
        console.log(JSON.parse(body).data);
        resolve(JSON.parse(body).data);
      });
    });

    req.on("error", (error) => {
      console.error(error);
      reject(new Error(error));
    });

    req.write(requestBody);
    req.end();
  });
};

exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const path = request.uri;
  // 今回はアクセスされたURLのパスの一番目に、欲しい情報に対応するIDを指定すると仮定
  const pathList = path.split("/");
  const id = pathList[1];

  const fetchedData = await getInfo("info", id);
  // 以下、受け取った内容をご所望の形に整形してください
  ...
};
```


## ざっくり解説
今回のミソは、`https`を使ってGraphQLのリクエストをどのように投げれば良いのか、ということに尽きます。
[こちら](https://stepzen.com/blog/consume-graphql-in-javascript)を参考に実装しましたが、少しだけ解説します。

`getInfo`という関数がGraphQLのリクエストの役割を担っており、その中でPromiseを利用した非同期処理を行います。
Promiseの中にある`https`を使ったリクエストがその非同期処理の正体です。

ここでGraphQLのリクエストについて簡単に説明します。
GraphQLのリクエストで送信できるデータは、`query`、`operationName`、`variables`の3つです。
`query`は必須で、GraphQLクエリを記述します。GraphQLは単一のエンドポイントを介して機能するため、エンドポイントが応答するデータはすべてクエリに依存します。

`variables`はオプションで、クエリに渡される変数の値を含むJSONオブジェクトです。例えば、クエリにidという変数が必要な場合（クエリにおいては$idと表示される）、以下のように変数を送信する必要があります。
```json
{
"id":1
}
```
今回はこのidの値を可変にするためにgetInfo関数でidを受け取れるようにしています。

`operationName`も省略可能です（今回は明示しています）。これは、複数の名前のついたオペレーションを含むクエリがある場合に、どのオペレーションを実行するかを指定するために使用されます。

この3つのパラメータを`requestBody`として定義し、`getInfo`の中でエンドポイントにリクエストしています。

あとはこの`getInfo`をawaitを用いて呼び出すことで、Promiseの中身を取り出すことができます。
今回は受け取った中身の加工部分の処理は特に記述していませんが、あとは好きなように調理するだけです。


# 参考
https://stepzen.com/blog/consume-graphql-in-javascript
Next.js TypescriptでWebアプリを開発する 1

# はじめに
Next.js TypescriptでWebアプリを開発するさいに調べたことをまとめます。

# 基礎

## Next.js
### Next.jsの基本がまとまった記事
Nextの特徴的であるSSRレンダリング、ページングやスタイルの基本知識、useStateとuseEffectを用いた画面更新など開発で必要になることがわかりやすくまとまっている。
公式チュートリアルをみたとは以下の記事で確認するほうがいい。

https://zenn.dev/ttani/articles/nextjs_basic_learning

### 命名規則

https://zenn.dev/hrtk/scraps/ad027fd2cd50a1

## ReactContext
アプリケーションのあらゆる場所からアクセスできるグローバル状態オブジェクトを管理する方法。

https://dev-k.hatenablog.com/entry/nextjs-state-reactcontext-dev-k

## TypeScript

### コーディング規約

https://typescript-jp.gitbook.io/deep-dive/

### TypeScriptで使用する型がまとまった記事、わかりやすかった

https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a

### interfaceとTypeの違い
interfaceを用いて変なところで拡張されたくないからTypeを使用した。

>interfaceでできることが大体typeでもできるし、typeのほうが表現できる範囲が広いし、知らないうちに拡張されたくないから最初からtypeでよいということがtype派の理由です。

https://zenn.dev/luvmini511/articles/6c6f69481c2d17

### export defaultとexportの違い

> export defaultの場合は、変数や定数、関数などの処理を、１つの機能として渡します。いわゆるモジュールです。
exportの場合は変数や定数を複数渡すことができます。

https://prograshi.com/language/javascript/export-default-and-export/

### メモ
パラメータをオプションにしたい場合は、構造体などで『?』を付けて指定する。


# APIとの通信

### axiosを用いたGET,POST,PUT,DELETEの基本

https://docs.strapi.io/developer-docs/latest/developer-resources/content-api/integrations/next-js.html#create-a-next-js-app


# CORS
CORSとは、オリジン間リソース共有。オリジンが異なるもので通信しようとするとCORSエラーで引っかかる。
オリジンとは、リソース自身のURLの「スキーム」「ホスト」「ポート」の3つの組み合わせ。
別記事にまとめる。

https://qiita.com/att55/items/2154a8aad8bf1409db2b

# SWR
 Next.jsではGETメソッドを使用するとき、SWRの仕様が推奨されている。
ローディング、通信エラー、データ取得の状態を簡単に表すことができて便利。

公式

https://swr.vercel.app/ja

以下記事はSWRの使い方、メリットがわかりやすくまとまっている。

https://nosuke-blog.site/blog/react-get-method-library

https://maku.blog/p/vm2ft83/

以下記事はNext.jsのSSGの仕組み、SWRの使い方を同時に理解することができる記事。

https://zenn.dev/purenium/articles/nextjs-sg-use-swr-strong-consistency

mutateはswrで同じデータを再度取得するときに使用する。

https://swr.vercel.app/ja/docs/mutation

# JWT認証

ReactアプリとGolangAPIサーバーとのJWT認証の実装についてまとまった記事
認証機能の実装については別記事にまとめる。

https://log.include.co.jp/2021/02/12/golang_6/

# 開発で参考にした記事
### 入力フォームのバリデーション機能

https://www.ey-office.com/blog_archive/2022/04/29/i-remembered-html5-form-validation,-so-i-tried-using-it-with-mui/

### メッセージダイアログの表示方法

全ページで共通のメッセージダイアログを適宜する方法

https://zenn.dev/thirosue/books/13ac92fc34ae22/viewer/b4115b


# その他
### 正規表現

https://www.javadrive.jp/regex-basic/sample/index13.html
障害削減に向けた開発チームとの取り組みの話

## はじめに

今年もあっという間にこの季節がやってまいりました。
前回のアドベントカレンダーでは
「[障害対策は開発チームと二人三脚で行こう！](https://qiita.com/mountainQ/items/6f17e30bc74b4e0e940a)」として
開発チームと障害対策を進めようと記事を書きましたが
今回は更に踏み込んだ内容をお届けできればと思っています。


## 開発と進める障害対策の内容について

開発チームとの協力体制構築は[前回の記事](https://qiita.com/mountainQ/items/6f17e30bc74b4e0e940a)で説明させて頂いているので
今回は私が障害削減を実施するために行った対応について説明します。

開発チームとは下記の流れで障害対策を実施しました。

①開発とQAで障害再発防止を継続的にすり合わせるMTGの用意
②MTG前にQAから再発防止を実施したい障害の共有＆参加者の選定
③MTGまでに各セクション(プランナー、エンジニア、QA)で再発防止案の検討
④MTGを実施し各セクションの再発防止案を持ち寄りすり合わせ
⑤再発防止案の実施

上記①から⑤の詳細は以下となります。

**①開発とQAで、障害再発防止を継続的にすり合わせるMTGの用意**
障害が0というのは理想としつつも
運用を続けていると大なり小なり問題は発生するかと思います。

私が対応しているプロダクトでも継続的に障害が発生していたので
障害再発防止は一時的ではなく継続的に実施する必要があると考え、
開発チームとはスポット対応ではなく、継続的に話し合う場を用意しました。


**②MTG前に、QA側から再発防止を実施したい障害の共有＆参加者の選定**
基本障害周りはQAが管理している事が多いかと思います。
なのでQA側から再発防止を検討したい障害を選定し、関係者に共有する流れをお勧めします。

また、参加者についても、常に開発者全員が参加すると相当コストがかかってしまうので、
選定した障害にかかわるメンバーをMTGに呼ぶ形が良いかと思います。

**③MTGまでに各セクション(プランナー、エンジニア、QA)で再発防止案の検討**
MTG時に初めて再発防止案を検討していると時間が足りないので、
MTGまでに各セクション内で再発防止案を検討します。

どういう点に気を付けて再発防止案を検討しているかは後述します。

**④MTGを実施し各セクションの再発防止案のすり合わせ**
MTGの場では、自分のセクションで検討した内容を持ち寄り、
その再発防止案に考慮漏れ等が無いか。より効率的に対応できる方法がないかを、
他セクションにも確認してもらいながらすり合わせします。

**⑤再発防止案の実施**
MTGですり合わせた再発防止案を実施します。
実施できているかどうかは次回以降のMTGの場で確認したり、
JIRA等のプロジェクト管理ツールを使用して、再発防止用のタスクチケットを作成。
再発防止策を検討/実施出来たらタスクチケットをクローズする流れで進めます。


上記①から⑤の流れを続けることによって継続的に障害の再発防止対応を進めました。



## 再発防止案の検討について

また、特に気を付けていたのは各セクションで再発防止案を検討するタイミングとなり、
その際に重要視していたポイントを紹介できればと思います。

**①確認を他セクションに丸投げしない**
自分のセクションでの再発防止ではなく、例えばQAへの仕様共有を徹底する等、
再発防止を他セクションに丸投げする事はNGとしました。
(対策の一つとして実施する事はOK)

そういった再発防止案になっていた場合はMTGの場で、
まずは自分のセクションで対応できることが無いかをヒアリングし、
対策のすり合わせを行うようにしました。

**②ツールや機能を欲しがるだけ**
なぜこの障害が発生してしまったかの深堀りをせずに、
安易に自動化や補助ツールを求めることもNGとしました。

まずは、なぜこの障害が発生してしまったかの原因を明らかにし
そのうえで問題を事前に検知し防ぐ手順や工程を明確にする。
そして必要に応じてその手順の自動化や補助ツールの検討を行うようにしました。

他にも注意していたポイントはありますが、
特に上の2点は再発防止を開発チームと進めるにあたって重要視していました。

## 効果について

開発チームと連携してこれらの対策を進めることで
障害を前年と比較して約40%削減する事が出来ました。

QAだけでなく開発チームと一緒に発生原因を深堀りし、
他セクションではなく自分事として考え再発防止を検討/実施した事で
得られた結果だと思っています。

## 最後に

障害を減らしたいというのはQAだけでなく
開発チーム全体の思いでもあるかと思います。

改めてにはなりますが、
障害対策は開発チームを巻き込んで進めるようにしましょう！

ありがとうございました！
AI、ブロックチェーン、Web3 のコンサルティングとサービス

ブロックチェーン
開発サービス
当社はブロックチェーン開発サービスで、利用者に対してブロックチェーンを簡単に活用できるように取り組んでいます。 本サービスは広範なユーザビリティとユーティリティを通じて、様々なドメインや分野に影響を及ぼします。
dApps開発
私たちはお客様のビジネスにブロックチェーンアプリケーションを構築する手間を省きます。 当社のブロックチェーン開発者は、複雑なビジネス要件を取り、それらをユーザーフレンドリーなdAppに構成します。 dAppが他の分散型アプリとの相互作用する仕方から、ユーザーにシンプルなスマートコントラクトを作成することまで、クライアントにあらゆるプラットフォームで使用可能でスケーラブルなdAppをお届けします。 お客様のソフトウェア開発パートナーとして、当社はブロックチェーン技術を通じてお客様のビジネスにより多くの価値を生み出すソリューションを提供することをお約束します。

スマートコントラクトの開発
当社は、パブリックおよびプライベートブロックチェーンのスマートコントラクトの開発、実装、テスト、および監査に関する専門知識を持っています。 私たちは信頼できるスマートコントラクト開発会社であり、最も安全で高速なスマートコントラクト機能を提供しています。

スマートコントラクトアーキテクチャ
ワークフローにバグのないスマートコントラクトアーキテクチャを作成します

スマートコントラクトの設計と開発
あらゆる業界向けのカスタムメイドのスマートコントラクト。 不変のコードの強さとビジネスニーズに適応する柔軟性を備えたインテリジェントな自動されたコントラクト。

スマートコントラクト監査
当社のスマートコントラクト検証サービスは、スマートコントラクトにバグや違反がないことを保証します。

スマートコントラクトの最適化
当社の最適化サービスは、導入前にスマートコントラクトを最適化して、ガス（送信料金）の節約に役立てます。

NFTマーケットプレイスの開発
あなたは、デジタル資産の取引、入札、販売を整理するために独自のNFTマーケットプレイスを立ち上げたいアーティスト、コレクター、またはビジネスマンですか？ お手伝いします。 私たちは、アートワーク、ゲームカード、ソフトウェアライセンス、デジタル収集品、実世界の資産など、独自のデジタル資産をトークン化しようとしている企業向けの分散型マーケットプレイスを構築する専門家です。 マーケットプレイスの機能が豊富で使いやすいものにすることで、コミュニティが急速に成長することを保証します。

NFTマーケットプレイスの設計と開発

NFTスマートコントラクトの開発と監査

NFTマーケットプレイスのサポートとメンテナンス

NFT開発

NFTミンティングプラットフォームの開発

NFTストレージソリューション


分散型取引所
Unilabのチームは、完全に安全で、堅牢で、費用対効果の高い分散型暗号取引プラットフォームを開発しています。
ブロックチェーンウォレットの開発
安全で機能が豊富で直感的なブロックチェーンウォレットアプリケーションを開発し、ユーザーが簡単に資金を即座に受け取り、転送できるようにします。 当社のブロックチェーンウォレットソリューションを利用すると、プラットフォームや通貨を問わず、デジタル資産を操作して金融取引を行うことができます。 さらに、トークンスワッピングとクロスチェーントークン交換のアドオン機能に加えて、分析やその他の同様の目的で取引データを第三者と共有する機能を提供します。
トークン化（トークンとアルトコインの開発）
ブロックチェーン技術コンサルティング
ブロックチェーンサプライチェーン開発
初心者向けgit&githubの使い方(作業編)

# はじめに
こちらの記事は[前記事 初心者向けにgit & github](https://qiita.com/usamaro/items/dee2188ba6dd64860454)にて、初心者向けにgit & githubの続きになりますのでまだ見てない方はそちらを先に見て下さい。

## なぜブランチを切る必要があるのか？
たとえば、冒険ゲームのように**Aデータは右へ** **Bデータは左へ**みたいに別々展開のデータ持ちたい時なんかにそれぞれセーブできたら便利だと思いませんか？

こんな感じで普段からgitを使用していると「あ、まちがえた！」なんて経験あると思います。
今回の記事はそんな時などに便利な機能(保管機能)になります。

今回は実際に実用的にブランチを切ってpush,mergeなどをやって行きたいと思いますのでお願いします。
やることは、
1.親ブランチを切って子ブランチを作成
**↓**
2.ファイルの編集
**↓**
3.保存
**↓**
4.編集内容がOKであればmerge(親ブランチに反映させる)

になります。
## 親ブランチからブランチを切ってからの作業です!
まず下記コマンドを実行
~~~
$ git checkout -branch 好きなブランチ名(main,master以外の好きな名前など)
~~~
<font color="red">これで親ブランチから分身を作成しました。</font>
続いて先程までやってもらったgit管理したファイルを適当に**編集**してください。
そしてもう一度コマンド入力します。
~~~
$ git status
~~~
ファイル名が出て文字が<font color="red">赤く</font>なっていればOKです。
続いて、仮保存して確認して行きます。
~~~
$ git add .
~~~
~~~
$ git status
~~~
先程<font color="red">赤</font>だったファイル名が<font color="green">緑</font>になっていればOKです。

続いて、本保存からgithubへ保存までです。
~~~
$ git commit -m 'ここにどんなファイルかなど入力'

$ git push origin 先程切ったブランチ名
~~~
ここまでは先程と同じですね。

# ここからはgithubでの作業になります。

上から順番にクリックして行きます。
まずPull requestsを選択
![スクリーンショット 2022-06-16 1.22.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701052/7c1a81ad-91a3-8944-a44f-c86491456e17.png)

New pull requestsを選択
![スクリーンショット 2022-06-16 1.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701052/3cb8f125-97a1-432c-bebb-458d302294c7.png)


base(本番ブランチ名)<-compare(切ったブランチ名)を指定
![スクリーンショット 2022-06-16 1.00.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701052/545537e2-9a95-3013-5994-887b5273f0cf.png)
クリック
![スクリーンショット 2022-06-16 1.00.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701052/7ecf9fd7-ec07-e018-6888-81b9366400d1.png)
クリック
![スクリーンショット 2022-06-16 1.00.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701052/bdb3cc3e-dd41-7c2c-31d5-87af35d4a5e6.png)
Confirm mergeを選択
![スクリーンショット 2022-06-16 1.31.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701052/5794ad5e-1004-87e6-d32b-1809ea27b62b.png)


最後のConfirm mergeまで行きましたら完了になります！

# 最後に
こちらで一通りの作業は完了になります。
まだまだ色々できることがありますがそれはその都度必要になれば調べてもらえばと思います。
ここまでお付き合いくださりありがとうございました。
テスト80

```vb

Sub copy_Object()

Dim fpath As String
Dim obj As Variant

'自身のAccessファイルが排他モードでもバックアップする方法
'(正確には、指定のフォルダに新しくAccessファイルを作成し、
'そこに自身の全てのオブジェクトをコピーするというもの)....
'...〆(･ω･＊)<ややパワープレイになってしまうか・・・。

'2022/12/14追記、下記のコードはあくまでオブジェクトだけコピーできるだけで、
'参照設定などのファイルの設定まではコピーできない

'Docmd.CopyObject コピー先データベース,新しい名前,オブジェクトの種類,オブジェクト名
fpath = "C:\Users\User\Desktop\VBA関連\AccessVBA学習\バックアップ\test1.accdb"

'新しいAccessファイルの作成
With New Application
    .NewCurrentDatabase fpath
    .Quit
End With

Application.AutomationSecurity = 1

'DataAccessPageを列挙
For Each obj In CurrentProject.AllDataAccessPages

        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acDataAccessPage, obj.Name
        DoCmd.SetWarnings True
        
Next

'フォームを列挙
For Each obj In CurrentProject.AllForms

        DoCmd.Close acForm, obj.Name
        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acForm, obj.Name
        DoCmd.SetWarnings True
        
Next

'マクロを列挙
For Each obj In CurrentProject.AllMacros

        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acMacro, obj.Name
        DoCmd.SetWarnings True
        
Next

'モジュールを列挙
For Each obj In CurrentProject.AllModules

        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acModule, obj.Name
        DoCmd.SetWarnings True
        
Next

'レポートを列挙
For Each obj In CurrentProject.AllReports

        DoCmd.Close acReport, obj.Name
        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acReport, obj.Name
        DoCmd.SetWarnings True
        
Next

'テーブルの列挙
For Each obj In CurrentData.AllTables
    
    If obj.Name <> "MSysAccessStorage" _
    And obj.Name <> "MSysAccessXML" _
    And obj.Name <> "MSysACEs" _
    And obj.Name <> "MSysComplexColumns" _
    And obj.Name <> "MSysNameMap" _
    And obj.Name <> "MSysNavPaneGroupCategories" _
    And obj.Name <> "MSysNavPaneGroups" _
    And obj.Name <> "MSysNavPaneGroupToobj.Nameects" _
    And obj.Name <> "MSysNavPaneobj.NameectIDs" _
    And obj.Name <> "MSysobj.Nameects" _
    And obj.Name <> "MSysQueries" _
    And obj.Name <> "MSysRelationships" _
    And obj.Name <> "MSysResources" _
    And obj.Name <> "MSysNavPaneGroupToObjects" _
    And obj.Name <> "MSysNavPaneObjectIDs" _
    And obj.Name <> "USysRibbons" _
    And obj.Name <> "MSysObjects" Then
    
        DoCmd.Close acTable, obj.Name
        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acTable, obj.Name
        DoCmd.SetWarnings True
    
    End If
    
Next

'クエリの列挙
For Each obj In CurrentData.AllQueries

        DoCmd.Close acQuery, obj.Name
        DoCmd.SetWarnings False
        DoCmd.CopyObject fpath, , acQuery, obj.Name
        DoCmd.SetWarnings True

Next

'MsgBox "全てのオブジェクトをコピーしました。"

End Sub

'メモ
'更新クエリや削除クエリ実行前後にエラー処理はあるか確認
Ubuntu で CoreDump を取得する

あるプログラム（/usr/loca/bin/\<prog_name\>）を実行していたら、以下のエラーを吐いて、core dump したらしいです。

```
malloc(): memory corruption
Aborted (core dumped)
```
Ubuntu に詳しくないのですが、core ファイルがどこかにあるはずだ、と思い、/var/crash を探したりしても、ありません。

どういう仕組みになっているのか。。

どうやら、Ubuntu には、apport という仕掛けがあるらしいです。

要すれば、Ubuntu のパッケージであれば、そのエラーを捕捉して、Ubuntu のセキュリティチームに送信できる、みたいな仕組みで、RHEL にも、同様の仕組み（abrt）がありますよね。

で、ちょっと調べると、/var/log/apport.log というところに、ログが出力されているらしい、と。

```
executable does not belong to a package, ignoring
```

どうやら、Ubuntu パッケージに含まれていないプログラムだったために、core dumped となっているが、実際は、core dump されていないようです。
では、どうやったらいいのか。。
以下で出来ました。

```
# mkdir -p ~/.config/apport
# vim ~/.config/apport/settings
[main]
unpackaged=true
```

パッケージに含まれていないけど、よろしく、って意味でしょうかね。

また、core dump が吐かれるような動作をしてみたら、/var/crash 配下に、以下のようなファイル名のファイルが生成されていました。
フルパスで書きます。

```
/var/crash/_usr_local_bin_<prog_name>.0.crash
```

では、これが、CoreDump なのかというと、そうではありませんでした。
次のコマンドで、展開する必要があるようでした。

```
# apport-unpack /var/crash/_usr_local_bin_<prog_name>.0.crash exp
```

exp ディレクトリ内に、CoreDump ファイルを発見しました！

プログラムは、デバッグシンボル付きでコンパイルされていませんでしたが、何が起こったかぐらいは分かりました。

```
# gdb /usr/local/bin/<prog_name> CoreDump
...(snip)...
(gdb) bt
...(snip)...
#3 0x...... in malloc_printerr (Str=str@entry=0x...... "malloc(): memory corruption") at malloc.c:5342
...(snip)...
```

Signal というファイルを開くと、6 とありました。

（参考）
Apport ～Ubuntu のコアダンプ作成動作～ 
https://valinux.hatenablog.com/entry/20210721
たった4ヶ月間でUdemy講師として9ドル近くを稼いだ私が実践している学習法

# さぁ、学習しましょ、そうしましょ
勉強は時に辛く、あまり楽しいものではありません。しかし、学習法を体得することで楽しく知識を身につけることを覚えれば、スキルアップにもつながるので、実践していきましょう!!

## なぜ、Udemy講師を始めたか
タイトルにもある通り、私はUdemyの講師を2022年8月半ばから始めました。そうしたらなんと、4ヶ月で9ドルも頂けました。これはアレゲな人たちが集うアレゲなお店の[たん清](https://tankiyo.com)約1/7～1/10回分のお値段に相当します。なんでこんなに稼ぎが悪いのに講師を続けるかというと「**教えるプロセスで重要な気づきが得られる**」からです。

## 先生は優しく・正直であれ
教えるプロセスでの気づきとは何か、それは「平易に説明できる」ことと「間違ったことを言わない」と言うことを意識するようになるとわかります。相手に伝えるためにはどうしたらよいか、徹底的に考えると頭の中では教えるために整理され、きちんと順序立てて話ができるようになります。この時点でおそらく自ら学習したことが定着し始めると思います。また、教えている相手にウソを言っていないかと言うことに気をつけることによって、学習内容のチェックが改めてできるわけです。そしてなにより、本を読む習慣が付きます。これは本当にあっているのだろうかという不安感にかられて、資料を読むようになります。その時は書籍が一番頼りになる、と私は思っています(よほど先進的でない限りは)。

## 教えることが苦手ならば、まずは自分が何者か、それを言えるようにしよう

学習するのになんで教えなきゃいけないんだ、と思うかたもいるでしょう。じゃぁ教えることはこっちに置いておいて、まずは「自分の仕事などを説明する」力を養ってみましょう。そうすることで「頭の中を整理する」ことができるようになると思います。

一応私は研究者の端くれです。国費で出張に行ったこともあります。国のお金と言うことは税金です。税金と言うことは納税者がいてその納税者というのは国民となります。ですから研究者というのは納税者、つまり一般の人に「自分の研究内容」をいかにしてわかってもらえるかと言うことを常に頭の中で整理しておく必要があり、「あなたは何者ですか？あなたの研究はどんなものですか？」と言われたときにはきちんと説明できるようにしておかなければならないと思っています。と言うように自分のやっていることを他の人に、特に何もわかっていない人に説明する力を養っておくと先に述べた「教えることで学習が定着する理論」の真意がわかって頂けるようになると思います。

## プログラムは、習うより慣れろだが、基礎は誰かに教えてもらうべきだと思う

さて、このアドベントカレンダーはUdemyさんと新人プログラマさんをタグに持つので、まずは私の経験からプログラミングに必要な学習方法について持論を述べます。これは、私の考えですので、正しいとかどうかは皆さんのご判断でお願いします。

私は、プログラミングテクニックは自分で編み出すことが重要であると思いますがその基礎になっている以下のこと

* 変数代入
* 制御構文
    * if文
    * for文
    * while文
* 関数の作り方と呼び出し方

等については師匠(今風に言うとメンターかな？)について学ぶことが重要だと思います。基本構造さえ抑えればプログラム言語が変わっても多少の学習でその変わった言語でも対応ができると思います。

## ちなみに私が学んだプログラミングテクニック習得法

実はそんなものは私にはありません。自分で考え行動し身につけたものばかりです。プログラミングにはじめにであったのは幼少期の頃で、ファミコンを買ってもらえずMSXを買い与えられた私は、読んでもわからないリファレンスマニュアルと格闘し、自力で覚えたものばかりです。だから簡単に言えば「環境がそうしてくれた」がプログラミング習得法に関する私の回答です。そんな「環境がそうさせる」ことに時間がかかり、そんな暇が無い人はやはり良い師匠を見つけてプログラミングのいろはだけでも盗んでしまうのが良いかと思います。

## そんな私が学習したUdemyの教材
そんな私がUdemyで学習したのは次の通りです。

https://www.udemy.com/course/learn-to-use-hpc-systems-and-supercomputers/

これは、私の専門分野である並列処理やHPCと呼ばれている高性能計算の為のレクチャーが詰まっているものです。ただし、英語が超苦手なので学習効果はあまり上がらず、だから私が日本語でHPCの学習教材を作成しようと誓うきっかけになったコースです。

次はこれです。

https://www.udemy.com/course/illustratgor/

絵心が全くないので学習した教材です。コロナ禍で在宅勤務を始めた頃に通勤時間分をこれに費やしました。

なんだ、プログラミングに関することが書かれていないじゃん!!とお思いでしょうが、私一個人の意見として、やはりよっぽど時間が余っている場合を除き、プログラムは習うより慣れろだと思っています。

## 本との出会いを大切にしよう

良い師匠に恵まれ、プログラムの基本構造を覚えた後は、自分で実践するのみです。その時に頼りになるのはやはり書籍になります。
このとき、以外とジャケ買いが有効なときがあり、買って読んだ本が後々ベストセラーになるなんてこともざらにあります。ですのでリアル書店に行き、手に取って「これだ」と思ったものを買ってみるのも良いかと思います。

### 番外編：並列処理屋さんらしい学習方法

私は計算機科学者、特に並列処理関係の科学者の端くれなのですが、その私が実践している方法は**秘技!!並列リーディング**です。どういうことかというと、私は本を読んでも集中力が続きません。大体一回に一冊で読むことができるのは2～3ページが限界なので、それを有効活用して、数冊以上の本を用意して、同時並行的に読んで飽きたら次の本に切り替えて読んでみると言うのを実践しました。学習効果が高いかどうかは別の話として、こうすることで、1回に読める一冊あたりのページ数は変わらないものの、それを連続しておこなうことで一回に読める総ページ数は多くなりました。

## おしまいに

私が心がけている学習法を少しご覧に入れることができたかと思います。教える相手がいないならば私のようにUdemyで講師をしてみるのも良いかと思います。そうすることで学習内容が身につき、頭の中がスッキリする事でしょう。

是非お試しあれ。
フレームワークの設定をする、"Framework Bundle"

[Symfony Component Advent Calendar 2022](https://qiita.com/advent-calendar/2022/symfony-component)の25日目の記事です。

## 最初に
[Symfony](https://symfony.com)はPHPのフレームワークのひとつです。しかし、公式サイトの説明文には

> Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
  （SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。）

と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。

今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。

※記事内ではautoloadのインポートは省略します。


## フレームワークの設定をする、"Framework Bundle"

[Framework Bundle](https://symfony.com/doc/current/reference/configuration/framework.html)は、、フレームワークの設定するためのコンポーネントです。

:::note alert
**フレームワークの設定をするもの**であって、フレームワーク自体ではありません。
:::

### インストール

```shell
composer require symfony/framework-bundle
```

### フレームワーク設定する

Symfonyは、すでにご存知の通りたくさんのコンポーネントから成り立っています。どのようにルーティングしていくか、翻訳をどうするか、セッションはどう管理するかなどをひとつずつ設定していくのは大変です。`Framework Bundle`はフレームワークとして動作するために必要な主要な設定を定義するために利用します。

```yaml:config/packages/framework.yaml
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
    secret: '%env(APP_SECRET)%'
    #csrf_protection: true
    http_method_override: false

    # Enables session support. Note that the session will ONLY be started if you read or write from it.
    # Remove or comment this section to explicitly disable session support.
    session:
        handler_id: null
        cookie_secure: auto
        cookie_samesite: lax
        storage_factory_id: session.storage.factory.native

    #esi: true
    #fragments: true
    php_errors:
        log: true

when@test:
    framework:
        test: true
        session:
            storage_factory_id: session.storage.factory.mock_file
```

変更が必要な場合は、`framework.yaml`に設定すれば機能を変更してくれます。
設定できる項目は[こちら](https://symfony.com/doc/current/reference/configuration/framework.html#configuration)です。
また、各種コンポーネントインストール時に作成された設定ファイルにも`framework:`キーを指定して以降に定義すれば、反映されます。

この`Framework Bundle`により、必要な設定が全て反映され、わたしたちの知っているSymfonyとして動作します。

### 便利なクラスやアトリビュートの提供

`Framework Bundle`は設定のほか、フレームワークとして利用する際に便利なクラスやアトリビュートを用意しています。
Controllerで普段使うメソッドを備えた抽象クラス`AbstractController`、機能テストを行うときに便利な`KernelTestCase`や`WebTestCase`、指定のURLにアクセスさせるか決めるサービスを選ぶ`#[AsRoutingConditionService]`なんていうアトリビュートも用意しています。


## まとめ

今回は、`Framework Bundle`を紹介しました。設定とその反映を行うコンポーネントですが、Symfonyにとっては非常に大事なコンポーネントになります。


## アドベントカレンダーのまとめ

25日分書き切ることができました。それぞれのコンポーネントは正直基本中の基本な使い方程度の紹介しかできていないです。
詳しくは公式ドキュメントを見ていただきたいのですが、結構かゆいところに手の届くコンポーネントばかりです。
Symfony以外でも動作するものが多いので、ぜひぜひ使ってみていただけたらなと思います。

今回25個のコンポーネントを紹介してきましたが、じつは[Symfonyのコンポーネントは全部で207あります](https://symfony.com/components)。（2022年12月25日現在）

来年もできそうですね。