OmniAICreator/Qiita-1.07M huggingface dataset:
Farfalle と Ollama で LLM を利用した検索エンジンを試す

# はじめに

Farfalle は Perplexity の様なAI搭載の対話型検索エンジンです。LLMとして、ローカルの Ollama が利用できます。また、当初は検索に Tavily などのAPI keyが必要でしたが、ローカルで動作するメタ検索エンジン [SearXNG](https://github.com/searxng/searxng) でも動作する様になったため、完全ローカルで実行できます。

https://github.com/rashadphz/farfalle

# セットアップ

## インストール

公式リポジトリで紹介されている Docker Compose を使う方法を少しアレンジして、インストールします。

```sh
git clone https://github.com/rashadphz/farfalle.git
cd farfalle
cp　docker-compose.dev.yaml　docker-compose.yaml
```

`docker-compose.yaml` を以下の様に修正・追記して、検索エンジンを searXNG にするとともに、ollama が同時に起動する様にします。

```yaml
services:
  backend:
  # ... (中略) ...
  environment:
    # ... (中略) ...
    - SEARCH_PROVIDER=${SEARCH_PROVIDER:-searxng} # tavily から変更
  # ... (中略) ...
  ollama:
    image: ollama/ollama
    container_name: ollama
    ports:
      - 11434:11434
    volumes:
      - $HOME/.ollama:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
  ```

公式の docker image もありますが、searXNG を別で起動しておく必要があるなど面倒なので、上記の様に Docker Compose を使う方法が楽だと思います。

修正が済んだら、起動します。

```sh
docker compose up -d
```

## 設定

`http://localhost:3000/` にアクセスします。

![farfalle_01](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/101a02eb-bf2e-28b0-9b32-c08410414814.png)

右下が `Local` になっている事を確認し、その上のモデル名部分を押すと、モデル選択ができます。

![farfalle_02](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/29b68c82-0794-0fc4-9adf-d2bbd36c6175.png)

'Local' (Ollama)の場合、 `llama3`, `gemma`, `mistral`, `phi3:14b` が利用できます。
注意点として、ここに表示されているモデルのみが利用でき、自由にモデルを選択することはできません(2023/6/11時点)。モデルの種類が固定されているのは、性能を担保する関係で理解できなくもありませんが、量子化タイプも選べないのは少し残念です。Ollamaはデフォルトで Q4_0 を使用するので、新しい量子化方式の Q4_K_M が使えなかったり、メモリに余裕があっても Q5 以上が使えなかったりするのは勿体ないですね。Ollama の CLI で cp をして名前を上書きすればどのモデルでも使えると思いますが、未確認です。

2024/6/16 追記:
[LiteLLM]('https://github.com/CerebriumAI/litellm) を使うと上記モデル以外にも様々なモデルが使用できるようになりました。


# 検索実行

NVIDIA の CEO である Jen-Hsun Huang 氏について尋ねてみました。

![farfalle_03](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/8b8c68bc-20ae-2d08-4abc-6927324957ab.png)

生年が変になっていますが、それ以外は合っていそうです。情報源へのリンクがあるので、内容の確認はしやすくなっています。また、一般的な検索エンジンと同様に関連画像も表示されています。

![farfalle_04](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/fac74712-b843-e141-15fc-f627d88d4e12.png)

関連する検索文が表示されるので、続けて質問してみたところ、(多分)正しく答えてくれました。

![farfalle_05](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3791334/f18263af-4f40-ea3b-289e-3695b974e0d5.png)

# まとめ

Perplexity の様な AI 搭載の対話型検索エンジンをローカルのみで動かせる Farfalle を試してみました。本家の様にフォーカスを選ぶ事はできませんが、十分に便利だと思います。
Woocommerceの商品登録でブロックエディタを有効にする

# 概要
最近のWordpressではブロックエディタを使って
サイトを作ることが多くなってきました。
そこでWoocommerceの商品登録でも
ブロックエディタを使えるようにしました。

# 実際のコード
```functions.php
function activate_gutenberg_product( $can_edit, $post_type ) {
  if ( $post_type == 'product' ) {
    $can_edit = true;
  }
  return $can_edit;
}
add_filter( 'use_block_editor_for_post_type', 'activate_gutenberg_product', 10, 2 );
```
上記をfunctions.phpに記載することで
有効にできます。
Listアプリ


```tsx:App.tsx 
import React, { useState } from 'react';
import { Form } from './Form';
import { List } from './List';
import { Container, Typography } from '@mui/material';

export type ListItem = {
  id: number;
  title: string;
  details: string;
};

const App: React.FC = () => {
  const [listItems, setListItems] = useState<ListItem[]>([]);

  const addItem = (title: string, details: string) => {
    const newItem: ListItem = {
      id: listItems.length ? listItems[listItems.length - 1].id + 1 : 1,
      title,
      details,
    };
    setListItems([...listItems, newItem]);
  };

  const removeItem = (id: number) => {
    setListItems(listItems.filter(item => item.id !== id));
  };

  return (
    <Container>
      <Typography variant="h4" gutterBottom>My List App</Typography>
      <Form addItem={addItem} />
      <List items={listItems} removeItem={removeItem} />
    </Container>
  );
};

export default App;
```

```tsx:Form.tsx
import React, { useState } from 'react';
import { TextField, Button, Box, Alert } from '@mui/material';

type FormProps = {
  addItem: (title: string, details: string) => void;
};

export const Form: React.FC<FormProps> = ({ addItem }) => {
  const [title, setTitle] = useState('');
  const [details, setDetails] = useState('');
  const [showAlert, setShowAlert] = useState(false);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (title) {
      addItem(title, details);
      setTitle('');
      setDetails('');
      setShowAlert(false);
    } else {
      setShowAlert(true);
    }
  };

  return (
    <Box component="form" onSubmit={handleSubmit} sx={{ mb: 2 }}>
      {showAlert && (
        <Alert severity="warning" onClose={() => setShowAlert(false)}>
          Title is required!
        </Alert>
      )}
      <TextField
        label="Title"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        fullWidth
        margin="normal"
      />
      <TextField
        label="Details"
        value={details}
        onChange={(e) => setDetails(e.target.value)}
        fullWidth
        margin="normal"
      />
      <Button type="submit" variant="contained" color="primary" sx={{ mt: 2 }}>
        Add Item
      </Button>
    </Box>
  );
};
```

```tsx:List.tsx
import React from 'react';
import { ListItem as ListItemType } from './App';
import { List as MUIList, ListItem, ListItemText, IconButton, Divider } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';

type ListProps = {
  items: ListItemType[];
  removeItem: (id: number) => void;
};

export const List: React.FC<ListProps> = ({ items, removeItem }) => {
  return (
    <MUIList>
      {items.map((item) => (
        <React.Fragment key={item.id}>
          <ListItem
            secondaryAction={
              <IconButton edge="end" aria-label="delete" onClick={() => removeItem(item.id)}>
                <DeleteIcon />
              </IconButton>
            }
          >
            <ListItemText primary={item.title} secondary={item.details} />
          </ListItem>
          <Divider />
        </React.Fragment>
      ))}
    </MUIList>
  );
};
```
mecab-python3 インストールからユーザー辞書の登録まで（Windows11）

# 前置き
- MeCabにユーザー辞書を登録し、形態素解析を行おうと思いましたがなかなか動かず。
ネットで検索してもWindows関連の情報は古いものしか見つからずでしたので備忘録としてなるべく簡潔に投稿します。 
- 参考サイトの内容を実行するだけの部分は割愛させていただきます。  
- ライブラリのインストールも割愛しているため、使用するライブラリをインストールしていない場合はインストールをしておいてください。  

# 参考サイト
1. [金子邦彦研究室Webサイト（MeCabのインストール）](https://www.kkaneko.jp/ai/win/mecabinst.html)
2. [MeCab 単語の追加方法](https://taku910.github.io/mecab/dic.html)

# MeCab本体のインストール
こちらは「参考サイト1」を全て（手順1～15まで）行ってください。
コマンドプロントで実行できる状態まで持っていければ大丈夫です。

# 単語帳となるCSVを作成
単語帳としてpythonでcsvファイルを作成します。
今回は「あもいはすはす」という単語を作成してみます（めちゃめちゃ適当です。）。
保存先は`C:/MeCab_dicts/csv/`を指定しています。
```python
import pandas as pd

user_dict = pd.DataFrame({
    '項目名': ['あもいはすはす'],
    '左文脈ID': [1285],
    '右文脈ID': [1285],
    'コスト': [1000],
    '品詞': ['カスタム'], 
    '品詞細分類1': ['カスタム'], 
    '品詞細分類2': ['*'],
    '品詞細分類3': ['*'],
    '活用形': ['*'],
    '活用型': ['*'],
    '原形': ['あもいはすはす'],
    '読み': ['アモイハスハス'],
    '発音': ['amoihasuhasu']
})

user_dict.to_csv("C:/MeCab_dicts/csv/user_dict.csv", index=False, header=False)
```

# CSVの内容をコンパイル（foo.dicの作成）
`foo.dic`ファイルの保存先として`C:/MeCab_dicts/dic/`を作成します。
その後、コマンドプロントで次のコマンドを実行します。
```
"C:\Program Files (x86)\MeCab\bin\mecab-dict-index.exe" -d "C:\Program Files (x86)\MeCab\dic\ipadic" -u "C:\MeCab_dicts\dic\foo.dic" -f utf-8 -t utf-8 "C:\MeCab_dicts\csv\user_dict.csv"
```

説明を加えると次のようになります。お使いの環境に合わせて変更をしてください。
```
"{mecab-dict-index.exeのパス}" -d "{MeCab\dic\ipadicのパス}" -u "{foo.dicのパス}" -f utf-8 -t utf-8 "{user_dict.csvのパス}"
```

# dicrcへの追加
`MeCab\dic\ipadic`の配下にある`dicrc`にfoo.dicのエントリ情報を追加します。
```
userdic = C:\MeCab_dicts\dic\foo.dic
```
私の環境だと下の画像のようになります。
![スクリーンショット 2024-06-11 203510.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491855/72d359f1-c6c3-4039-250d-d183ed57a28d.png)


# pythonで動作確認
pythonで次のコードを実行します。パスに注意してください。
```python
import MeCab

mecab = MeCab.Tagger(r"-u C:/MeCab_dicts/dic/foo.dic -d 'C:/Program Files (x86)/MeCab/dic/ipadic'")

print(mecab.parse("あもいはすはすが食べたい"))
```

実行結果です。
![スクリーンショット 2024-06-11 203746.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491855/07d162e6-07c3-3adb-9bf1-ad9c06fac29d.png)

「あもいはすはす」なんて言葉は現実に存在しないはずなのでユーザー辞書をしっかり認識できていることが分かります。

# Note
やり始めの時にパスの書き方、特に`Program Files`の様に空白があるパスなどの書き方のところで躓いてしまいエラーを沢山出してしまったので皆さんはお気を付けください。
matplotlibからSVG出力したときに、inkscape等で触ってもストローク色が変わらない問題への対処


matplotlibの散布図をSVGで出力した場合、系列がPathCollection中で定義されていることがある。このとき、系列中のポイントをまとめたグループで&lt;[defs](https://developer.mozilla.org/ja/docs/Web/SVG/Element/defs)&gt;と&lt;use&gt;が使われていることがある。defs要素で共通したポイントの形を（定数のように）定義し、use要素でそれをコピーしつつ表示座標だけ変えるという仕組みである。

問題は
- 系列のストローク色はdefs要素中で定義されていてる
- defs要素をinkscapeから操作することができない

この2つが重なることで、ストローク色が変更不能になる。

手っ取り早い解決策としては、テキストエディタでSVGファイルを開き、defs要素を直接編集してストローク色の指定を取り除くとよい。
DynamoDBにてネストしている属性を検索、値を取得したい【PartiQL】

# はじめに
とある案件対応中、DynamoDB上でネストしている属性 ~~1属性にJSON押し込んでるやつ~~に対して検索、特定階層の値の一覧取得をしたいという場面に遭遇しました。

RDBでのイメージからこのような状況下ではLIKE検索(contains句)でひっかけた後頑張って整形する...といったアプローチしか取れないイメージが強かったのですが、PartiQLというものがあると知り、少し利用してみた際のメモとなります。

今回はマネジメントコンソール上から以下のPartiQLエディタを利用してみました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617151/f4ac48f5-0b7c-86f4-27b8-9e5813c49e7c.png)

# テスト用データ作成
お試しでシンプルな「test」テーブルを作成した後、以下のSQL文をPartiQLエディタから実行することでデータ投入を実施してみました。この時点でSQLのように操作できるという点がまずオドロキでした😲
```sql
INSERT INTO test VALUE {
    'ID': 1,
    'created_at': 12345,
    'name': 'Taro Test',
    'contact': {'email': 'test@example.com', 'phone': '090-1234-5678'},
    'projects': [
        {'project_id': 'P100', 'title': 'Data Migration', 'technologies': ['SQL', 'AWS', 'Lambda'], 'status': 'active'},
        {'project_id': 'P101', 'title': 'Web Application Development', 'technologies': ['Ruby', 'Rails', 'PostgreSQL'], 'status': 'completed'}
    ],
    'skills': ['SQL', 'Ruby', 'JavaScript', 'AWS']
}
```

# 検索を少し試してみた
簡単な例でネストしている属性に対していくつか検索を試してみました
```sql
# 属性名.キー名 の形でマップをハッシュのように掘れる！
select * from test where contact.email = 'test@example.com'
```

```sql
# 属性名[インデックス] の形でリストを配列のように掘れる！
select * from test where skills[0] = 'SQL'
```

```sql
# 組み合わせも行ける！
select * from test where projects[0].technologies[1] = 'AWS'
```

```sql
# 選択項目リストにも書ける！
select ID, contact.email from test
```
個人的に最後の性質が特に便利かつ今回欲しかったモノであり、
PartiQLエディタに備わっているSQLの実行結果をCSVとして保存する機能と組み合わせて、たどり着くまでに何階層も掘る必要がある深い階層の値をお手軽にCSV化出来たりします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617151/bd298a2d-89d4-97fd-49d0-3c3301799955.png)

# おわりに
今回PartiQLというものにふとしたキッカケから触れてみましたが、個人的にとても魅力的な存在だと感じましたので今後仲良くなっていきたいです🙏

また、アプリケーション側でパースをしてからデータ利用等をしている状況で、DynamoDB上にはネスト構造を持っておらず**全体が1つの長い文字列として保存されているパターン**では今回のようにサクサク掘っていくことは出来ず、基本的にcontains句等を中心にしたアプローチで取り組むしかないようです...😢

# 参考にさせていただいた記事
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/ql-reference.html
https://qiita.com/danishi/items/a8f2da32232fd0abd922
RFxについてまとめてみた

## はじめに
システム発注のフローについて調べていたら、RFP、RFI、RFx などなど似たような言葉で、何が何を指すのか、わからなくなってきたので一括でまとめてみました。

違いや内容、どのように使用されるのか、備忘録としてまとめています。

## RFx
RFxは、調達プロセスにおいて使用される一連の文書の総称でRFI、RFP、RFQの３つからなる。それぞれ目的は違うが、ベンダーやサプライヤーなどから必要な情報を提供してもらうための要請書のこと。
xという変数にPかIかQが入るって意味らしい。


## RFI、RFP、RFQについて
急に出てきたけど、どれも意味わからん！ってなるので、それぞれ解説していきます。

### RFI
RFIとは、「Request For Information」の略称で、「情報提供依頼書」と呼ばれる。
ベンダーの情報やサービスの一般的な情報の提供を依頼する文書のこと。
内容: 企業情報、導入実績、技術、経験についての情報など。
目的：特定の製品やサービスについての情報を幅広く収集するため。

### RFP
RFPとは、「Request For Proposal」の略称で、「提案依頼書」と呼ばれる。
ベンダーに対して必要な各種要件をまとめ、具体的な提案を依頼する文書のこと。
内容: プロジェクトの詳細、完成・運用までのスケジュール、作業範囲、契約条件など。
目的：具体的な提案をベンダーから受け取り、最適なベンダーを選定するため。

### RFQ
RFQとは「Request for Quotation」の略称で、「見積依頼書」や「見積要求書」と呼ばれる。
ベンダーに対してシステム開発の価格や内訳の開示を依頼するための文書のこと。
内容: 製品やサービスの詳細仕様、数量、想定費用、問題発生時の補償条件など。
目的：特定の製品やサービスについての詳細な価格見積もりを受け取るため。


## RFxの一般的な流れ
1.　情報収集フェーズ (RFI)
* ベンダーの情報を収集し、市場の状況を把握する
* ニーズに適したソリューションがあるかを確認する

2.　提案依頼フェーズ (RFP)
* ベンダーから具体的な提案を受け取り、適切なベンダーを選定する
* 技術的なソリューション、価格、スケジュール、サポート体制などを比較する

3.　見積依頼フェーズ (RFQ)
* 選定したベンダーに対して詳細な見積もりを依頼する
* コストを比較し、予算内での実施可能性を検討する

## まとめ
RFx、RFP、RFI、RFx、それぞれ似た言葉ですがそれぞれ目的や項目が違うことがわかりました。
それぞれの目的を適切に把握したうえで、適切に使い分けることができるようになりたいですね。
JQLでエピック内のチケットをフィルターしたい

# はじめに
社内のプロジェクトでJiraを使っているがなかなか思い通りに課題をフィルターできなかったのでメモ

# JQLとは
「Jira Query Language」の略で、Jira上で特定の課題を検索するため使われる。

# エピック内のチケットをフィルターする方法
`parent = エピックのチケット番号`

最初はチケット番号ではなくエピック名を入れていたがフィルターできず、チケット番号に書き換えたら無事できた。
JQLは便利ですがなかなか使いこなすのが難しいと思ってます。
また何か気づきがあればメモとして残していきたいです。

# 参考
https://www.atlassian.com/ja/blog/jql-for-beginners-1
プロジェクト進行のスタート地点について考えてみた


閲覧いただきありがとうございます。今回は、私の前職での経験をもとに、プロジェクト進行について考察した内容を共有します。

## 前提
以前、勤めていた会社で社内ドキュメントの管理を刷新するプロジェクトにリードとして参画した際、他プロジェクトメンバーは全員、他部署から担当者がアサインされました。

キックオフミーティングは他の会議の影響で直前にキャンセルが相次ぎ、参加率は80％でスタートしました。この時点で既に不穏な雰囲気が漂っていました。キャンセルの理由を聞くと、プロジェクト自体の優先度がメンバーごとに異なっていることが明らかでした。中には「今のドキュメント管理で問題ない」という意見もありました。しかし、私は上司から強くプロジェクトの遂行を指示されており、今更プロジェクトを取りやめることはできませんでした。

結果として、プロジェクトは各部署の管理方法を再認識するだけで終わり、理想的な形にはなりませんでした。本来なら、全ての部署が一貫性のあるやり方に統合し、UX向上やマンパワーの削減時間などをターゲットにして進めるべきだったと思います。

~~社内プロジェクトが煮え切らない形で自然消滅や意味のない成果をだして終わってしまうのってあるあるなんですかね？~~

## 教訓
この経験から得た教訓として、プロジェクト進行において最も重要なのは以下の点だと考えます。

### 1. プロジェクトの目的とゴールの明確化
プロジェクトの目的とゴールを**具体的**に設定し、メンバー全員の認識を一致させることが重要です。これがプロジェクトのスタートラインとなると考えます。

### 2. コミュニケーション方法の設定
目的とゴールが明確になった後に適切なコミュニケーション方法や定期ミーティングの設定を行います。ゴールが明確になっていることでマイルストーンの認知もしやすくなっているはずです。これによりプロジェクトの問題も発見・解決されやすくなります。

プロジェクト進行において、これらの点を意識することで、成功率を高めることができると考えます。

以上、私の経験と考えを共有しました。ご覧いただきありがとうございました。
チームに迅速に合流して成果を出すためのチェックリスト

## はじめに

◆この記事は何？
チームに加入するときに役立つチェックリストを紹介します。
実際に私が活用しているチェックリストです。

◆対象は？
- チームに新しく加わったエンジニア
- 新しいプロジェクトに加入予定のエンジニア
- 新入社員

◆この記事のねらい
素早くチームに合流し、成果を出せるようになること

## まず確認したい10個
- 関わっているメンバーは誰か？体制図は？
- 質問の方法は？誰に？
- チャットのコミュニケーション方法は？全てのチャンネルに参加できているか？
- 必要なアカウントは？抜け漏れないか？
- ドキュメントの格納場所は？
- 朝会などのデイリーミーティングはあるか？いつ？どこで？
- オンボーディング資料はあるか？（ないなら作るべきか？他にもメンバーは増えるのか？）
- 自分の役割は？どんな責任がある？
- 自分への期待は？
- 最初のタスクは？締め切りは？


## プロジェクトをキャッチアップするための10個

- プロジェクトの目的は？目標は？
- 背景は？
- 今のフェーズは？
- ステークホルダは？
- 規模は？予算は？
- 顧客は？特徴は？
- 組織から見たときのこのプロジェクトの位置付けは？
- プロジェクトの難しいところは？
- リスクは？
- 使用できるリソース（人的リソース、マシンリソースなど）は？


## 技術をキャッチアップするための10個

- 開発言語は？
- 開発ポリシー（開発アーキテクチャドキュメント）はあるか？
- 要件定義書はあるか？
- 非機能要件定義書はあるか？
- システム構成図はあるか？
- データベース設計書はあるか？ER図はあるか？
- 外部設計書（画面設計書）はあるか？
- 詳細設計書はあるか？
- レビューのやり方は決まっているか？レビュー観点の優先順位は？
- テストアクティビティについてのドキュメントはあるか？単体テスト、結合テストの粒度は？


## チーム運営をキャッチアップするための5個

- 確認事項や質問はどうするのが良いか？確認事項一覧はあるか？
- 報告連絡相談はどのように？
- 資料作成にルールはあるか？
- デザインルールはあるか？
- タスク管理方法は？チケットはあるか？

## 大事な3つの思考法

**①クイックウィンでチームに貢献していく**
「クイックウィン」とは、「素早く勝つ」という意味です。
これを意識するのが重要です。

まずは、チームに貢献していくことを意識します。
素早く貢献できれば、信頼を得るだけでなく、チーム全体のモチベーションが向上します。

**②ハイスピードで終わらせる**

チームへの合流には、時間をいくらでも費やせてしまうことがあります。
完了を意識しなければ、ダラダラと時間が過ぎていくだけです。

そのためハイスピードで完了させることを意識します。

ハイスピードで完了させるために、上記のチェックリストを活用してキャッチアップします。
質問する前に、自分なりの答えを持つ（仮説を立てる）ことも有効です。

**③自分とチームに足りないものを見つける**

チームに入ったとき、チームに求められるスキルと自分のスキルにギャップがあることがあります。
そのギャップを早く埋めるためには、その存在に早く気づくことが重要です。

また、自分のこれまでの経験とチームの運営にギャップがある場合もあります。
チームに足りない部分を自分が補うことで、クイックウィンに繋がります。

例えば、次に参画するメンバーのためのドキュメント作成はクイックウィンになりやすいです。

自分とチームに足りないものは何か？という視点を持ちながらキャッチアップを進めることが重要です。

## おわりに

この記事では、新しいチームに素早く合流して成果を出すための考え方とチェックリストを紹介しました。

みなさんが確認していることがあれば、コメントで教えてください。

それでは。

## 参考

https://customercore.jp/glossary/%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%A6%E3%82%A3%E3%83%B3
Macを一瞬でスクリーンセーバに切り替える

# はじめに
オフィスでの作業時、離席のたびに画面ロックしていると思います。
今回は手軽にスクリーンセーバに切り替える方法を残しておきます。

# 手順

システムの環境設定を開き、「デスクトップとスクリーンセーバ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523103/0b16b278-04e0-937c-616a-7a343df992ad.png)

右下のホットコーナーをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523103/07bce52a-dd52-c7e2-d9b1-9ed7d69c8b16.png)

好きな角に「スクリーンセーバを開始する」をセットしてOKをクリック
私は左下に設定してます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523103/ddf951e6-279b-e159-c35a-88b3779b6413.png)

カーソルを設定した角に持っていくとスクリーンセーバが開始されます。
【Mac】ホームポジションから無駄な移動をしない方法

## はじめに
Macの便利だと思った操作を紹介します。
プログラミング学習を始めて、Macを使い始めた方に読んで頂きたい記事です。

## 結論
「A」の左にある「control」のショートカットキーが便利です。
ホームポジションから指を離す機会が減ります。

### 使用頻度の高いショートカットキー

| キー | 内容 | 備考 |
| ---- | ---- | ---- |
| control + P | 1 行上に移動 | ↑キー |
| control + F | 1 文字分進む | →キー |
| control + N | 1 行下に移動 | ↓キー |
| control + B | 1 文字分戻る | ←キー |
| control + H | 左側にある文字を削除 | windowsのDeleteキー |
| control + D | 右側にある文字を削除 | windowsのBackspaceキー |
| control + A | 行または段落の先頭に移動 |  |
| control + E | 行または段落の末尾に移動 |  |
| control + ; | （入力中の文字を）半角にする |  |
| control + L | （入力中の文字を）全角にする |  |
| control + K | （入力中の文字を）カタカナにする |  |
| control + J | （入力中の文字を）ひらがなにする |  |

## まとめ
最初は全く上手くいかないのですが、慣れるとwindowsのパソコンでも使いたくなるほど必須です。特に上から6つは1日に何十回も押すと思います。

#### こんなショートカットキーもあります

| キー | 内容 | 備考 |
| ---- | ---- | ---- |
| Z + K| 「↑」 | 「やじるし」や「うえ」と打って変換するやつ |
| Z + L| 「→」 | 「やじるし」や「みぎ」と打って変換するやつ |
| Z + J| 「↓」 | 「やじるし」や「した」と打って変換するやつ |
| Z + H| 「←」 | 「やじるし」や「ひだり」と打って変換するやつ |
Qiita初投稿

はじめまして＊
都内でフロントエンドのエンジニアをしています。

普段はCMSを使ってサイトの新規構築や保守業務をしています。
主に使用している言語は HTML, CSS, Ruby, JavaScript です。

エンジニアになって4年？5年？
まだまだひよっこです🐥⸒⸒
恐れ多くも職場では何名か後輩がいて面倒をみさせてもらったりしているので私も自分の技術を見直したり更新する日々です。
また、自分の市場価値を上げるためにも業務以外の言語も勉強したいと思っています。
そのためのアウトプットにQiitaを使えたらな、と思っています。

どうぞお手柔らかにお願いいたします◎
エミュレータの画面いっぱいにボタンが広がっていた原因

### きっかけ

Androidアプリを作っていて、ふと見ると配置したボタンがエミュレーターの画面いっぱいに広がっていてびっくりしたので原因を調べた。

### 原因

res/layout/activity_main.xmlのButtonタグに、android:layout_weight="1"が実装されていたため

### android:layout_weightとは

UIの構造を定義するレイアウトの1つであるLinearLayoutで使える。
Viewを配置した際残っているスペースを埋めることができる
layout_weightを指定していない場合は0として扱われる。

### ボタンが広がらないように修正した方法

android:layout_weight="1"を削除しエミュレータで確認するとイメージしたボタンの大きさになったため削除しておく方法をとった
dyld[35134]: Library not loaded: @rpath/libopencv_aruco.410.dylib の対処方法

## 概要

タイトルのままですが、ハマったので書いておきます。

まず、ライブラリのパスとして /usr/local/lib
を渡していたのですが、

```bash
find /usr/local -name "libopencv_aruco.410.dylib"
```

とすると、

```bash
/usr/local/lib/libopencv_aruco.410.dylib
```

出てきますし、実際にls して確かめてもいいのですが、dylib　自体はopencvをビルドし、

```bash
make install
```

した時点できちんとインストールされていました。


## 解決策

```bash
export DYLD_LIBRARY_PATH=/usr/local/lib:$DYLD_LIBRARY_PATH
```

とするだけでした。ランタイムでDYLDを参照するパスが通っていなかったようです。


以上、どなたか同じ現象に行き当たった方の助けになれば幸いです。
自社サービスサイトをNuxtからAstroに置き換えた話

# はじめに
Nuxtで作られていた弊社サービスサイトを一部Astroに置き換えたので、よかったことや困ったことを書きたいと思います。

# Astroとは
[公式サイト](https://docs.astro.build/ja/concepts/why-astro/)には以下の様に記されています。
>Astroは、ブログやマーケティング、eコマースなど、コンテンツ駆動のウェブサイトを作成するためのウェブフレームワークです。Astroは、新しいフロントエンドアーキテクチャを開拓し、他のフレームワークと比較してJavaScriptのオーバーヘッドと複雑さを低減することで知られています。高速でSEOに優れたウェブサイトが必要なら、Astroが最適です。

サービスサイトの様な静的サイトを作成するにあたって、とてもマッチしているフレームワークといえます。
さらに、AstroはReactやVueなどのUIライブラリで作られたコンポーネントを呼び出すことができるため、Nuxtで作られていた既存資産を流用しながら置き換えるにはとても良いフレームワークだと考えました。

https://docs.astro.build/ja/guides/framework-components/

# Astroへの漸進的な移行
いきなり全てAstroへの移行を行うと、とてつもない工数がかかるため、部分的にAstroへの移行を開始しました。

弊社サービスサイトは以下の様な構成になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285733/3283ac7a-064e-a79d-78e5-c125748e7bb3.png)

表示速度の改善はCVRの向上に繋がるというデータの元、ユーザーの表示回数の多い各種プロダクトページからAstro化していくことにしました。

https://repro.io/contents/site-page-speed/

## Astro化する際に困ったこと

### client:loadを使用すること
Nuxtでは意識していなかった、クライアント側で何を処理させるかという考え方の変化に躓きました。
弊社サービスサイトはレスポンシブデザインとなっていて、スマーフォン、タブレット、PCでの画面切り替えが必要です。
しかし、Astroはデフォルトではjsを排除してビルドされているため、画面幅を検知してDOMを切り替え等のことは初期状態ではできません。
そのため、JavaScriptでの処理が必要な場合は明示的に `client:load`を付ける必要がありました。

https://docs.astro.build/ja/reference/directives-reference/#clientload

```ts:index.astro
--- 
import HogeComponent from '../components/HogeComponent.vue'
---

<HogeComponent
  client:load
/>
```
```vue:HogeComponent.vue
<template>
  <div>
    <p v-if="isPc">PC表示</p>
    <p v-else-if="isSp">SP表示</p>
  </div>
</template>
<script>
export default {
// リサイズ等のイベント登録等は省略してます
computed: {
    isPc() {
      return 1024 <= window.innerWidth
    },
    isSp() {
      return window.innerWidth < 768
    },
  },
}
</script>
```

### パフォーマンス改善
jsが排除されることでページスピードは飛躍的に向上しましたが、やはり`cleint:load`をつけているとその分だけTotal Blocking Timeがあがってしまいました。
Astroの良さをさらに引き出すため、jsは極力使わずCSSのメディアクエリーで再現できるものはそちらで対応するようにしました。

### まだ情報が少ない
Astroはモダンな技術ということもあり、使用事例等がまだまだ少なかったので、試行錯誤でかなり工数をつかってしまいました。
公式ドキュメントはかなり充実しているので、困ったら眺めるようにしています。

## Astro化してよかったこと

### 高速化
Astroではクライアント側でのjs実行を明示的に指定しない限りは、js等を取り除いて生成されます。
そのため、ページのロード速度等が飛躍的に向上しました。

### 既存資材の流用が可能
元々弊社サービスサイトはNuxt2で作られていました。
各コンポーネントはVue.jsで作成されていましたが、Astroでは各種フレームワークのコンポーネントを使用することができるため、移行のコストは最小限に抑えることができました。
また、移行前はNuxt2で作られており、Vueのバージョンも古かったためこのタイミングでVue3にあげることにより、マイグレーションも同時に行うことができました。

### CLS改善
Astroではローカル内の画像をimgタグ等に使用する際はimportして読み込みます。

https://docs.astro.build/ja/guides/images/

```vue
<template>
  <img
    :src="hoge.src"
    :width="hoge.width"
    :height="hoge.height"
  />
</template>

<script>
import hoge from '../assets/images/hoge.png'

export default {
  data() {
    return {
      hoge
    }
  }
}
</script>
```
上記のように読み込むことができ、画像の横幅や縦幅が画像から読み込むことができます。
そのため、画像ごとにwidth,heightをマジックナンバーで指定する必要がなくなりました。

# おわりに
現在ではトップページと各種プロダクトページのAstro化が終わっていて、体感でもわかるレベルで高速化されています。
ぜひ弊社サービスサイトを一度訪れて、体験していただければと思います。

https://www.hrbrain.jp/
Vue.js テンプレート構文: Composition API を使ったデータ表示と操作

今回はVue.jsの基礎、テンプレート構文について触れていきたいと思います。
最近vueを教える機会が増えてきた際にテンプレート構文ってなんですか？と聞かれ咄嗟に説明できなかったので改めて復習として記事を書いてまとめてみました。

### テンプレート構文とは
Vue.js のテンプレート構文は、HTML に JavaScript のデータやロジックを埋め込むための仕組みです。これにより、静的な HTML を動的に変化させることができ、ユーザーインタラクションやデータの可視化を容易にします。
これだけ言われてもいまいちピンとこないと思います。

その中でも特に重要な3つの構文、`mustache記法 {{ }}`、`v-bind`、`v-model` について見ていきたいと思います。
Composition API の `setup` 構文を用いた具体的な例を通じて理解を深めていきたいと思います。

### 1. データを表示する: `mustache記法 {{ }}`

mustache記法は、最も基本的なテンプレート構文で、Vue.js のデータプロパティを HTMLテンプレートに表示する役割を持っています。

**例:**

```vue
<script sutup>
    const name = ref('太郎');
</script>

<template>
  <div>
    <h1>こんにちは、{{ name }}!</h1>
  </div>
</template>
```

この例では、`name` という変数に `ref` を使ってリアクティブなデータとして `太郎` を格納しています。`{{ name }}` を使うことで、テンプレートに `太郎` が表示されます。

### 2. 属性を動的に操作する: `v-bind`

`v-bind` は、HTML 要素の属性にデータプロパティをバインドします。属性値を動的に変更したい場合に便利です。

**例:**

```vue
<script sutup>
    const imageUrl = ref('https://example.com/sample.jpg');
</script>

<template>
  <img :src="imageUrl" alt="風景写真">
</template>
```

この例では、`imageUrl` という変数に `ref` を使って画像のURLをリアクティブなデータとして格納しています。`v-bind:src="imageUrl"` を使うことで、画像の`src`属性に `imageUrl` の値がバインドされます。

`v-bind` は `:` を省略して `:src` の代わりに `src` と書くこともできます。

### 3. フォーム入力とデータを同期する: `v-model`

`v-model` は、フォーム要素の値をデータプロパティと双方向にバインドします。ユーザーの入力とデータの同期を簡単に行うことができます。

**例:**

```vue
<script sutup>
    const message = ref('');
</script>

<template>
  <input type="text" v-model="message">
  <p>入力されたメッセージ: {{ message }}</p>
</template>
```

この例では、`message` という変数に `ref` を使ってテキスト入力の内容をリアクティブなデータとして格納しています。ユーザーがテキスト入力に何かを入力すると、`message` の値が更新されます。同時に、`message` の値が `{{ message }}` によって表示されるため、リアルタイムで入力内容が反映されます。

### まとめ

このようにテンプレート構文を扱えるようになれば動的なウェブサイトを構築することができるようになります。また、Composition API の `setup` 構文を使えば、より整理されたコードで、テンプレート構文を活用することができるためこちらも同時に復習していきたいと思います。
Gitでコードの変更を記録する方法（add, commit）

# 記事を書いた目的　
DjangoでWebアプリを作成し、デプロイしてからというもの、何度もコードを修正してきました。その度に、SourceTreeやVSCodeのソース管理などのGUIな方法でコミットしてきました。ただ、書籍に書いてあったコミットの手順をそのまま利用するのみで、Gitやバージョン管理そのものについてはほとんど理解していませんでした。

なんか修正がうまくいっているみたいだけど、なんでうまくいっているのか説明できなくて気持ち悪いな〜。GitとかGitHubとか、わかったんだかわかっていないんだか、よくわからないな〜。こんな状態が長くてずっとモヤモヤしていました。今後、ずっと一人でWebアプリを開発するなら問題ありませんが、将来複数人で開発をするときには、Gitについてわかっていないとお仕事にならないみたいですね。そういうわけで、今更ですが、Gitについて勉強しています。


今回は、Gitでコードの変更を記録する方法（add, commit）を勉強します。
Gitに登場する専門用語は簡単に記事にしましたので、ぜひ参考にしてみてください。


記事: [Gitとは](https://qiita.com/eric50905/items/94ea4503d42ea5ca019a)
# 最初にやっておくこと

### 基本コマンド
| 目的 | コマンド |
|:-|:-|
| 簡易ヘルプを表示したい  |  git |
| バージョンを表示したい  |  git --version |

### 初期設定
Gitを使うには初期設定が必要です。作業履歴に名前とメールアドレスが使われるので、まず登録しておきます。
| 目的 | コマンド |
|:-|:-|
| リポジトリに名前を登録したい  |  git config --global user.name "eric" |
| リポジトリにメールアドレスを登録したい |  git config --global user.email "eric@example.com" |
|登録情報を確認したい|git config --list|

***

ディレクトリを作成し、そこにリポジトリを作ります。作成したディレクトリ(myapp)のファイルが記録対象となります。作業履歴はこのディレクトリの「.git」という隠しディレクトリに記録されています。lsコマンドで見てみると、「.git」という隠しディレクトリが作成されています。
```
mkdir myapp
cd myapp
git init　　  # Gitを使う作業ディレクトリを宣言する
```


# リポジトリにファイルを追加し、コミットする
### 用語の確認
- コミット：変更履歴を隠し領域に記録する操作のことです。変更履歴自体のこともコミットと呼びます。

- ワーキングディレクトリ：普段プログラミングなどの作業しているディレクトリのことです。ワーキングツリーとも呼ばれます。
- ステージングエリア：ファイルを仮登録する場所です。インデックスとも呼ばれます。
- リポジトリ：実際に変更履歴が記録される場所です。

**リポジトリにファイルを追加し、コミットするまでのステップ**
1. ワーキングディレクトリでファイルを作成
2. ステージングエリアにファイルを仮登録
3. メッセージを追加してファイルをローカルリポジトリにコミット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642333/a43816eb-9042-fad7-64bc-3176b34465a1.png)


| 目的 | コマンド |メモ|
|:-|:-|:-|
|リポジトリやステージングエリアの状態を確認する|git status||
|ステージングエリアに仮登録する|git add ファイル名||
|ステージングエリアに複数のファイルをまとめて仮登録する|git add .||
|ステージングエリアの内容をコミットする|git commit|コミットしたらvimが起動するので、コミットメッセージを入力する|
|仮登録とコミットを同時に実行する|git commit -a|新規で作成したファイルは対象外なので、git add コマンドを使う|
|コミットメッセージを同時に指定する|git commit -m "メッセージ"||
|仮登録とコミットを同時に実行し、メッセージを指定する|git commit -a -m "メッセージ"||
|コミット履歴を確認する|git log||



**vimの使い方**
vimとは、シェルで利用できるテキストエディタです。Gitでコミットしようとすると、コミットメッセージの入力のために、自動的に起動します。

編集モードに切り替える
- a 現在のカーソル位置の右から入力する
- A 現在の行の末尾に入力する

コマンドモード
- 編集モードからコマンドモードに切り替える
- u 元に戻す
- :wq 保存して終了
- :q! 保存しないで終了


# まとめ
今回は、リポジトリにファイルをコミットする方法を勉強しました。
作成、修正されたファイルはステージングエリアに仮登録され、（メッセージを追加して）ローカルリポジトリにコミットされます。コミットには、この２段階の作業が必要なのですね。次回は、現在の状態や変更箇所を確認する方法 （log, diff）を勉強します。
ETEC(組込み技術者試験制度)は受けるべきか

## はじめに……
こんにちは。
この記事はETEC(組込み技術者試験制度)を受験してきた組込みソフトエンジニア2年目の記事です。
ETECについて興味を持っている方向けの情報記事になります。
※ここで言うエンジニアは組込みソフトウェア開発エンジニアを指します。

## そもそもETEC(組込み技術者試験制度)とは
一般社団法人組込みシステム技術協会[JASA]が監督・運営する試験制度です。
ETEC自体は2006年末に運用され始めた試験制度であり、出来立てほやほやの資格とかではない。

## 結論:ETECは初学者におすすめしない。
正確に書くと、自身の知恵試しとして受験する分にはいいだろう。
しかし
▶組込み業界に就職したい人
▶資格勉強を行うことで体系的に学ぼうとする人(組込み知識を習得したい人)
には向いていない資格といえる。
なぜその結論となったのか書いていこう。

## おすすめしない理由1: 認知度が無い
▶組込み業界に就職したい人
これは、就職活動のために資格を取得したい人からしたら致命的欠点であろう。
冒頭でも記載している様に2006年末から運用されている試験制度であるが、組込み業界にいるエンジニアにすら認知されていない。
車業界にいるエンジニア、医療・精密機器系のエンジニアに聞き取りを行ってみたところ一切知らないようだった。
IPAのエンベデッドではないんだよね？最近出来た資格？と確認されたくらいの認知度であった。

## おすすめしない理由2: 情報が出回ってない。
▶資格勉強を行うことで体系的に学ぼうとする人(組込み知識を習得したい人)
認知度が低いのか検索しても受験者の体験記や問題などの情報もほとんどない。
どう資格勉強を行うか計画する段階で頓挫しかねない。

## おすすめしない理由3: 参考書籍が参考にならない。
▶資格勉強を行うことで体系的に学ぼうとする人(組込み知識を習得したい人)
ETEC公式(https://www.jasa.or.jp/etec)
に参考書籍のタブがあるが、そのほとんどが2000年代発刊であり絶版となっている。
2010年代発刊の本もあるが絶版である。(一部本が、PDF版での購入はできるのみ)
今でも定額で購入できるのが2020年代発刊は1冊「組込みシステム開発入門」がある。

絶版本であるが故に入手性が悪くメルカリなどのフリマサイトでは高値での取引がなされているくらいである。
そして調べて頂くとわかるが詐欺ECサイトにもちらほら転載されているため、本にたどり着くまでの労力が他資格と比べ高いのである。

最新の「組込みシステム開発入門」で勉強でもしてみようかと思っても、JASA公式が本当に書いたのかと思うほど抽象的すぎる解説(というか概要だけ)で、実際に受験してみると内容があまりにも乖離しすぎている。
公式からは「組込みシステム開発入門」がETECクラス2に対応する。と回答を頂いているが、これだけでは対策にすらならない。

例として挙げるなら
書籍にはETECクラス2の通信範囲である”Bluetooth”についての説明文があったが、その説明はクラスの出力と範囲について書いてあるだけで終了している。
しかし、試験に出てくる”Bluetoothについてはそれ以上に深いレベルでの知識を要求してくる。
これが他の範囲でも起こるので試験対策どころの話ではない。

NDAを受験時に結んでいる以上、内容について詳細に語ることは出来ないが、対応しているというからには単語の概要だけでなく、試験に出題される知識レベルでの解説が必要だろうと感じた。

## 結論
以上挙げた理由で(主に資格対策に対するものになるが)
初学者のETEC(組込み技術者試験制度)の受験はおすすめしない。
筆者自身、資格勉強を通して対象分野の知識を付けてきた経緯があるので、そのつもりでETEC受験を決意したが、参考になるような情報が殆ど出回っておらず結果としてグレード2Bとなった。

筆者は、これまでIPAの基本情報やCompTIAのSecurity+, Network+を受験した経験から管理技術全般、通信(有線)については
公式発表(https://www.jasa.or.jp/dl/etec/ETEC2_statistical_data.pdf)
の組込経験1-3年平均より正答率が高い。
しかし、組込みについての知識を問う技術・開発要素については平均に届かぬ結果となった。
公式推奨の本だけでは組込みの知識としては、単語レベルの理解しか得られないため、本を購入せず試験出題範囲の単語をWikiなどを参照して知識をノートにまとめ、自身で知識の体系化を図ったほうが有意義であろう。
今まで他のIT分野にも触れてこなかった初学者が、本だけの理解で挑んでしまうと恐らく2Cの判定となると推測する。
そのため初学者にはおすすめできない資格といえる。
![output_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396560/0d90252d-051f-fe50-b6a0-0af427b3d7df.png)




だが、筆者のようなパターンではなく純粋に組込みの知識レベルを測りたい人にとっては有用な資格であると考える。
3年以上経験あり自身の知識レベルがどのくらいだろうかと気になっている人には筆者もおすすめするだろう。

## 補足
ETECは合否がなく、どの知識レベルにいるのかというのを結果として出力してくれる。
公式から2024年度中にETECクラス1の参考書籍を発刊したいとの言及があった。
ETSS(組込みスキル標準)はIPAが2005～2009年度に実施した取り組みとなる。
(過去形であるのはIPA公式サイトで”実施しました。”との記載があるためである。)
64bitと32bitの違い

# Windowsの64bitと32bitの違いについて自分用にまとめました。よかったら参考にしてください :v:

# What is the difference between a 32-bit and a 64-bit architecture?
 A 64-bit architecture can handle data in chunks of 64 bits at a time, which allows it to address significantly more memory compared to a 32-bit system. A 64-bit system can theoretically address up to 18.4 million terabytes (TB) of memory. This increased memory capacity enables better performance for memory-intensive applications and larger datasets.
(https://www.lenovo.com/us/en/glossary/32-bit/?orgRef=https%253A%252F%252Fwww.google.com%252F より引用)

64bitのコンピュータは一度に64bitのデータの塊を処理できて、32bitに比べてかなり多くのメモリにアクセスすることができるようです。64bitシステムは理論的に最大1840万テラバイト（18.4 exabyte）のメモリにアクセスできるみたいです。すごい量ですね:point_left:

32bitシステムよりも64bitシステムの方が、より多くのメモリにアクセスできるため処理速度などの面で優れていることがわかりました。
anaconda で既存の環境を基に新しい環境を作る

# 背景
既存の環境を基に，新しいパッケージを追加した仮想環境だけをパッパと作りたかったので，備忘録も兼ねて残しておきます．
操作としては，「環境を複製する」だけなので，めちゃくちゃ簡単です．
（でも，毎回やり方を忘れる...どうして...）
# 内容
## 既存の環境を複製
```
conda create -name NewEnv --clone PresentEnv
```

```NewEnv``` には，**新しい環境の名前** を入れます．
```PresentEnv``` には，**既存の環境の名前** を入れます．
```--name``` は ```-n``` と省略することも可能です．

## 新しい環境の立ち上げ
新しい仮想環境を立ち上げるには ```conda activate``` コマンドを使ってください．
```
conda activate NewEnv
```
あとは，新しい環境に好きなパッケージをインストールすれば，新しい環境の出来上がりです．
ieee802.11acを無効にしたい

# AP機器(Linux）で無効

hostapd.confにて、ieee80211ac=0にする

# STA機器(Linux)で無効

11ac無効（ACの2.4GHzと5GHzをOFF)
```bash
$ mlanutl wlan0 bandcfg 0x1f
```

参考文献「README_MLAN」より、0x1fでAC 2.4GとAC5Gを無効にした。
```
bandcfg
	This command is used to set/get infra/ad-hoc band.
	Note: This command is only available in disconnected state.

	Usage:
		mlanutl mlanX bandcfg [l] [m] [n]

	where the parameters:
		[l]: Infrastructure band
		     bit 0: B
		     bit 1: G
		     bit 2: A
		     bit 3: GN
		     bit 4: AN

		     bit 5: AC 2.4G
		     bit 6: AC 5G
		[m]: Ad-hoc start band
		     bit 0: B
		     bit 1: G
		     bit 2: A
		[n]: Ad-hoc start channel
	Examples:
		mlanutl mlan0 bandcfg            : Get infra/ad-hoc band and ad-hoc
		                                  start channel configurations
		mlanutl mlan0 bandcfg 1          : Set infra band to B only
		mlanutl mlan0 bandcfg 3 2 6      : Set infra band to B/G, ad-hoc start band
		                                  to G and ad-hoc start channel to 6
```

## その他コマンド

bandcfg確認
```bash
$ mlanutl wlan0 bandcfg
Band Configuration:
  Infra Band: 0x7f ( B G A GN AN GAC AAC )
  Adhoc Start Band: 0x4 ( A )
  Adhoc Start Channel: 36
```
datarate確認
```bash
$ mlanutl wlan0 getdatarate
Data Rate:
  TX:
    Type: VHT
    BW:   20 MHz
    GI:   Long
    NSS:  1
    MCS:  MCS 8
    Rate: 78.000000 Mbps
  RX:
    Type: LG
    Rate: 6 Mbps
```

# 参考文献
* [README_MLAN](https://github.com/StreamUnlimited/marvell-sd-uapsta-8987/blob/master/README_MLAN#L1678)
batファイルで簡単に拡張子変換ツールを作ってみた

初投稿です。
なにかおかしいところ(情報やマナーなど)がございましたら教えてくれると嬉しいです。

※この記事ではWindows11を使いffmpegはバージョン7.0を使用しています。
※前提条件としてffmpegがインストール済みであるとします。


## なぜbatファイルやffmpegを使う必要があるのか
ffmpegとはオープンソースのマルチメディアフレームワークのことで、主に映像や音声ファイルをコマンドで弄くれるものです。 これを使って例えば拡張子を変更したり、そのファイルの細かい情報(再生時間や動画なら縦横の長さなど)を見たりすることができます。
これのすごいところは基本何でもできることなんですよね
コマンドで操作するので表現の幅が無限大過ぎてやってて楽しいので採用しました。
今回は拡張子を変更してみたいと思います。

batとは拡張子の一種でこのように表します。(例:hello.bat)この中にコードを書いて実行するとコマンドプロンプトがその通りに動いてくれるというやつでめっちゃ便利です。

そもそもなんでこれを作ったかというと、エクスプローラーから拡張子は変更できるっちゃできるんですが不便なとこがあったので、サイトを使ってたんですが拡張子をいちいちサイトで変換するのはめんどくさいしソフトをダウンロードするのも容量の無駄なので手持ちにあったffmpegで変換しよう！ってことで作った次第です。
batファイルは使うことで何も考えずとも使えるし手軽に作れるので採用しました。

## 実際に作ってみる
今回の完成品はこんな感じです。
```
@echo off
chcp 65001
cd \
set /p "input=ファイルをドラッグアンドドロップしてね:"
set /p "name=出力ファイルの名前と拡張子を書いてね:"
rem 保存先のパス
set save=C:\Users\UserName\Downloads\%name%

ffmpeg -i %input% %save%

pause
```
一行ずつ流れを見ていくと
`@echo off`でC:\Users\UserName>こういうのを消して

`chcp 65001`で文字コードをUTF-8にして

`cd \`でcドライブの直下に移動して

`set /p "input=ファイルをドラッグアンドドロップしてね:"`で`input`変数に`/p`で入力状態にして
（これが変換するファイルのパスを入力するコード）

`set /p "name=出力ファイルの名前と拡張子を書いてね:"`で`name`変数に`/p`で入力状態にして
（これが変換後のファイルの名前と拡張子を入力するコード）

`rem 保存先のパス`これはただのコメント

`set save=C:\Users\UserName\Downloads\%name%`で`save`変数に保存先のフォルダパスをいれて
（文末に変換後のファイルをそのフォルダにいれるため%name%を使う）

`ffmpeg -i %input% %save%`で`%input%`を使って変更したいファイルのパスをそこに代入して`%save%`で保存先のパスを代入して拡張子を変換します。

`pause`これはコマンドプロンプトが一瞬で閉じないようにするためのやつです。

これを拡張子が.txt（例:hello.txt）に入力して拡張子を.batに変更してから実行すると成功します。**必ず.txtに書いてから.batに変更してください。**
パス入力(input変数)は変更したいファイルをドラッグアンドドロップすれば勝手に入力されます。

## まとめ
このコードはまだまだ未完成で例えばsave変数をコマンドプロンプト側から変更したり複数のファイルを変更したりエラー処理をしたり細かい設定を、、とかいっぱいあるけど今回は見やすさ重視でシンプルに書きました。
みなさんもbatファイルで色々遊んでみると楽しいですよ！ではさようなら！
React hooks History使用方法まとめ


ページ遷移の際に使用するHistoryの使用方法についてまとめました。
# 基本的な使用方法
実行された際に、引数で指定したpathに遷移します。
```javascript
history.push('/new-path');
```
現在のpathからの相対pathで指定する場合は以下のように記述することで、現在のpathを参照できます。
```javascript
history.push(`${history.location.pathname}/hoge`);
```

## プロパティ
`history.push`には、以下のようなプロパティを指定できます。

1. **パス（path）**:
   - ページ遷移するURLを指定します。
   ```javascript
   history.push('/new-path');
   ```

2. **オプション（state, pathname, search, hash）**:
   - オブジェクト形式で複数のプロパティを指定することができます。
   ```javascript
   history.push({
       pathname: '/new-path',
       search: '?query=abc',
       hash: '#hash',
       state: { fromDashboard: true }
   });
   ```

### オプション詳細

- **pathname**:
  - 移動先のURLパスを指定します。
  ```javascript
  pathname: '/new-path'
  ```

- **search**:
  - クエリパラメータを指定します。`?`を含む文字列を指定します。
  ```javascript
  search: '?query=abc'
  ```

- **hash**:
  - URLのハッシュ部分を指定します。`#`を含む文字列を指定します。
  ```javascript
  hash: '#section2'
  ```

- **state**:
  - 移動先に渡す状態情報をオブジェクト形式で指定します。これにより、ページ間で追加の情報を渡すことができます。
  ```javascript
  state: { fromDashboard: true }
  `


### 使用例
```javascript
history.push({
    pathname: '/new-path',
    search: '?query=abc',
    hash: '#section2',
    state: { fromDashboard: true }
});
```
- **pathname**: `'/new-path'` への遷移を指定します。
- **search**: クエリパラメータとして`'?query=abc'`を指定します。
- **hash**: URLのハッシュ部分として`'#section2'`を指定します。
- **state**: `{ fromDashboard: true }` という状態情報を渡します。この情報は、遷移先のコンポーネントで`location.state`を通じてアクセスできます。

## 状態情報の取得
遷移先のコンポーネントで状態情報を取得するには、`useLocation`フックを使います。

```javascript
import React from 'react';
import { useLocation } from 'react-router-dom';

const NewPathComponent = () => {
    const location = useLocation();

    console.log(location.state); // { fromDashboard: true }

    return (
        <div>
            <h2>New Path</h2>
            <p>State: {JSON.stringify(location.state)}</p>
        </div>
    );
}

export default NewPathComponent;
```
Qiita記事に Shields.io バッジのアイコンを表示させる方法

### はじめに

この記事を書いた時に気づいたんですが、`Shields.io`のバッジを記事内に表示させる際、ちょっと工夫しないとアイコンが表示されませんでした。その時の覚書です。

https://qiita.com/fujithuro/items/a8561983028c731309cf

### pngにしよう

話は単純で、デフォルトの`svg`ではなく`png`を指定しようというだけの話です。

#### svg

下記の通り、拡張子を`svg`指定（ないし未指定）にすると

```
https://img.shields.io/badge/Github-grey.svg?logo=github
```

この通り、アイコンが表示されません。

![svg](https://img.shields.io/badge/Github-grey.svg?logo=github)

#### png

それに対し、下記のように拡張子を`png`にすると

```
https://img.shields.io/badge/Github-grey.png?logo=github
```

この通り、アイコンが表示されます。

![png](https://img.shields.io/badge/Github-grey.png?logo=github)


### 余談

この件、Qiita記事は`svg`に対応していないみたいなので、それが原因なのだと思います。

ただちょっと混乱したのは、記事作成時のプレビュー画面だと`svg`の方もちゃんとアイコンが出るんですよね。
なので、最初はちょっと原因がわかりませんでした。

なお、この情報は記事投稿時点（2024/06/11）のものですので、将来的なShields.ioやQiitaの仕様変更などによっては動作が変わることもあります。あしからず。
デスクトップマスコット［ポエム］

みなさんもデスクトップマスコットについて考えたことがあると思います
理想のデスクトップマスコットがあれば、QoLは爆上がりですしあん現運転家内安全病気も治ります（個人差があります）

### 歴史的背景
みなさんもよく知っている通り、古くはペルソナウェアやofficeのイルカなんかが思い出される方も少なくないでしょう
RO世代の方は立ちアコ経由で自動芋を使った方は懐かしいでしょう
※現在はチートツールに分類されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11300/d34f00f3-7e0c-d743-562c-cecb4a8bad2b.png)

また、現在もアクセスが可能な伺かというプロダクトは多くの古のインターネットオタクを魅了しました

http://usada.sakura.vg/

### 現代より少し前
アプローチは様々にあり、qiita上で独自に実装を試みている試みがたくさん見られます

#### ネイティブ

https://qiita.com/massoumen/items/2985a0fb30472b97a590

https://qiita.com/zooooi/items/8de33b0b7e1a647e92e4

#### javaとかpythonとか

https://qiita.com/urado/items/140293b94cac2424dc02

https://qiita.com/sugarflower/items/74281bed307a6e31ae3b

https://qiita.com/magiclib/items/89447ffbf42371cd6538

#### Unity

https://qiita.com/wakuto/items/4201af5ee753e2e5d776

https://qiita.com/kirurobo/items/013cee3fa47a5332e186

など数え切れないほどのアバターを表示する試みを観測することができます
ただ、概ね表示することで満足しているプロジェクトが多く、アマゾンの奥地で生きているのかもしれない彼らをなんとかして発見したい気持ちはあります

### 現代
調べてみると現代でもいくつかの試みがあるようです
steam上では、
Desktop Mascot Engine

https://store.steampowered.com/app/821060/Desktop_Mascot_Engine/

Desktop Kanojo

https://store.steampowered.com/app/1284820/Desktop_Kanojo/

他にもたくさんのアプローチを見ることができます

### OSS
オープンソースソフトウェアでは、neco-arc-gptというものを見つけることができます

https://github.com/topics/desktop-mascot

まだ手元でビルドしていないのでわからないですが、一応モデルの差し替えは可能で、VRMモデルを読み込むことができるようです
OpenAIのAPIを入力することでチャットが可能とのことなんですが、動作風景をみたいです

### 機能
伺かや立ちアコに見た未来というのは、アスラーダの影を追っているのではないかと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11300/fef960b4-9261-24c1-9bad-aaf6565019b7.png)

なので、スケジューラーやメールの受信通知や各種チャットの統合インターフェースであったり、簡単なマクロ機能など、思いつく限りのユーティリティが詰め込まれていたのはそういう理由もあるかと思います

改めて現代のイルカを作るのであれば、モデルには話してもらいたい、スケジュールはいい感じで押さえてほしい、喋ってる内容からいい感じでオンライン会議のURLを発行してほしい、資料をまとめてほしい、など、つまり**めっちゃ優秀な秘書がほしい！**
というかんじではないでしょうか
そんな気持ちについてポエムを残しておくことにしました

一緒に作ってくれる人いないかなぁ・・・
DIVER OSINT CTF 2024 writeup

2024/06/08から2024/06/09まで行われたDIVER OSINT CTFに参加しました。
部員とチームを組んで参加したのですが、自分が解いた問題についてのWriteupを残しておこうと思います。

## dream
> 画像に写っているパイプオルガンがある施設の郵便番号を答えなさい。
Flag形式: Diver24{123-4567}

![dream.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813397/b15347f6-00ba-2b7d-80a9-ea7bccf90bac.jpeg)

- https://www.google.com/imghp

画像検索すると、、下記がでてきた。

- https://g.co/kgs/Ak51h8b

Flag: `Diver24{574-0046}`


## leak

>先月、日本の会社で大規模なBTCの不正流出が起きた。
流出先となっているウォレットアドレスを答えよ。
Flag形式: Diver24{ウォレットアドレス}


つい最近、起こった某企業のBTCの不正流出のことですね。
なら、調べてみましょう...
今回流出先のウォレットアドレスなので、下記のとおりとなる。

Flag:`Diver24{1B6rJRfjTXwEy36SCs5zofGMmdv2kdZw7P}`

## youtuber
> 2023年、あるYouTuberが日本で無賃乗車や無銭飲食を行い、その様子を投稿したことで問題となった。
彼は日本である列車に無賃乗車をしていたところ、九州地方のある駅で一度捕まったが、そのまま逃走して別の列車に再び無賃乗車をした。
彼が捕まった駅と、乗り継いだ列車の列車番号を教えてほしい。なお、列車番号は時刻表に掲載されている形式で回答せよ。
Flag形式: Diver24{駅名_列車番号}
例えば、折尾駅で捕まり、456Mという列車に乗り換えた場合、Diver24{折尾_456M} となる。

このひと、X(old Twitter)で確認していたため、単純に見つけるのは簡単だったが、最初、参考にした動画が低画質のため、博多行が見えず、探すことが億劫になってしまった。

休憩してからまた、もう一度該当する動画を探しました。

![スクリーンショット 2024-06-11 18.55.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813397/3a268624-a589-fc06-68da-afa62a262915.png)

- https://youtu.be/KAoL7pgAlm8?t=262



高画質な動画を見つけ、`さくら、572 次は博多`とありましたので、新幹線さくら572が博多に停車する前の駅と新幹線さくらの列車番号を確認する必要があります。
調べて、、

Flag:`Diver24{新鳥栖駅_572A}`

> 参考サイト
- https://ekitan.com/timetable/railway/train?sf=5429&tx=90100-10564-543A&dw=0&departure=0650&dt=20240611
- https://timetable.jr-odekake.net/train-timetable/104121?date=20240217


## promoter
> 画像に写っている池沼を開拓した発起人の父親の命日を答えよ。
Flag形式: Diver24{yyyy/MM/dd}

![promoter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813397/553a5be2-f6d4-97b6-7ca3-84393cbb0793.jpeg)

- http://mar0921.seesaa.net/article/388830548.html

まずは、これは入鹿池だとわかった。

江崎善左衛門の父の亡くなられた年まではわかりますが...
命日はいつやと...

いろいろ資料を探っていたが、なかなか見つからなかったです...
じっーと眺めていたら、
ありました。

> 江崎善左衛門了也の父善左衛門宗度 は織 田信秀 の家臣
で尾張国知多郡 大高村(名 古屋 市緑 区大 高町)の 生れで
ある。信秀の軍に従い小牧 山に陣 を張 っていたが信秀没
後は信長の命に よ り小牧村 の守備 に任 じられ ていた。 天
正12年(1584)3月 の小牧 の役 には徳川方 につき,関 ケ
原の戦いには徳川 勢のために軍功 をたてた。義直が尾 張
に封ぜ られ ると,義 直 の命 に より名古屋か ら中仙道 に通
じる名犬街道 を開設 し,小 牧,善 師野,土 田等 の宿駅 を
開き地方 開発 に尽 くした。義直 の知遇を受け,寛 永4年
(1627)11月13日 に病没 した

出所:https://www.jstage.jst.go.jp/article/jjsidre1965/49/7/49_7_630/_pdf

Flag: `Diver24{1627/11/13}`



## paddy(解けてはない)
> この地域では地形の人工的な大規模改変が2回行われたという。郡司としてこれにかかわった人物の名は？
日本語表記で答えよ。
Flag形式: Diver24{人名}


![gsimap.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813397/68ac0207-b28e-1efa-cd8d-24cfaea4dac1.jpeg)



場所まではわかっていたが、郡司といったら、、
```
郡司は、日本の律令制下において、律令国内の各郡を治める地方官である。
中央官僚である国司の下で、郡の行政に当たり、その地の有力者が世襲的に任命された。 
律令制開始時に、古代からの地方豪族は、統治権は中央国家へ収公されたが、
彼らは、地方行政官として古代からの氏族制に基づき村落に対する行政を任された
```

これしか思い当たる節がなかったので、その時代の人々を検索してました...
日本語って難しいですね...

場所はわかったのになぁ。。。

場所は下記に...
- https://www.pref.miyagi.jp/bunkazai/map2/index.html#14/38.495955/141.222467/&base=std&ls=std&disp=1&vs=c1j0h0k0l0u0t0z0r0s0m0f1




## 感想
始めてOSINT問だけのCTFに出たのでとても楽しかったです。
他の人のwriteupをみると、こんなサイトがあるんだとか新しい発見がありました。Akeomeという問題に関しては、おそらくこの期間、捕まっていると考えていましたが、最後まで解き切ることはできませんでした。
大会期間中に粘れば答えがあるというのがOSINTのいいところだと思います。今後も開催されるようなので、参加したいと思います。
運営されていた方々、ほんとにいい機会を提供してくださり、ありがとうございました。
Spettro Remodels

If your family is growing or you simply crave more space, an addition to your home can be a transformative investment. Spettro Remodels, an experienced addition construction company in Springville, understands that each square foot of your home is valuable real estate. Whether you're dreaming of a sunroom, an enlarged kitchen, or a second-story add-on, we recognize the significance of personalizing your living space to fit your lifestyle needs.

1. Tailored Design Approach: Every home extension project begins with meticulous planning and design tailored to match your vision while harmoniously blending with your existing structure. Our team at Spettro Remodels takes pride in collaborating with homeowners to create additions that enhance both function and aesthetics seamlessly.

2. Comprehensive General Remodeling Services: Expanding your home provides the perfect opportunity to not only add space but also upgrade interiors. Be it revamping the flooring or infusing new life into old rooms; our comprehensive remodeling services ensure consistency throughout your newly extended and existing spaces.

3. Custom Carpentry for Distinctive Accents: Additions are about more than just extra room; they're about adding character and value to your home. Our custom carpentry services allow for unique architectural details, such as built-in shelving or bespoke staircases that echo personal style while remaining true to the current layout.

4. Durable Siding Solutions: Protecting the exterior of your addition is just as important as crafting its interior beauty. We offer siding options suited for Springville’s climate to safeguard against elements while complementing the look of your overall home.

5. Basement Finishing Opportunities: If elevation isn't part of the plan, why not expand downwards? A professionally finished basement can double as a guest suite, entertainment area, or even a workspace adding functional square footage within the existing footprint of your home.

6. Quality Roofing Systems Integration: A new addition requires a sturdy roofline extension or integration that not only matches but fortifies against weather wear-and-tear over time. With Spettro Remodels’ roofing expertise, rest assured that continuity is maintained from every shingle down to the last waterproof seal.

For homeowners looking into expansion possibilities whether vertical additions smartly crafted above ground level or subterranean spaces reimagined Spettro Remodels leverages precision craftsmanship and dedicated attention to detail in all stages from concept realization to final finishes.
Choosing the right construction partner means picking someone who listens closely and transforms those discussions into tangible reality effectively while respecting timelines and budgets a commitment we uphold at Spettro Remodels for residents in Springville seeking exceptional service for their addition construction projects.
497 West 200 S, Springville, Utah, 84663
Monday  - Friday :08:00 - 18:00
(385) 332-3253
levi@myspettro.com
https://www.myspettro.com/
Postfixの構築 - queue file write error

# はじめに

Dockerベースでpostfixの環境を作成しており、その際のつまづきポイントを記録として残す。

# 構成（前提条件）

環境としてはLinuxベースのhost(debian)にDockerにてイメージをフルスクラッチで作成。ベースイメージとしてはdebianのbookwormを採用。最初はminimumのイメージで作成していたが色々パッケージ不足等々で躓くところが多いので普通のイメージベースを採用しています。またLDAPにてユーザー管理を行う。

# なにが起きたか

とりあえず正常に起動するところまでは設定を行いメールクライアントから送信テストを行った際に下記のエラーが出た。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17219/117d688c-2fbd-ac0d-84a5-1294d3b71756.png)

# まず疑った部分

logを見ると

```
error: unsupported dictionary type: ldap
```

が出ている。つまりLDAPが有効になっていない。しかしインストールしたパッケージを確認すると下記のようにpostfix-ldapは入れてある

```
# dpkg -l|grep postfix
ii  postfix                     3.7.10-0+deb12u1               amd64        High-performance mail transport agent
ii  postfix-ldap                3.7.10-0+deb12u1               amd64        LDAP map support for Postfix
ii  postfix-policyd-spf-python  3.0.4-2                        all          Postfix policy server for SPF checking
# dpkg -l|grep ldap   
ii  dovecot-ldap                1:2.3.19.1+dfsg1-2.1           amd64        secure POP3/IMAP server - LDAP support
ii  libldap-2.5-0:amd64         2.5.13+dfsg-5                  amd64        OpenLDAP libraries
ii  libsasl2-modules-ldap:amd64 2.1.28+dfsg-10                 amd64        Cyrus SASL - pluggable authentication modules (LDAP)
ii  postfix-ldap                3.7.10-0+deb12u1               amd64        LDAP map support for Postfix
# dpkg -l|grep libc6
ii  libc6:amd64                 2.36-9+deb12u7                 amd64        GNU C Library: Shared libraries
ii  libc6-dev:amd64             2.36-9+deb12u7                 amd64        GNU C Library: Development Libraries and Header Files
```

そしてモジュールのロードの設定としては下記のものを記載している。

```
# cat /etc/postfix/dynamicmaps.cf
# dict-type     so-name (pathname)      dict-function   mkmap-function
ldap    postfix-ldap.so dict_ldap_open
```

仮にこの記載が反映されていないのであれば

```
dynamicmaps=yes
```

でビルドされた物であればこの設定によりLDAPサポートが有効化されるはずなのでおそらくそこが問題？と思ったが結論としては下記のものが問題だった。

ふと有効な機能の確認をしていた際に最初は見逃していたが一行目に設定ファイル絡みのwarningが出ている。

```
# postconf -m
postconf: warning: /etc/postfix/dynamicmaps.cf: file is owned or writable by non-root users -- skipping this file
btree
cidr
environ
fail
hash
inline
internal
memcache
nis
pipemap
proxy
randmap
regexp
socketmap
static
tcp
texthash
unionmap
unix
```

設定ファイルのownerをrootにしてサービス再起動後確認するとldapが出てきた

```
# postconf -m
btree
cidr
environ
fail
hash
inline
internal
ldap
memcache
nis
pipemap
proxy
randmap
regexp
socketmap
static
tcp
texthash
unionmap
unix
```

ポイントとしてはDockerでホストのボリュームをマウントして設定ファイルを読み込ませているので、ここのファイルの権限が変化していたという事。最初にQueueに書けないというエラーの段階でQueueとMailDirの権限は疑っていて確認したが設定ファイルの権限はwarningが出ているだけで読み込まれていると思ったのでまさかの原因だった。

# 結論

Dockerを使用すると内部のUID/GIDに引きずられて色々な事が起きるのでファイルの権限系は適当にせずにしっかり設定しましょうという話・・・。
ReactHooksでDeepCompareしてレンダリングを抑制する

## 意図しないタイミングで大量に再レンダリングが発生

useEffectやuseMemoを使う際、複雑な構造のObjectやArray型を第2引数に指定すると意図しないタイミングで再レンダリングが走ってしまうことが多々あったため、深い比較（DeepCompare）をするためのCustomHookを作ってみました。

## なぜ意図しないタイミングで再レンダリングされるのか？
以下の記事で丁寧にまとめられているため詳しい解説は割愛しますが、要するにReactHooksの内部で `===` での比較がされているのが原因でレンダリングが発生してしまうものを、今回はCustomHookの中で深い比較に変えて対応してしまおうという形です。

https://qiita.com/kutarou197/items/a09b6aa5d24c5319f470


## 前提環境
- react@17.0.2
- 深い比較には `fast-deep-equal@3.1.3` を使用
- 複雑なデータをフロントで扱わざるを得ないシステムなため、useEffectやuseMemoには多次元配列や深くネストしたObjectを構わず指定していく


## 実際のコード
### 共通で使う関数
```ts
import * as React from 'react'
import * as deepEqual from 'fast-deep-equal'
import { DependencyList } from 'react'

// 以下ページのコードをそのまま利用
// https://stackoverflow.com/questions/54095994/react-useeffect-comparing-objects
function useDeepCompareMemorize(value: DependencyList[number]) {
  const ref = React.useRef()

  if (!deepEqual(value, ref.current)) {
    ref.current = value
  }

  return ref.current
}
```

### deepEqualでの比較を用いたuseEffect
```ts
export function useDeepCompareEffect(
  callback: React.EffectCallback,
  dependencies: DependencyList
) {
  // eslint-disable-next-line react-hooks/exhaustive-deps
  React.useEffect(callback, dependencies.map(useDeepCompareMemorize))
}
```

### deepEqualでの比較を用いたuseMemo
```ts
export function useDeepCompareMemo<T>(
  callback: () => T,
  dependencies: DependencyList
) {
  // eslint-disable-next-line react-hooks/exhaustive-deps
  return React.useMemo(callback, dependencies.map(useDeepCompareMemorize))
}
```

### deepEqualでの比較を用いたuseEffectで、かつ初回の実行を無効にしたもの
```ts
export const useDeepCompareUpdateEffect = (
  callback: () => void,
  dependencies: DependencyList
) => {
  const isFirstRender = React.useRef(true)
  useDeepCompareEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false
      return
    }
    return callback()
  }, dependencies)
}
```

## 使い方
普段useEffectやuseMemoを使うのと同じように使います。

```ts
const obj = { hoge: 'hoge', fuga: 'fuga', nest: { hoge: 'hoge', fuga: 'fuga' } }

useDeepCompareEffect(() => {
  // do something
}, [obj])

useDeepCompareUpdateEffect(() => {
  // do something
}, [obj])

const value = useDeepCompareMemo(() => {
  // do something
}, [obj])


```
CSSの関数

# CSSの関数

個人的「質はともかく継続する」4日目です。

## CSSで使える関数

先日はカスタムプロパティについて説明しました。

[CSSで変数を扱う](https://qiita.com/moonWalf/items/e15030c44e3c09c74252)

今回は関数についてメモ書きしていきます。

### calc()

calc()関数は四則演算を行う関数です。
異なる単位の値の計算も可能です。
主な活躍場面はレスポンシブのときでしょうか。

```css
width: calc(100% - 20px);
```

### attr()

attr()関数はHTML要素の属性値を取得します。
主にcontentプロパティで使われるようです。
私は使ったことがないですが、属性にあらかじめ値を用意して置けるのは便利ですね。

```html
<div data-text="Hello"></div>
```

```css
div::before {
  content: attr(data-text);
}
```

### counter()

counter()関数はカウンターの値を取得します。
主にリストの番号をカウントするときに使われるようですが、
使う場面があるのか...?

```css
ol {
  counter-reset: section;
}

li::before {
  content: counter(section) ". ";
  counter-increment: section;
}
```

### おわりに

今日はCSSの関数についてメモ書きしてみました。
counter()関数の使い所ってどこなんだろう。。。