OmniAICreator/Qiita-1.07M huggingface dataset:
UE5 2D（ドット絵）最適な設定方法

`macOS 13.2.1, UE5.1.1で動作確認済みです。一応Windowsも対応しています（はず）`
`前提条件
2Dのドット絵を見たときに色がにじんだりする場合`
まず、色がにじむファイルを選択します。
![スクリーンショット 2023-02-28 13.12.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/ca4390b6-07ba-9048-ed5c-97ac74e08193.png)
次に、ファイルの上で右クリックをします。
![スクリーンショット 2023-02-28 13.14.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/5e9fffed-0ff6-1a5d-b14d-ad0f4a40fd76.png)
Sprite Actions -> Apply Paper2D Texture Settingsをクリック
![スクリーンショット 2023-02-28 13.16.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/99ff218a-eac6-b154-5a74-bbe340c40856.png)
これで、色のにじみがなくなります。
ですが、UE5.1からFilterをNearsetにしないと急に色のにじみが出たりしてしまいます。
ファイルを開きます。
![スクリーンショット 2023-02-28 13.05.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/7ed34084-9ce7-85e6-3809-f1aaffaad92a.png)
そして、Texture -> Advenced -> FilterをNearestにします。
![スクリーンショット 2023-02-28 13.21.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/ffe494cc-cc67-be97-8047-dffb8a1b7302.png)
これで、2Dのドット絵で最低限の設定が終わりました。
2Dのドット絵を頻繁に使う人のために、これらの設定を一括でできるツールを作成しました。
下のリンクから、ダウンロードして使ってください。
[ツール](https://drive.google.com/file/d/1XOLsqADkCEYU_859TJ94gY0VPma1BcTG/view?usp=share_link)
ツールの使い方↓
まず、ダウンロードしたツールをプロジェクトのContent直下にFinder(エクスプローラー)で移動させます。（フォルダーはContent内だったらどこでもいい）
![スクリーンショット 2023-02-28 13.37.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/5f4fd770-7b96-337c-a61f-b5c9ce3677c3.png)
ファイルを右クリック -> Scripted Asset Acctions -> New Paper 2DTexture Settingsをクリック。
![スクリーンショット 2023-02-28 13.41.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200440/745581b9-83ce-c394-2af5-94e73f9e082b.png)
ツールを使えばこれだけで完了します。
ツール作成の参考
[UE5 2Dとか](https://www.youtube.com/@UE5Study)
Unity で GLB/GLTF Scripted Importer が被ってエラーになったら、

# こうじゃ。

https://github.com/vrm-c/UniVRM

https://github.com/readyplayerme/rpm-unity-sdk-core

UniVRM と Ready Player Me Unity SDK Core をインポートしたら、コンソールに以下の表示があった。

::: note alert
Multiple scripted importers are targeting the extension 'gltf' and have all been rejected: GLTFast.Editor.GltfImporter (assembly: C:\■PROJECT DIRECTORY■\Library\ScriptAssemblies\glTFast.Editor.dll), UniGLTF.GltfScriptedImporter (assembly: C:\■PROJECT DIRECTORY■\Library\ScriptAssemblies\UniGLTF.Editor.dll) 
UnityEditor.AssetImporters.ScriptedImporter:RegisterScriptedImporters ()
:::

::: note alert
Multiple scripted importers are targeting the extension 'glb' and have all been rejected: GLTFast.Editor.GltfImporter (assembly: C:\■PROJECT DIRECTORY■\Library\ScriptAssemblies\glTFast.Editor.dll), UniGLTF.GlbScriptedImporter (assembly: C:\■PROJECT DIRECTORY■\Library\ScriptAssemblies\UniGLTF.Editor.dll) 
UnityEditor.AssetImporters.ScriptedImporter:RegisterScriptedImporters ()
:::

フォーラムで以下の回答が見つかった。

https://github.com/readyplayerme/rpm-unity-sdk-core

> If you can edit one of these plugins' code in your project then you should be able to work around the issue easily.
Choose one of the importer that you don't want to be the default for gltf import, and change the [ScriptedImporter] attribute to make it an optional importer.

``` C#
    // Default importer
    [ScriptedImporter(1, new [] {"gltf", "glb"})]
    // Optional importer
    [ScriptedImporter(1, null, new [] {"gltf", "glb"})]

```

> From that point, selecting any gltf or glb asset in your project should show you a drop-down at the top of the inspector to let you change which importer you want to use on that asset. 

競合しているので、どちらかがデフォルトではなくなるようにスクリプトを書きかえれば良いらしい。

とりあえず UniVRM に入ってる方をデフォルトにすることにした。
glb, gltf それぞれでプロジェクト内を検索し、それっぽいスクリプトを開く。

GLB:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253921/93f045cf-34df-550b-2a47-4aa389e21d6f.png)

GLTF:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253921/d868793d-7eac-85e2-a54b-00ac4b41a842.png)

すでにプラットフォーム依存コンパイル（#if ディレクティブ）として、`UNIGLTF_DISABLE_DEFAULT_GLTF_IMPORTER` と `UNIGLTF_DISABLE_DEFAULT_GLB_IMPORTER` が使えることが分かった。

Project Settings > Player > Other Settings > Script Compilation > Scripting Define Symbols に、上記の項目を追加する。

ここに↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253921/a68d3d7f-3bca-bac0-0977-51be6a42581b.png)
こう↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253921/8b4de544-d6f1-a939-568c-7da86e68b32d.png)

Apply を押下するとコンパイルが走り、問題が解決する。

# 追記 @ 2023-03-01

この作業はプラットフォームごとに設定が必要です。
typescript function文とfunction式

今まで雰囲気で書いてましたが、ある本を読んでなるほどと思ったのでメモです。
型定義を共通して使えるという理由でfunction式(アロー関数)の使用を推奨されてました。
(他にも違いはあると思いますが……)



### function文の場合
function文の場合、全ての関数定義に型付けする必要があり煩雑ですよね。
さらに、引数や戻り値が変わった場合すべてを修正する必要があります。

```typescript
function add(a: number, b: number): number {
  return a + b;
}

function subtract(a: number, b: number): number {
  return a - b;
}

function multiply(a: number, b: number): number {
  return a * b;
}

function divide(a: number, b: number): number {
  return a / b;
}
```

### function式の場合
下記のように型定義をCalcTypeでまとめることができ、変更があった場合も一か所の修正で済むようにできました。
（まあ、型が変われば関数の実装も変わるんだろうけど。。。）

```typescript
type CalcType = (a: number, b: number) => number;

const add: CalcType = (a, b) => a + b;
const subtract: CalcType = (a, b) => a - b;
const multiply: CalcType = (a, b) => a * b;
const divide: CalcType = (a, b) => a / b;
```

参考になれば幸いです。
[Tipsシリーズ]アプリを有効化しTeamsから利用可能にする

みんな、楽してる？どーも飯田です。
より日々の業務が便利になるTipsを不定期で紹介していきます。皆様の業務が楽に、楽しくなるような様々なナレッジを共有していきますので、是非お楽しみください:point_up:


# Teamsからのアプリ利用
前回の記事で、[Teamsからアプリをピン留めして利用する方法](https://qiita.com/Mikio_Iida/items/32aef1f1ca670b7635aa)についてご紹介させて頂きました。
ただ全員が自由にアプリを使えるということもなく、「使いたいアプリが見つからない」「そもそもどんなアプリが使えるかわからない」、というお声を耳にします。
そこで今回は活用推進担当者向けに、アプリを有効化してTeamsからアクセスできるようにする方法をご紹介します。




# 管理センターでの設定
先ずは、Teams管理センターにアクセスしましょう。（管理者権限を持っていない方は権限を持っている方と一緒に）

## アプリ自体の有効化
Teams管理センターにアクセスし、

1. **Teams管理センター＞Teamsのアプリ＞アプリを管理**
の画面に遷移し対象のアプリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889038/4e092954-59f7-95f5-1ad2-f4e28b3627a0.png)

2.次にたくさんのアプリが表示されるので、参照元＞右上検索ボタン "名前を検索" から任意のアプリを検索してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889038/ac237c23-1288-3fab-68e7-807befcfd42a.png)

ここではAcrobatを検索し、アプリの "状態" が "許可済み" であることを確認しました。

### Tips
- もしアプリの "状態" が "ブロック済み"であるとユーザーが利用できないので、"許可済み"に変更しましょう。


## アプリへのアクセス許可

1. **Teams管理センター＞Teamsのアプリ＞アクセス許可 ポリシー**
の画面に遷移し対象のポリシー（ここではグローバル）を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889038/2b5f4c78-4eb1-718b-971f-04f166e0306a.png)


2.グローバルのポリシーの設定を確認すると、デフォルトでは"すべてのアプリを許可"になっております。この場合、アプリを管理画面にて許可されているすべてのアプリへTeamsからアクセス可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889038/17690863-e77d-f331-ac71-eda29d8ad509.png)



### アプリを使えない場合
アプリ自体の有効化以外にも、ポリシーでアプリ利用制御をかけている場合があります。

1. **Teams管理センター＞Teamsのアプリ＞アクセス許可ポリシー**
の画面に遷移し対象のポリシー（ここでは制御するユーザー）を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889038/f7c39556-5c24-fdbf-2e61-96bd49e1938b.png)


2.制御するユーザーのポリシーの設定を確認すると、サードパーティー製アプリ＞"特定のアプリを許可し、他のすべてのアプリをブロック"になっております。この場合、アプリを管理画面にて許可されているAcrobatアプリのみTeamsからアクセス可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889038/c2164e6a-0a1c-b811-4c19-aa3698159a42.png)


セットアップポリシーにてピン留め設定をしてもTeams上に表示されない場合は、このアクセス許可ポリシーから当該アプリを制御していないかも確認しましょう。

# まとめ

「せっかく使いたいアプリがあるのに使えない」、「ピン留め設定をしたのに見つからない」という悩みとはおさらばです。
**アプリの有効化とアクセス許可**を確認し、Teams左メニューへの固定表示をして普段利用するTeamsから楽にアプリを使ってみましょう！

スマホのホーム画面のように、Teams上で “好みのアプリ” をいつでも手元に！

それではまた次回、会いましょう～:raised_hand:
React + MUI + react-router-dom でNavigatorを作る

## 環境
- React
- MUI
- react-router-dom

## 完成図
左側のナビゲーターで、現在いるページを強調表示したかったのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/20a3d5bf-e9bd-3c9d-972c-b15a8f299b21.png)

## 参考にしたサンプル
https://github.com/mui/material-ui/blob/master/docs/src/pages/premium-themes/paperbase/Navigator.js

## コード
元だと、リンク先に飛ばす仕組みと、遷移後に強調表示する仕組みがなかったので追加します。

ListItemButtonのActiveをtrueにしたいので、
`location = useLocation()`
で取得したlocationのpathnameと、リンク（to）を比較してください。

```react:useLocationの呼び出し位置
export default function Navigator(props) {
  const { ...other } = props

  const location = useLocation()

  return (
```

そしてReact + MUIだとメニューはListItemやListItemButtonを使って作ると思います。
ListItemにNavLinkを組み合わせるには
`component={NavLink}`を指定します。

```react:jsx
<ListItem  key={childId} disablePadding component={NavLink}
to={to}>
    <ListItemButton
        selected={location.pathname===to}
        sx={item}
    >
        <ListItemIcon>{icon}</ListItemIcon>
        <ListItemText>{childId}</ListItemText>
    </ListItemButton>
</ListItem>
```

クリックしたら元データの`active`プロパティをfalseにして・・とか考えてたんですけどよく考えたら現在のURLと比較するだけだったのでメモをのこしておきます。
【PostgreSQL】OSS-DB Silverに一発合格するためにしたこと

## はじめに
データベースエンジニアをしているだいちです。
と言っても前職はバックエンドエンジニアとして開発を担当していたのですが、とあるご縁とキャリアパスを検討した結果、データベースエンジニアとして進むことを決めました。
ですが、DBのことは正直知らないことが多いです。
特に開発のときにはMySQLがメインで、ちょこっとSQLServerに触れたぐらい。
しかもDBの監視・運用なんて深く関わることがなく、ただただDMLをアプリケーション側から発行しているだけのような自分でした。

そんな状態でいざデータベースエンジニアとして、業務をしていくと知らない言葉がポンポン出てくるわけです。
スキーマ、ロール、DDL、他にも沢山。
もちろん、聞いたことある単語もありますが、その場だけ理解してすぐに忘れているような状況です。
これでは流石に仕事にならんと思い勉強を始めるのですが、いまいち自分が覚えているのかが実務の中ではわからない。
というわけで自分が理解できているということが資格というもので図れたら、自分は理解出来ていることも明確になり、おまけで日本人大好き資格のおかげでなんかすげぇと評価されると思ったわけです。

今回取得した、OSS-DB Silverの勉強過程をまとめて、これから受ける人のちからになれたらと思います。

## やったこと一覧
やったことはシンプルに下記の3つに纏められる
それぞれ、なぜそうしたのかも含めて紹介していきます。

- 申し込み
- 勉強
- 試験

## 申し込み
### ケツに火を付けるために先に試験日を決定
僕の場合は先に試験日を決めるためにサクッと申し込みをしました。
約1ヶ月後に試験日になるように申し込みをしておき、限られた時間で最大限に勉強できるよう自分に縛りを設けたわけです（縛られるのは嫌いです）

## 勉強
### 書籍を購入・活用
まずはざっくりとOSS教科書を読んでPostgreSQLを知ろうとしました。
↓↓↓↓↓
[OSS教科書 OSS-DB Silver Ver2.0対応](https://amzn.to/3ZmM59s)
↑↑↑↑↑
ですが、読んでも頭に入らなくてどうにかしないとまずいなと思っているところに
とある勉強法を知り、まとめられた本が出ていたので読んでみました。
結論としては自然と自分が学生の頃にもしていた勉強法ではあったのですが、思い出すことができ勉強の仕方を変えるきっかけが出来ました。
↓↓↓↓↓
[大量に覚えて絶対忘れない「紙1枚」勉強法](https://amzn.to/3IriSTS)
↑↑↑↑↑

### Ping-tを活用
[Ping-t](https://mondai.ping-t.com/g)という問題集をまとめているサービスがありこちらを活用しました。

Ping-tにした理由としては、問題数が多いのもありますが、管理の仕方が理想に近い方法でした。
間違った問題はミスとしてカウント
1度正解した問題はヒット
2回以上続けて正解したらコンボ
という管理が出来て自分が覚えてない箇所がわかるし、
ミスした問題は優先的に模擬試験などで出題してくれます。

そんなサービスにプラスして僕は間違った問題について
ブログでまとめるようにしました。
下記のように結構な数の記事が結果としてできました。
![スクリーンショット 2023-02-27 23.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572072/05908e45-b97a-b5c8-4ed8-31dc164a1c6e.png)


まとめ方もただ説明を書き写すのではなく、
実際にPostgreSQLを使ってみることも意識してまとめました。
そうすることでinputとoutputが両方できてより記憶に残る感覚が自分にはあったので実践しました。
このおかげで試験のときには、問題に対して頭の中で自分が操作している記憶を探り答えを導いたこともあります。

## 試験
### 早起きしてカフェに向かう
最後の追い込みとしてカフェに行って模擬試験をやりました。
間違った問題はさらっと解説を読んでおくことで、一時的ではありますが試験のときに役立つと思いやったおかげか、運良く似たような問題が出てくれて助かりました。

## まとめ
今回の資格勉強だけでなく、自分が身につけたいことであればとにかくinputとoutputを意識して勉強方法を選ぶのがいいと考えてます。
教科書を読むだけでは何も印象に残らない。そこでoutputをすることで例えば同じようにやったのにエラーが出たりしたらそれは記憶に残りやすいことになると思います。
ぜひとも参考にしてみてください。

また、資格合格をしてみてわかったことは、
OSS-DB Silverを持っている = 実務でわからないことが最小限に抑えられる
と感じてます。
この資格をとったからといって実務でバリバリ活躍できる。とは感じてません。
ほんと、基本を身に付けたに過ぎないのでこれからも継続して勉強はしていきます。
次はOSS-DB Goldですかね。参考書などが極端に少なく、模擬試験も少ないようで骨が折れそうです。
 
### 最後に
#### 嫁に相談を忘れずに
僕には1歳になったばかりの息子がいます。
一人で子育ては想像以上に大変なことにも関わらず、嫁に勉強したいことを相談したらすぐさま応援してくれました。
そんな協力もあっての一発合格だと思っているので本当に嬉しい気持ちでいっぱいです。
応援してくれた嫁には感謝！！！！
古いcapistranoで Net::SSH::Exception: could not settle on host_key algorithm

古い環境のrailsアプリをcapistranoでビルドしようとしたところ、以下のエラーになった。

```
cap aborted!
Net::SSH::Exception: could not settle on host_key algorithm
```

おそらくopensslがデフォルトでRSAをサポートしなくなったことが原因。単純なSSH接続の場合は[この方法](https://qiita.com/sekitaka_1214/items/1b5669cbef0451ce45fc)で解決できました。
今回はどうやらcapistranoが使っているnet-sshが古すぎて `+ssh-rsa` という記法を理解できなくて、`+ssh-rsa` を追記してもcapistranoが失敗してしまうという状況。

以下のように対応するアルゴリズムをすべて列挙し解決しました。
本来ならサーバーの公開鍵を差し替えるのが正しいと思いますが、とりあえずワークアラウンドとして。

```diff
Host * 
   #PubkeyAcceptedKeyTypes=+ssh-rsa 
   #HostKeyAlgorithms=+ssh-rsa 
+ # +記法に対応していない古いruby net-sshのため 
+ HostkeyAlgorithms=ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521 
+ # +記法に対応していない古いruby net-sshのため 
+ keyAcceptedKeyTypes=ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521 
```
【備忘】Xiaomi系のデバイスでflutterのテストをする時の設定

忘れるのでメモ

## 手順まとめ
1. 開発者オプションを表示させる
1. 「MIUIの最適化をオンにする」の項目を表示させる
1. 「MIUIの最適化をオンにする」の項目を無効化する
1. 開発者オプションの「USBデバッグ」とか「USB経由でインストール」とかを有効化する

## 開発者オプションを表示させる
`設定→デバイス情報→MIUIバージョンを連打`

## 「MIUIの最適化をオンにする」を表示させる
`開発者オプション→デフォルト値にリセットを連打`
一番下の方にある
JSP/Servlet にリクエスト・レスポンスにヘッダ設定などする前後処理を入れる Filter

JSP/Servlet のリクエスト、レスポンスにヘッダ設定など共通的な処理を入れたいときがある
その際に `javax.servlet.Filter` を `implements` したクラスを作ることで前後処理をできるのでその簡易的な例です

# Filter の実態を作る（これだけでOK）
- `Filter` を `implements` したクラスを作る
- `@WebFilter` の `urlPatterns` に前後処理を入れたいパスを設定（`/*` で全部のパスが対象）
- `doFilter` メソッドに前後処理を記載する, `chain.doFilter` で Servlet や他の Filter を処理する

```java:SampleFilter
package presentation.servlet; //ここは環境に応じたパッケージでOK

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;

/**
 * {@link SampleFilter}
 */
@WebFilter(urlPatterns = "/*")
public class SampleFilter implements Filter {

  /**
   * {@inheritDoc}
   */
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    // 前処理
    System.out.println("before servlet");
    // Servlet, 他のFilter 処理
    chain.doFilter(request, response);
    // 後処理
    System.out.println("after servlet");
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    // フィルタ生成時の共通処理
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void destroy() {
    // フィルタ破棄時の共通処理
  }
}
```

### ヘッダ設定の例

```Java
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    ((HttpServletResponse) response).setHeader("Access-Control-Allow-Origin", "https://xxx.yyy.zzz.com");
    chain.doFilter(request, response);
  }

```
useEffectの依存配列にオブジェクトを指定して無限ループした場合の対処方法

# 依存配列にオブジェクトを指定した場合のuseEffectの挙動について
Reactの使いはじめの頃、おそらく頻繁に出くわす問題にuseEffectでの無限ループ問題がある。
つまずきがちなのが、以下の例のようにオブジェクトをuseEffectの依存配列に指定した場合である。
```js
const Component = () => {
  const [count, setCount] = useState(0);

  const hoge = {id:'xxx',name:'test'};

  useEffect(() => {
    // 無限ループする
    setCount(n => n + 1);
  }, [hoge]);

  return <div>{count}</div>;
};
```

ここではhogeというオブジェクトをuseEffectの依存配列に指定している。
この場合、次のような実行の流れになってしまい、無限ループが発生する。
1. Componentのレンダリングする。このときhogeオブジェクトを生成。
2. useEffectの実行
3. countの状態を+1する
4. countの状態がComponentを再レンダリング。このときhogeオブジェクトを生成。
5. hogeオブジェクトの参照先が変更されたのでuseEffectを再実行
6. 以降、3から5を繰り返す

このようにhogeオブジェクトがレンダリングのたびに生成されてしまうため、hogeオブジェクトの参照先が変更されてしまい、無限ループが発生する。

# 問題の対処
この問題を回避する方法はいくつかあるが一番簡単な回避方法は依存配列にオブジェクトではなく、オプジェクトのプロパティを指定する方法である。

```js
const Component = () => {
  const [count, setCount] = useState(0);

  const hoge = {id:'xxx',name:'test'};

  useEffect(() => {
    setCount(n => n + 1);
  }, [hoge.id]); // 依存配列にhogeオブジェクトのidプロパティを指定。

  return <div>{count}</div>;
};
```

このようにオブジェクトのプロパティを指定しておくとhoge.idのプロパティの値が前のレンダリングの値と変わらない限り、useEffectは実行されない。useEffectの依存配列にオブジェクトを指定して無限ループに陥ってしまった場合の対策方法の参考までに。

# 補足
もう一つの回避方法としてuseMemoを利用する方法もあるがこの文章では割愛
vegetaで投げたリクエストのレスポンスを見る

`vegeta encode`を使えばOK
bodyにはbase64された値が入ってる
```sh
$ echo 'GET https://httpbin.org/get' | vegeta attack -rate=1 -duration=1s | vegeta encode | jq
{
  "attack": "",
  "seq": 0,
  "code": 200,
  "timestamp": "2023-02-28T11:10:17.173759917+09:00",
  "latency": 1229773750,
  "bytes_out": 0,
  "bytes_in": 298,
  "error": "",
  "body": "ewog...",
  "method": "GET",
  "url": "https://httpbin.org/get",
  "headers": {
    "Content-Length": [
      "298"
    ],
...
```

https://github.com/tsenart/vegeta
Oracle Analytics Cloud：ログアウト後のリダイレクト

# はじめに
ユーザがOracle Analytics Cloud（**OAC**）からサインアウトするときに、特定のWebページに誘導します。たとえば、会社のWebページを表示したり、OACのClassicホームページのログインを表示したりします。

# OACからのログアウト
右上のアイコンをクリックして、「サインアウト」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/c09da44b-5fcb-9d00-d99e-221dc36a4345.png)
サインアウト処理が終了後、この画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/36bf740b-52f4-e0ea-4a5a-9d69f13ddf51.png)
再度サインインすると、セルフサービスBIのホームページが表示されます。
デフォルトの動作を確認したところで、サインアウト後に表示するページを変更してみます。

# システム設定で遷移先を指定
「コンソール」の「システム設定」に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/af280888-b711-53e3-7ac4-82227e24e716.png)
「Security」セクションの「Post Logout Redirect URL」に任意のページを指定します。
ここでは、「/ui/analytics」と入力し、クラシックホームページに移動するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/563c4965-ba6d-5ee9-04a6-0facda89c9ec.png)
ログアウトすると、再ログイン用の画面が表示されます。
もう一度ログインすると、セルフサービスBIのホームページではなくクラシック（エンタープライズBI）のホームページが表示されます。

:::note info
この設定は、2023年1月以降に作成されたOACインスタンスで機能します。
それ以前に作成されたOACインスタンスでPost Logout Redirect URLを構成したい場合は、Oracleサポートにサービスリクエストを送信して機能の有効化をリクエストしてください。
:::
Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「ストレージエンドポイントのセキュリティ保護」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「ストレージエンドポイントのセキュリティ保護」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure でのストレージの実装と管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-storage/)
◇対応するモジュール
[ストレージ エンドポイントをセキュリティで保護する](https://learn.microsoft.com/ja-jp/training/modules/configure-storage-accounts/7-secure-storage-endpoints)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「ストレージへのアクセス」](https://qiita.com/fsd-jume/items/52c732918a8393f37c2d)

## ストレージエンドポイントのセキュリティ保護
### Azureサービスへのネットワークアクセス制限
**◆ファイアウォール規則**
・パブリックIPアドレス範囲からのアクセスを制限可能
・ストレージアカウントのパブリックエンドポイントに適用

**◆仮想ネットワーク規則**
・特定のVNet内サブネットからのアクセス制限可能
・Azureサービスリソースへのアクセスを特定のVNetのみに制限可能
⇒Azureサービスエンドポイントを有効にする必要あり

### Azureサービスエンドポイント
・VNetからのトラフィックがAzureのバックボーンネットワーク上を通ってAzureサービスに接続
・VNet上のパブリックIPを使わずにAzureエンドポイントに接続可能
⇒VNetのIDを使用

### ストレージアカウントのアクセス設定考慮事項
・サブネットとVNetはストレージアカウントと同じリージョン/リージョンペアに存在する必要あり

## 次の学習内容
**◆Azure Blob Storage**

https://qiita.com/fsd-jume/items/568c5ce5379e1be718f7

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
OpenShift on AWS(ROSA)のB/Gアップグレードの全自動化に挑戦してみた

# はじめに
2023/1/27(金)に開催された[OpenShift.Run 2023](https://openshift.connpass.com/event/234302/)で、ROSAクラスターのB/Gアップグレードの全自動化デモを実施しました。OpenShift上のアプリのB/Gデプロイではなく、OpenShiftクラスターそのもののB/Gになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/60cd6e79-0df5-d2a8-66cf-984729f978f6.png)


よくお客様への提案で「OpenShiftクラスターはIn-Placeでアップグレードするのではなく新しいバージョンのクラスターを新規で構築してアプリを移行する方式がおすすめです」という話と、「繰り返しの作業は自動化していきましょう」という話をよくするのですが、口だけで言って実現のイメージを全く見せないのもどうかと思い、今回このデモを作成してみようと思いました。

実際に構築してみると考慮しなければならない点が山ほどあり、口で言うほど簡単な道ではないことを思い知らされました。Managed OpenShiftでこれだからSelf-Managedなクラスターだとどれだけ難しいか。。。

ですが、今回のデモでクラスターアップグレードの全自動化は「決して不可能なことではない」ということがわかったので、その感触をみなさんにも共有できたらいいかなと思います。


# 登壇スライド
当日デモの前に説明した資料は以下になります。
[OpenShiftクラスターのアップグレード自動化への挑戦！](https://speakerdeck.com/skitamura7446/openshift-cluster-upgrade-automation)
[![thumbnail](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/8ceab0cf-b6e3-6f42-b8cb-b767d9d97050.png)
](https://speakerdeck.com/skitamura7446/openshift-cluster-upgrade-automation)

# 発表時の動画
2023/2/28時点ではまだ公開されていません。公開されたらここに反映します。

# デモで使ったコード
GitHubにサンプルコードと手順を公開しています。事前にPipelines実行用のクラスターが必要です。ここではAWSにIPIインストールしたOpenShiftクラスターを想定していますが、こちらもROSAで構築してしまって問題ありません。

https://github.com/skitamura7446/openshift-upgrade-automation

# おわりに
スライドにも記載していますが、実際に運用するためにはまだまだ考えないといけない点があります。ですがクラスターアップグレードの全自動化のイメージを掴んだり、最初のとっかかりとして参考にしていただければと思います。
Djangoスタートアップ ～デバッグ環境構築編(vscode)～




`.vscode`フォルダを新規作成。以下の二つのファイルを新規作成して`.vscode`フォルダ内に保存
- `launch.json`★デバッグ実行ファイル
- `settings.json` ★vscodeの設定ファイル

※ブレークポイントでストップできる最小限の構成を紹介するのでデバッグ実行ファイル`.launch.json`の中身のみ掲載


```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Django",★デバッグ実行名（任意）
            "type": "python",★使用するデバッガ
            "request": "launch",★デバッグの実行モード※1
            "program": "${workspaceFolder}/manage.py",★デバッグ対象のプログラムのパス
            "console": "integratedTerminal",結果の出力コンソール
            "args": [★python mange.pyに続く引数
                "runserver",
                "0.0.0.0:8000",
                "--noreload",
//                "--nothreading"
            ],
            "django": true,
            "stopOnEntry": false,
            "justMyCode": false※2
        },
        {
            "name": "Python",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"

        }
    ]
}
```
※1 launchはプログラムの起動時からデバッグ開始, attachは起動しているプログラムに対してデバッグをする

※2 `Breakpoint in file excluded by filters.
Note: may be excluded because of "justMyCode" option (default == true). Try setting "justMyCode": false in the debug configuration (e.g., launch.json).`
の警告がでてブレークポイントで止まらない現象が起こっていたため
`justMyCode : false`で対応

参考記事
https://amateur-engineer-blog.com/vscode-launchjson/
axiosでPOST requestを送信をするとmethodがOPTIONSになってしまう問題の解決

# 問題
フロントはReact18.2.0、Next.js13.2.1、APIはGo言語1.20で開発していました。
axiosでPOST requestをGoのAPIに送信した際にMethodがOPTIONSになってしまって、APIからレスポンスが返ってこなかった。

# 原因
axiosのContent-Typeのデフォルトはapplication/jsonを使っていて、それが原因でAPI側ではMethodがOPTIONSと認識されてしまっていた。
ちなみにjQueryはデフォルトでapplication/x-www-form-urlencodedを使っています。

参考

https://github.com/axios/axios/issues/475#issuecomment-253968037

# 解決策
以下のようにContent-Typeをapplication/x-www-form-urlencodedに変更する。

```javascript
    axios
      .post(
        `${process.env.NEXT_PUBLIC_API_URL}/signup`,
        {
          name,
          email,
          password,
        },
        {
          headers: {
            "Content-Type": "application/x-www-form-urlencoded",
          },
        }
      )
```
チャット風 CSSを作ってみた


シンプルなのチャットUIの例です。HTMLとCSSを組み合わせて、このようなUIを作成することができます。


```html
<div class="chat-container">
  <div class="chat-header">
    <div class="profile-image">
      <img src="https://via.placeholder.com/50x50" alt="profile-image">
    </div>
    <div class="profile-name">
      <h3>Chat</h3>
    </div>
  </div>
  <div class="chat-history">
    <div class="message">
      <div class="message-sender">
        <h4>You</h4>
      </div>
      <div class="message-content">
        <p>Hello, how are you?</p>
      </div>
    </div>
    <div class="message">
      <div class="message-sender">
        <h4>Chat</h4>
      </div>
      <div class="message-content">
        <p>Hi, I'm doing great! How about you?</p>
      </div>
    </div>
  </div>
  <div class="chat-input">
    <input type="text" placeholder="Type your message...">
    <button>Send</button>
  </div>
</div>


```


```css
.chat-container {
  background-color: #f2f2f2;
  border-radius: 10px;
  height: 500px;
  width: 400px;
  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
  overflow-y: scroll;
}

.chat-header {
  background-color: #0084ff;
  color: white;
  display: flex;
  align-items: center;
  padding: 10px;
  border-radius: 10px 10px 0 0;
}

.profile-image img {
  border-radius: 50%;
  height: 50px;
  width: 50px;
}

.profile-name h3 {
  margin: 0;
  margin-left: 10px;
}

.chat-history {
  padding: 10px;
}

.message {
  display: flex;
  margin-bottom: 10px;
}

.message-sender h4 {
  margin: 0;
  margin-right: 10px;
  font-size: 14px;
  font-weight: bold;
}

.message-content {
  background-color: white;
  padding: 10px;
  border-radius: 10px;
}

.chat-input {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  border-top: 1px solid #ddd;
}

.chat-input input[type="text"] {
  flex: 1;
  padding: 10px;
  border: none;
  border-radius: 10px;
}

.chat-input button {
  background-color: #0084ff;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 10px;
  margin-left: 10px;
  cursor: pointer;
}

.chat-input button:hover {
  background-color: #0066cc;
}


```
validateDOMNesting が出たがどこだかわからない〜！！が５秒で解決する方法


```
Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
```

こういうエラーが出るときがある。
簡単に言えば
「 `<p>` の子要素に `<div>` 入れるな！！ それはブラウザルール違反！！！」
（は？動くが？）という気持ちになるが、一応今のHTMLの仕様上はそうなってる。
ほかには `<table>` タグに `<tbody>` がなかったり、 `<a>` の中に `<a>` がネストしてたりすると発生する。



参考：

https://qiita.com/k_kazukiiiiii/items/e1c45c532b8baeb0c888


https://note.crohaco.net/2018/react-errors-warnings/




### は？そんなDOM要素作って無いんだが？

これもよくある。何らかのライブラリが pタグで作っているのが原因であり、ゆえに原因行が特定出来ないのだ。


解決方法というか調査方法はシンプルで、Chrome等のデバッグコンソールで調べるだけ。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34573/69a08386-9960-7207-44bf-cf5a79fdf15e.png">

Reactのソース上でどのようなDOM(jsx)でマークアップされていようが、最終的に出るHTMLの方を調べてしまえばいい。
ここでは、閉じタグ `</p>` で検索するのがコツだろうか。
iOS16.4から利用できるプッシュ通知まとめ

# iOSのWebプッシュ通知調査

- macOSですでに対応しているPWAは自動的にiOSにも対応するらしい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200094/ef1a1ee9-06a8-519b-c8a8-46fa99aa6a3e.png)

- ↓のようにくる？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200094/4f7cc3d5-e326-746a-6a16-06ba243f060c.png)

- Webの規約に従ったコーディングをした場合は、特にSafari専用の設定は特に必要ない？

- サーバー上のプッシュエンドポイントを厳密に管理する場合、「.push.apple.com」のサブドメインを許可する必要あり

- PWAアプリとしてホーム画面に追加する必要がある。

- モバイルアプリと同じような感じでPWAのプッシュ通知の設定ができるっぽい。

- ドメイン全体で動作するJSのユニット（Service Worker）をインストール→Webアプリはプッシュのリクエスが可能になる。またJSで通知を許可したかの判別ができる。（JavaScript Push APIというのがある？）

- 通知にはタップしたあとに遷移したいURLなどを含めることができる。（新しいタブで開くとかも指定できる？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3200094/4a16875e-06ed-0cc1-2b7d-280c37ff52fe.png)

- 明示的なジェスチャーなしにプッシュを要求できない？


## 参考
https://developer.apple.com/videos/play/wwdc2022/10098/
https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/
https://webkit.org/blog/12945/meet-web-push/
convertで複数画像を並べる

自分用のメモです。

# 1. 横に並べる
```sh
% convert +append column1.jpg column2.jpg column3.jpg row.jpg
```

# 2. 縦に並べる
```sh
% convert -append row1.jpg row2.jpg row3.jpg column.jpg
```

- Imagemagick には `montage` もあるが、なぜか resize 等でサイズの指定ができなかった。
APIのエンドポイント設計で気をつけていること~ポエム編~

## この記事は？
日々の業務のなかで、フロントエンドチームの立場でAPIを利用したりバックエンドAPIチームの立場でAPIを設計実装改修したりする私のポエムみたいなものです。
みなさまが日々の業務に疲れたとき、誰かのポエムが見たいときにどうぞ😌
※めちゃくちゃ何番煎じかって内容を含んでます

### 改めて自己紹介
バックエンド歴多めの一応ハイブリッドエンジニア。
雑に業務経験の言語やツールを列挙すると下記な感じ。
* バック:Java,PHP,Go,VB.Net,C#,VBScript...
* フロント:javascript,typescript,React
* アプリ:Swift
* AWS:EC2,Lambda,ELB(CLB/ALB),ECS(on Fargate),S３,RDS(Aurora),Amplify,Lightsail,Code3兄弟
* GCP:GAE,GKE,あんまり、、、

基本スタンスは業務で必要なものは使いながら覚える感じ。
最近作って面白かったのはPuppeteerを使ったラッパーAPI。

とあるmPOSシステムに携わってから人生が転がり始めて、人のつながりのおかげでフリーランスになってバックエンドだけじゃないエンジニアになって今は株式会社スリーシェイクにて日々奮闘中。

## 設計について
エンドポイント設計はほんとにムズカシイ、その現場やチームの関係性やWebサービスの性質によるとしか言いようがない。
。。。で終わってもしょうがないのでポエム的に思うことを書いてみる。

エンドポイントと言っても2つくらい考えどころがありますよね。
* 基本のリソース部分や操作に関すること
* リソース特定や特殊な操作にパスパラメータやクエリパラメータをどう使うか

### リソース？操作？
原則、操作するリソースを複数形にすべし、メソッドは操作を表すべし、そうですね。
でも全部それで済むほど単純じゃないことがほとんど。。。
`GET /books/1?sort=title&order=asc`
シンプルなものはこんな感じになると思いますが、例えば見積書とか作るとき。
```
POST /estimates (作成)
POST /estimates/download (ダウンロード)
POST /estimates/print (印刷)
```
どうでしょう？**見積書リソースの作成であるPOST**と**実際の見積書のダウンロードや印刷のためのPOST**でエンドポイントを分けたいがために`download`や`print`といったものがパスに含まれています。
一口に操作をメソッドで表現すべき、といってもここらへんどうやって表現するかは人によったりプロジェクトによったり言語によったりになると思います。
まぁ言語仕様をエンドポイントに反映させるな、という原則もありますが笑

ちなみに上記は実際のプロジェクトで私はこのようにしましたという例です。
みなさんはどうしますかね？
クエリパラメータに実際の操作を入れたりする手段もあるとは思いますが、ハンドラ側の分岐が発生しそうでメンテナンス性悪くなりそうなので私は採用しませんでした（ポエム）

### パスパラメータ？クエリパラメータ？
対象のリソースを特定する手段をどちらにするか？ですが、私は、というかほとんどの人は恐らく下記の方針にしていると思います。
パスパラメータには「対象のリソースを**一意に**特定できるものを入れる」
ですね。

例として本の取得APIエンドポイントについて考えたときに一覧が`{ドメイン}/books`として、
bookのidを指定したリソースの取得を下記のどちらにするか、という話です。
```
{ドメイン}/books/1 (path)
{ドメイン}/books?id=1 (query)
```
めちゃめちゃ当たり前かもですが、pathのほうが望ましいです、場合によりますが。
これは実際のフロントのURLに照らし合わせても同様の例が多いですよね
Amazonの商品ページとか
https://www.amazon.co.jp/gp/product/B07NDNGQ5H

パスパラメータについては上記の通りで、じゃあクエリパラメータはというとパスパラメータと逆で
「クエリパラメータにはリソースを**一意に**特定するものを入れない」
ですね、わかりやすい例でいうと、**並べ替え**と**検索**です。
`GET /books/1?sort=title&order=asc`
`GET /books/1?author=alice`
みたいな。
検索はQiitaの検索画面も同様な構成でした。
https://qiita.com/search?q=Qiita&sort=created
他にも、画面上で複数チェックして削除したい、という用途で
`DELETE /books?id=1,3,4,5`
のような、カンマ区切りで複数指定するという使い方もあります。

### 私が思うのは（ポエム）
「リソース一覧（たとえば`/books`のような）のエンドポイントには全て**並べ替え**と**検索**のクエリパラメータを用意すべき」
です。
実際の業務であった話で、下記のようなことがありました。

フロントチーム:
* データの並び順はサーバーでID順にして返してほしい、フロントで並べ替えの処理をするのは性能的にも不利になることが多いから

わかる、めっちゃわかる。
でも、フロントだけで並べ替えを完結させたいときもあるんじゃない？
一覧のテーブルヘッダのクリックで昇順降順とか。
ページングとか複数選択とか絡んでくるとその限りじゃないけど、フロントは絶対並べ替えしません、というのも違うよなぁと思い。

上記に対するAPI側の答えとしては
* クエリパラメータに`sort`と`order`つけてくれればそのとおり返すよ
と至ってシンプルなのでしたが。

## 終わりに
まぁほんと、上記で書いたようにAPI側の対応で済んじゃう話ではあるんですが、フロントとAPIどっちがどっちが、というよりはどっちもできて選択できたり、場合によって誰がどうするとか柔軟にサービス作っていきたいよね、と思ったところでした。
そういえば今までのとこでも同じようなやりとりがあったなぁ、どっちがどうするとか、チームの関係性とかサービスの性質もあるけど、改めて設計について考えさせられるなぁ、と思い、ポエムと称して今回書いてみた次第です。

あ、APIがアプリから呼ばれるとなるとまたバージョン違いの話とかで色々面倒になってくるという話も書きたかったんですが、思いのほか長くなってしまったので、それはまた気が向いたときにポエムとして書ければなと思っています。
うわっ…私のDockerコンテナ、落ちるの遅すぎ…?

# はじめに
dockerの研修をやってた時に、「うーん、毎回docker-composeを使っててnodeコンテナだけ落ちるのに10秒以上かかるんだよな～なんでだろ～」で解決方法を見つけたので紹介したいと思います。

## 再現
ymlファイルを用意しました。
```:docker-compose.yml
version: '3.9'
services:
  node:
    image: node:18-slim
    tty: true
    ports: 
      - '4000:4000'
    volumes:
     - ./node:/node
```
コンテナを起動して状態を見てみる。
```
root@sun33 /home/sun33/qiita/init # docker compose up -d
[+] Running 2/2
 ⠿ Network init_default   Created                   0.0s
 ⠿ Container init-node-1  Started                   0.4s
root@sun33 /home/sun33/qiita/init # docker-compose ps
NAME                COMMAND                  SERVICE             STATUS              PORTS
init-node-1         "docker-entrypoint.s…"   node                running             0.0.0.0:8000->8000/tcp, :::8000->8000/tcp
```
コンテナを破壊します。
```
root@sun33 /home/sun33/qiita/init # docker compose down
[+] Running 2/2
 ⠿ Container init-node-1  Removed                 10.3s
 ⠿ Network init_default   Removed                  0.2s
root@sun33 /home/sun33/qiita/init #
```
十秒もかかるなんかおかしい。なんだろう強制終了した感じ？

## 原因
PID 1 問題のようでうまく終了シグナルが送れていないのが原因っぽい。
以下の記事がとてもわかりやすかったです。

https://text.superbrothers.dev/200328-how-to-avoid-pid-1-problem-in-kubernetes/

## 解決方法
`init`を追記する！
```:docker-compose.yml
version: '3.9'
services:
  node:
    image: node:18-slim
    tty: true
    init: true
    ports: 
      - '4000:4000'
    volumes:
     - ./node:/node
```
コンテナをもう一度破壊して見ます。
```
root@sun33 /home/sun33/qiita/init # docker compose down
[+] Running 2/2
 ⠿ Container init-node-1  Removed                  0.3s
 ⠿ Network init_default   Removed                  0.2s
root@sun33 /home/sun33/qiita/init #
```
正常に破壊できました。

## まとめ
今まで待ってた10秒何だったんだってぐらい早くなりました。
nodeコンテナ２つ使ってたので毎回20秒待たされていました…
「あれ、この挙動おかしい？」って疑問に思ったら、調べることが重要ですね。おしまい。
Chromeでレスポンスヘッダーの書き換えができるようになった。

## 概要
最近のChromeのアップデートでレスポンスヘッダーの書き換えができるようになっていました。まだExperimentの段階ですが、Chrome v111以降で使うことができます。

https://github.com/ChromeDevTools/rfcs/discussions/4



## 動作確認用ページ

以下のページでCORS（Cross-Origin Resource Sharing）エラーのサンプルがあるため、これを利用します。

https://cors-demo-devtools.glitch.me/


コンソールでエラーが確認できレスポンスヘッダーには `Access-Control-Allow-Origin`が無いことがわかります。
![スクリーンショット 2023-02-27 9.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/d134d9be-88cb-4b63-bb97-c38c03df3f3d.png)


ページとしても「Cannot load resource.」のエラー文言が表示されている状態です。

![スクリーンショット 2023-02-27 9.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/ef9f5341-23d1-e5f1-4e0e-c5ddfb08d089.png)

## 設定手順


設定のExperimentsから `Local overides for response headers`を有効にします。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3134373638392f64303138643239352d333630652d663539632d303964382d6636313762303634316665322e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/a1dd1eaf-4d22-04f3-b9dc-44d90900a692.png)


Networkパネルから任意のファイルを選び、 `Add header` を選択しフィールド名と値を設定します。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3134373638392f64333439653035612d323365372d383635652d303465392d3262386135333131626365612e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/e4b0cf98-716b-9dfd-918b-ed3f76749b93.png)

初回の設定時には設定情報を保存するためにローカルの任意のフォルダを選択する必要があります。

![スクリーンショット 2023-02-28 9.45.54（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/844cae55-a067-f58d-727c-fd22227689fc.png)


今回はCORSを有効にするため、`Access-Control-Allow-Origin`を `*`として設定しました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3134373638392f35396434393562392d313831352d363531642d303338372d3935636261393536353162322e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/ceeba597-7bf6-35f8-4c16-8c27ca929049.png)

なお、Sourcesパネルから.headersファイルを直接編集することでURIのルール設定をすることもできます。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3134373638392f38386661306264662d333465652d393338652d643634632d6530343734653063616365382e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/4f54c1ad-29b2-3caf-3ee6-11edab64d834.png)

設定後はXHR2として動作するようになったので、APIから返却された内容を表示することができました。

![スクリーンショット 2023-02-27 9.51.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/46c4b9bf-8daf-b682-9209-c988e7cc75ae.png)


## おわりに
これまでもSourcesパネルでレスポンスボディーの書き換えができましたが、レスポンスヘッダーの書き換えができるとCross-Origin Resource SharingやContent Security Policy周りのデバッグが捗りそうです。
わざわざCharlesを立ち上げる必要もなくなりますね。
VScodeとXcodeのショートカットキー対応表（Mac）

## 概要
VScodeとXcodeでよく使うショートカットキーの対応表を作成しました。

前提としてOSはmacOSであり、各エディタのバージョンは以下です。
VScode: 1.75.1
Xcode: 13.2 

## コード編集系
| コマンド | Vscode | Xcode |
| -------- | -------- | -------- |
| 指定した行に移動 | control + g | command + l |
| コードジャンプ | f12 | command + control + click |　
| コードジャンプ前に戻る | control + - | command + control + ← |　
| 変数名をまとめて変更 | command + shift + l | command + control + e|　 
| コメントアウト/コメントアウト解除 | command + / | command + / |　
| インデント追加 | command + ]  | command + ] |
| インデント削除 | command + [ | command + [ |
| コード整形（インデントを整える） | shift + option + F | control + i |

## ファイル操作系
| コマンド | VScode | Xcode |
| -------- | -------- | -------- |
| ファイル名を検索して移動 | command + p | command + shift + o |
| 戻る | control + - | command + control + ← |
| 進む | control + shift + - | command + control + → |

## 検索系
| コマンド | VScode | Xcode |
| -------- | -------- | -------- |
| ファイナル内検索 | command + f | command + f |
| プロジェクト内検索 | command + shift + f  | command + shift + f |
| 次の検索結果に移動 | command + d | command + g |
| ファイル内のシンボル/メソッドを検索 | command + shift + o | control + 6 |

## その他
| コマンド | Vscode | Xcode |
| -------- | -------- | -------- |
| 設定を開く | command + ,| command + , |
| 左サイドバー表示/非表示 | command + b | command + 0 |
| ヘルプ | command + shift + ? | command + shift + ? |
| フルスクリーン/フルスクリーン解除 | command + control + f | command + control + f |
Obsidianのvimでinoremap jj <ESC>が効かない問題の回避策

## 起こった問題
[Obsidian](https://obsidian.md/)に[vimrcをサポートするプラグイン](https://github.com/esm7/obsidian-vimrc-support)を導入した。
このプラグインを使うことで、Vaultのルートディレクトリに置いた`.obsidian.vimrc`を読み込んでくれるようになる。
しかし、普段vimで使っている「`jj`でインサートモードから抜ける」キーマッピングが効かない：
```
inoremap jj <ESC>
```

## 原因
`.obsidian.vimrc`の書き方に問題があった。
以下のような書き換えが必要：
1. `inoremap`ではなく`imap`を使う
2. `<ESC>`ではなく`<Esc>`と書く

## 解決
`.obsidian.vimrc`に以下のように書くことでキーマッピングが効くようになった：
```
imap jj <Esc>
```

## 参考
https://github.com/esm7/obsidian-vimrc-support/issues/18
サーバーを基本からまとめてみた

## サーバーとは？

サーバー利用者の要求に応じて、対応するデータを供給するシステムのこと

## サーバーの種類
##### ①共用サーバー

レンタルサーバーのこと

他人数で共有

- 各利用者の費用負担が軽減される
- 障害時、影響を受ける人が多い
- サーバーカスタマイズが困難

##### ②専用サーバー

一人が占有(ほぼ企業が使用する)

主に会社の社員情報や顧客・ビジネス情報などを管理するサーバーを作成する時に
専用サーバーが使われることが多い

　
- 他の利用者の影響を受けない
- 自由にカスタマイズ可能
- サーバーの運用・構築は自己責任


##### ③VPS(仮想サーバー)

VPS(仮想サーバー)は１台のサーバー上に構築されたVPS(仮想サーバー)を利用するもの
１台のサーバー上にはいくつもの仮想サーバーを作成できるので、仮想サーバーを利用する場合は、共有サーバーのように仮想サーバーをレンタルすることになる

仮想サーバーは利用者に対してそれぞれ構築されているので、OSやアプリケーションなどカスタムがしやすい

##### ④クラウドサーバー

クラウドサーバーは文字通り、インターネットなどのネットワーク上にあるクラウドに構築されたサーバーのこと　例：AWSなど

- カスタマイズ性が高い
- 費用は利用した分だけ

## サーバーの役割

##### ①Webサーバー

WebサイトやWebアプリケーションなど運営する際に必要なサーバー
利用者からの要求に応じて要求に沿ったデータをweb上に送り返す役割がある

##### ②Mailサーバー

メールサーバーは名前の通りメールの送受信を提供するサービスに活用されている
SMTPサーバーと受信を担当しているPOPサーバーに分けることが可能

SMTPサーバーとは『Simple Mail Transfer Protocol Sever』の略で、
送信したメールを指定のアドレス先にしっかり送り届けるのが役割

POPサーバーとは、『Post Office Protocol Server』の略で、送られてきたメールを認証して受信する役割がある

##### ③Databeseサーバー

利用者の要求に応じてデータベース上のデータを送り返すためのサーバー

##### ④DNSサーバー

DNSサーバーとは、『Domain Name System Sever』の略で、Webサイトなどの利用者の要求に応じてIPアドレスとドメインを結び付ける役割がある

IPアドレスはWeb上の住所のようなもの
ドメインはIPアドレスに名前をつけてわかりやすくしたもの

##### ⑤FTPサーバー

FTPサーバーとは『File Transfer Protocol Sever』の略で、
『ファイル転送プロトコル』とも言われるがwebサイトのデータの更新や上書きファイルのアップロードやダウンロードに必要

FTPはファイルの送受信をする際のルールのことで、FTPサーバーはそのルールを使用してファイルの送受信を可能にする



## 参考サイト
[サーバーとは？仕組みや種類・役割・用途をわかりやすく解説](https://www.youtube.com/watch?v=bPJuQI5Wdz0)
はじめてのGitHub Pages

## GitHub Pagesとは
>GitHub Pages は、GitHub のリポジトリから HTML、CSS、および JavaScript ファイル を直接取得し、任意でビルドプロセスを通じてファイルを実行し、ウェブサイトを公開できる静的なサイトホスティングサービスです。 

[引用元：GitHub公式](https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages)

要するに、無料でwebページを公開できるというGitHubの１つの機能です。
GitHub Pagesサイトの例は、下記リンクにリポジトリが置いてあるので、見てみると面白いかもしれません。

https://github.com/collections/github-pages-examples

## 使い方

### ①GitHubのアカウント作成
まずはGitHubのアカウントを作成する必要があるので、無料でアカウントを作成しましょう。
https://github.com/

すでにGitHubのアカウントを持っている方は、ログインしてください。

### ②GitHubにてリポジトリの作成
GitHub Pagesでwebページを公開するには、リポジトリを作成する必要があります。
リポジトリとは、webページやwebアプリケーション等を、GitHubで管理するための箱のようなものです。

以下リンクからリポジトリを作成しましょう。
（右上の+アイコンをクリック → `New repository`をクリックしても同じ画面に行けます）
https://github.com/new

`Repository name`の部分に任意のリポジトリ名を入力しましょう。

このリポジトリ名は、後ほど公開するwebページのURLになります。
（`https://アカウント名.github.io/リポジトリ名`のような感じになる）

なお、webページを公開するので、`Private`ではなく`Public`で作成してください。
![pages_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191578/b641b46c-7b19-db1e-a259-e72641d104a5.png)




### ③表示したいファイルの追加

GitHub Pagesで公開したいファイルを、作成したリポジトリ内にアップロードしましょう。

HTML/CSS/JavaScriptファイルをそれぞれアップロードすればOKです。
（本記事はHTML/CSS/JavaScriptの扱い方に関する記事ではないため詳細は割愛します）


### ④GitHub Pagesの公開
該当のリポジトリ内にファイルをアップロードできたらいよいよ公開です。

リポジトリ画面の右上にある`Settings`をクリックします。
![pages_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191578/5b7b1e64-6ee4-4040-aad1-771c6b5b1b40.png)

Settings画面の左側メニューにある`Pages`をクリックします。
![pages_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191578/483508d2-f4bf-1bf9-3a52-d72f8929223e.png)

`Branch`部分を任意のブランチ（基本的にはmainブランチだと思います）に変更して、`save`をクリックします。
![pages_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191578/9072924f-dafd-d733-e763-e0e8ec8c60b4.png)

上記操作で完了です。
しばらくすると、`Visit site`と表示されるので、そちらをクリックするとGitHub Pagesを使って公開したwebページを見ることができます。
![pages_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191578/7beb5268-da8e-cbc3-75ce-7247dce55d3a.png)

お疲れ様でした。

とても手軽に静的なページを公開できるので、便利だなと思います。
サクッと試したい時などにぜひお試しください。

## 参考資料
https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages
StaticCheckは同じパッケージ内のdeprecated要素の参照を無視する

# TL; DR

- 廃止予定(deprecated) の関数、変数を同じパッケージ内から参照しても `staticcheck` は警告しない
- この挙動は意図的（`staticcheck` は廃止予定の要素が「**外部から参照される**」ことを禁止している）

```go
// DeprecatedFunc shows some messages.
//
// Deprecated: should not be used.
func DeprecatedFunc() {
	fmt.Println("hoge")
}

// NewFunc shows some messages.
func NewFunc() {
	DeprecatedFunc() // ここはstaticcheckで警告されない！！
}
```

# はじめに

staticcheckは、廃止予定の関数、変数を参照している箇所を警告してくれます。golangci-lintに標準で入っているので使っている方も多いと思います。

Goでは廃止予定の要素には `// Deprecated: ...` というコメントを書く決まりがあるため、この行を検知しています。

https://github.com/golang/go/wiki/Deprecated

```go:foo/foo.go
package foo

import "fmt"

// DeprecatedFunc shows some messages.
//
// Deprecated: should not be used.
func DeprecatedFunc() {
	fmt.Println("hoge")
}
```

```go:main.go
package main

import "example.com/foo"

func main() {
	foo.DeprecatedFunc()
}
```

```bash
$ staticcheck
main.go:6:2: foo.DeprecatedFunc is deprecated: should not be used.  (SA1019)
```

一方、冒頭のように同じパッケージ内であれば廃止予定の要素を参照しても警告されません。
最初はバグかと思いましたが、この仕様は意図的なものでした。

# パッケージ内の参照を無視しない理由

https://github.com/dominikh/go-tools/issues/508#issuecomment-500682935

> 廃止予定API利用のチェックは、同じパッケージからの廃止予定のものの利用を明示的に許可しています。つまり、新しい、廃止予定ではないAPIを内部的に廃止予定APIの上に構築することができます。何かが廃止予定であるということは、別のパッケージやサードパーティーの利用者にしか影響しません。廃止予定の方の（埋め込み）フィールドを持つことも問題ない場合もあります。
> 
> The check for use of deprecated APIs explicitly allows the use of deprecated things from the same package. After all, a new, not deprecated API can internally be built upon a deprecated API. That something is deprecated only affects other packages, 3rd party users. Even having (embedded) fields of deprecated types can be fine sometimes.

確かに、新APIへの過渡期には旧APIの実装を参照することがあると思います。「レガシーコード改善ガイド」に登場した「スプラウトメソッド」の話を思い出しました。

# おわりに

以上、staticcheckのdeprecatedチェックの仕様についてでした。内部でさえ使いたくないものについては、レビューで確認するしかなさそうです。
M1 Macbook Proにasdfを導入して複数バージョンのPHPをインストールする

# asdf導入

## インストール
- brewを使ってインストール
```bash
brew install asdf
echo -e "\n# for asdf\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ~/.zshrc
```

## 基本操作
- 使用できるプラグインを表示
```bash
asdf plugin list all
```
- プラグインのインストール
```bash
asdf plugin add <name>
```
- 使用できるバージョンの表示
```bash
asdf list all <name>
```
- バージョンのインストール
```bash
asdf install <name> <version>
```
- 使用するバージョンの指定
```bash
asdf global <name> <version>
or
asdf local <name> <version>
```

# PHPインストール
- 依存関係のあるライブラリ群をインストール
	- 不足している際に発生するエラーは後述。
```bash
brew install bison re2c pkg-config libiconv oniguruma libzip
```

- phpインストール
```bash
asdf plugin add php
asdf list all php
asdf install php 8.2.3
```

## エラー
### 依存関係のあるライブラリが不足している場合
- bison
```bash
configure: error: bison 3.0.0 or later is required to generate PHP parsers (excluded versions: none).
```
- re2c
```bash
configure: error: re2c 0.13.4 is required to generate PHP lexers.
```
- pkg-config
```bash
configure: error: in `/var/folders/d0/88syyrq97098_c1mx8pr224jm1137v/T/php-src-php-8.2.3':
configure: error: The pkg-config script could not be found or is too old.  Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config.
```
- libiconv
```bash
configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>
```
- oniguruma
```bash
configure: error: Package requirements (oniguruma) were not met:
```
- libzip
```bash
configure: error: Package requirements (libzip >= 0.11 libzip != 1.3.1 libzip != 1.7.0) were not met:
```
進捗をこまめに更新しないプロジェクトのことを考えてみた

# はじめに
今までそれなりの数のプロジェクトに関わってきたが、進捗を更新しない、それこそ言われないとしないようなプロジェクトと、こまめに(作業の開始、経過、終了、etc毎)更新するプロジェクトの違いが何かを考えてみた。

# 原因
エクセルでスケジュール管理していると更新しない。

# 対策
エクセルやめろ。
新しいGitHub検索で空白を検索できるようになりました

スペースを含めて検索できます

Before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/fc9688df-f8b4-2af4-5935-265c405e6557.png)

After
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/38467121-0b4d-acd4-9d6f-64f8b25e25cf.png)

### 有効化手順

Enableを押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/24827526-c968-5c75-170b-24d169e71d80.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/c414b538-e56c-9d56-1de7-047c608db7a4.png)
ネットワークと基本からまとめてみた【基本】

## 参考サイト
[ネットワークとは何かやLAN・WAN・インターネットの違いを理解しよう【高校情報Ⅰ】4-1 ネットワークの基本](https://www.youtube.com/watch?v=iWfKp-Qv7Xk)
スクリーンショットを撮るために、まっさらなChromeを起動する方法

Google Chromeをスクリーンショットを撮るためだけに起動する場合、ブックマークや拡張機能などの設定を無効にすることが望ましい場合があります。以下のコマンドを使用することで、ブックマークや拡張機能などを無効にした状態で、Google Chromeを起動することができます。

## まっさらなChromeを起動するコマンド

```sh
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
	--disable-extensions \
	--disable-plugins \
	--bwsi \
	--no-first-run \
	--no-default-browser-check \
	--user-data-dir=/tmp/temporary-chrome-profile \
	--disable-features=Translate \
	--window-size=800,600
```

## 各オプションの解説

- `--disable-extensions`: このオプションは、Google Chromeの拡張機能を無効にします。 
- `--disable-plugins`: このオプションは、Google Chromeのプラグインを無効にします。 
- `--bwsi`: このオプションは、ブラウザーウィンドウをゲストモードで開きます。このモードでは、ブラウザがローカルにデータを保存しません。 
- `--no-first-run`: このオプションは、Google Chromeの初回起動時に表示されるウィザードをスキップします。 
- `--no-default-browser-check`: このオプションは、Google Chromeがデフォルトのブラウザであるかどうかを確認するチェックを無効にします。 
- `--user-data-dir=/tmp/temporary-chrome-profile`: このオプションは、一時的なユーザーデータディレクトリを指定します。デフォルトでは、Chromeはホームディレクトリに新しいプロファイルを作成しますが、このオプションを使用することで、一時的なディレクトリを指定することができます。 
- `--disable-features=Translate`: 翻訳機能を無効にします。翻訳アイコンが表示されなくなります。![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/3842ebb7-a627-420f-a912-bee9f986eee2.png)
- `--window-size=800,600`: このオプションは、ブラウザーウィンドウのサイズを指定します。この例では、ウィンドウサイズを幅800ピクセル、高さ600ピクセルに設定しています。

これらのオプションを指定することで、Google Chromeを拡張機能やプラグインなし、ゲストモードで、初回起動時のウィザードをスキップし、一時的なプロファイルを使用し、特定のウィンドウサイズで起動することができます。
docker-composeを詠唱する黒魔術「Makefile」入門

# はじめに
dockerの研修をやってた時に、「うーん、docker-composeって毎回打つのめんどくさい。なにかいい方法ないかな～」で見つけたMakefileを紹介したいと思います。

# Makefileとは？
**Make**というプログラムのビルド作業を自動化するツールのルールを記述したテキストファイルのことです。

https://linuc.org/study/knowledge/542/#:~:text=%E3%80%8CMakefile%E3%80%8D%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%80%81,%E9%96%A2%E4%BF%82%E3%82%92%E8%A8%98%E8%BF%B0%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

## 魔導書(Makefile)の作成
**Makefile**という名前のファイルを作成して以下の内容を保存します。
```:Makefile
.PHONY: setup up d b ps node

setup:
	@make up
	@make ps
d:
	docker compose down
up:
	docker compose up -d
ps:
	docker compose ps
node:
	docker compose exec node bash
```
makefileの中身ですが
`.PHONY`を記載しないとコマンドと同じ名前のファイルがある場合衝突してしまいコマンドが実行できません。(ハマりました。)
`@make コマンド`を使うことでコマンドをまとめて扱うことができます。
`@`はエコーしないって意味だそうです(コメント頂きましたありがとうございます。)
コマンド内容のインデントはTabを使ってください。半角スペースだと動きません。

## 魔術の詠唱(makeコマンドの実行)
`make コマンド`で使用することができます。
コマンドを使ってみるためにymlファイルを用意しました。
```:docker-compose.yml
version: '3.9'
services:
  node:
    image: node:18-slim
    tty: true
    init: true
    ports: 
      - '4000:4000'
    volumes:
     - ./node:/node
```

実際にwslで使ってみましょう。
`make setup`でコンテナを立ち上げて、コンテナ状態を見てみます。
```
root@sun33 /home/sun33/qiita/makefil # make setup
make[1]: Entering directory '/home/sun33/qiita/makefile'
docker compose up -d
[+] Running 2/2
 ⠿ Network makefile_default   Created                                                                                  0.0s
 ⠿ Container makefile-node-1  Started                                                                                  0.5s
make[1]: Leaving directory '/home/sun33/qiita/makefile'
make[1]: Entering directory '/home/sun33/qiita/makefile'
docker compose ps
NAME                COMMAND                  SERVICE             STATUS              PORTS
makefile-node-1     "docker-entrypoint.s…"   node                running             0.0.0.0:4000->4000/tcp, :::4000->4000/tcp
make[1]: Leaving directory '/home/sun33/qiita/makefile'
root@sun33 /home/sun33/qiita/makefile #
```
２つのコマンドを実行できましたね。
`make node`でnodeコンテナ内に入ってみます。
```
root@sun33 /home/sun33/qiita/makefile # make node
docker compose exec node bash
root@333c33c333c:/#
```
もし同じファイルがあって`.PHONY`を記載していないとコマンドが実行できません
```
root@sun33 /home/sun33/qiita/makefile # make node
make: 'node' is up to date.
```


ctrl + D または `exit`コマンドでコンテナ内から出て、コンテナを破壊して見ます。
```
root@sun33 /home/sun33/qiita/makefile # make d
docker compose down
[+] Running 2/2
 ⠿ Container makefile-node-1  Removed                                                                                  0.4s
 ⠿ Network makefile_default   Removed                                                                                  0.2s
root@sun33 /home/sun33/qiita/makefile #
```

makeコマンドを使うことでdocker-composeの長いコマンドを打たずに楽にコマンド操作ができるようになりました。

## windowsの場合
windowsの場合デフォルトでmakeコマンドが使えません。
makeをinstallして設定してあげてください。

https://qiita.com/BARANCE_TW/items/c7ffdb311df84d47bddd
## まとめ
もうmakeコマンド楽すぎて手放さなくなってしまいました。
とっても便利なので、いろいろコマンドを定義して使ってみてくださいね。おしまい。