OmniAICreator/Qiita-1.07M huggingface dataset:
asciidocでタイトルの色だけ変える

# adocファイルの修正

`:stylesheet: default.css`をヘッダに追記する。
同じ場所に置く場合は`:stylesdir:`の指定も不要。

```
# (タイトル)
:nofooter:
...
:stylesheet: default.css
```

# cssの作成
[公式](https://docs.asciidoctor.org/asciidoctor/latest/html-backend/default-stylesheet/#customize-extend)に載っているやりかただと
_図1_ とか _表1_ とかのタイトルがオレンジ色のままなのでそこも変更する。
また、タイトルの色を変えると本文と見分けがつかないので太字にするなどする。

```css
@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";
@import "https://cdn.jsdelivr.net/gh/asciidoctor/asciidoctor@2.0/data/stylesheets/asciidoctor-default.css";

h1, h2, h3, h4, h5, h6, #toctitle,.sidebarblock > .content > .title {
  color: rgba(0, 0, 0, 0.8);
  font-weight: bold;
}
div#toctitle {
  color: rgba(0, 0, 0, 0.8);
}
.paragraph> .title, table.tableblock >.title {
  color: rgba(0, 0, 0, 0.8);
}

```

尚、ネットから取ってこなくても以下にある。
```
/path/to/gem_dir/asciidoctor-x.x.xx/data/stylesheets/asciidoctor-default.css
```


# ビルド
変換コマンド時にcssの指定をするような記載が見受けられるが
vscodeでhtml変換するならデフォルトのままで問題なかった。

---

参考:https://docs.asciidoctor.org/asciidoctor/latest/html-backend/default-stylesheet/#customize-extend
Amazon Linux 2023 にnet-snmpを入れる(2023年5月時点)

# 【注意】この記事の内容は古くなりました

Amazon Linux 2023 でも `net-snmp` のパッケージが利用できるようになりました。
特に理由がなければ、公式パッケージをご利用ください。
[https://docs.aws.amazon.com/linux/al2023/release-notes/new-AL2023.0-AL2023.1.html](https://docs.aws.amazon.com/linux/al2023/release-notes/new-AL2023.0-AL2023.1.html)

以下の内容は、過去の情報としてご参照ください。

# はじめに

Amazon Linux 2023 からは `net-snmp` パッケージが削除されています。
参考：[削除されたパッケージ - Amazon Linux 2023](https://docs.aws.amazon.com/ja_jp/linux/al2022/release-notes/removed-packages.html)


このため、snmpdを利用して各種監視を行っている場合に困ったことになります。
というわけで Amazon Linux 2023 にソースコードからnet-snmpをインストールして設定してみました。

# 手順

[SourceForge](https://sourceforge.net/projects/net-snmp/files/net-snmp/5.9.1/) から圧縮アーカイブされているソースコードをダウンロードします。
※説明例では `net-snmp-5.9.1.tar.gz` をダウンロードしたものとして記載します。

```shell
# 必要パッケージのインストール
dnf install gcc make
# 別途ダウンロードしたファイルを解凍
tar zxvf net-snmp-5.9.1.tar.gz
cd net-snmp-5.9.1
# コンパイル・インストール等
./configure
make
make install
```

インストール後、まずはsnmpdの設定ファイルを準備します。
※各環境に合った設定ファイルをご用意ください。
```shell
mkdir -p /usr/local/etc/snmpd/
vi /usr/local/etc/snmpd/snmpd.conf
```

設定ファイルを用意したら、Systemdを使ってデーモン化を行います。
```/etc/systemd/system/snmpd.service
[Unit]
Description=snmpd daemon
Requires=network.target
After=network.target

[Service]
Type=simple
KillMode=process
User=root
Group=root
PIDFile=/var/run/snmpd.pid
Environment="CONF=/usr/local/etc/snmpd/snmpd.conf"
Environment="OPTIONS=-f -LS 5 d -a -Lf /dev/null"
Environment="PIDFILE=/var/run/snmpd.pid"
ExecStart=/usr/local/sbin/snmpd $OPTIONS -c $CONF -p $PIDFILE
ExecReload=/usr/bin/kill -HUP $MAINPID
ExecStop=/usr/bin/kill -TERM $MAINPID
Restart=always

[Install]
WantedBy=multi-user.target
```

```shell
systemctl enable snmpd.service
systemctl start snmpd.service
```

デーモン起動後に `snmpwalk`などを利用して動作確認を行います。

# さいごに
AWSさん、パッケージ消しすぎでは？
OpenAIドキュメントから学ぶプロンプトエンジニアリングと評価方法

プロンプトエンジニアリングのお勉強のため、OpenAIのドキュメントを読んで学んだことをメモ

## プロンプトデザイン

https://platform.openai.com/docs/guides/completion/prompt-design

### 大事なこと
- **Show and tell** : 明確に。指示でも例でも。
  - 目指すべき生成が明確か
- **provide quality data** : 適切な例を与える。
  - 十分な例があるか
  - 例のミスはないか
- **check your settings** : temperatureやtop_pの設定で決定論隔離を決める
  - temperatureやtop_pの設定は適切か

## 嘘をつかないようにするためには
- プロンプトに正しい情報を与えてそこから答えさせるようにする
- わからなそうな回答には"わからない"と答えさせるようにpromptで指示する

https://platform.openai.com/docs/guides/completion/factual-responses

## ChatCompletionについて
- createCompletion() と ChatCompletionがある
- 基本ChatCompletionを使えばいい
  - `gpt-4` はChatCompletionのみ対応
  - gpt-3.5 も 安価な `gpt-3.5-turbo` はChatCompletionのみ対応
- roleがある
  - system: asistantの挙動を決める
  - asistant: userの問いかけに対して返答する
  - user: 問いかけする人
- 出力JSON内のfinish_reason: 出力が終了した理由が記載される
  - stop: シンプルに出力終了
  - length: 出力トークンが上限に達したため. 再度リクエストする必要あり
  - content_filter: 出力内容がフィルターに引っかかったため
- 使用したtokenは `response['usage']['total_tokens']` をみる

https://platform.openai.com/docs/guides/chat/response-format


## 評価の話

- APIの出力を測定し、モデルを評価する軸を持つことが大事
- ただしLLMの評価は非常に難しい
- まずは手動で出力を確認してみることが一番シンプルな方法

https://platform.openai.com/docs/guides/production-best-practices/evaluation-and-iteration

# リンク集
- プロンプトをより信頼性のあるものに改善するためのドキュメント

https://github.com/openai/openai-cookbook/blob/main/techniques_to_improve_reliability.md

- OpenAIの例題集

https://platform.openai.com/examples
Rails 7でバリデーションエラーが表示されるようにした

# はじめに
Rails学習のために入力フォームに対して無記入、または140字を超えた入力をするとエラーメッセージを表示させる機能を作っていたが、[お手本](https://prog-8.com/)通りにやっても、`render`で返っては来るがエラーメッセージは表示されない。
ということが起こったので、解決に至った対処法を残しておく。

#### 環境
Ruby 3.2.1
Railes 7.0.5

```ruby:お手本(controller.rb)
  def update
    @post = Post.find_by(id: params[:id])
    @post.content = params[:content]
    if @post.save
      redirect_to("/posts/index")
    else
      render :edit
    end
  end
```


# 対処法
お手本コードの`render ("posts/edit")`のあとに、`status: :unprocessable_entity`を追記する。
```ruby:追記後のコード(controller.rb)
  def update
    @post = Post.find_by(id: params[:id])
    @post.content = params[:content]
    if @post.save
      redirect_to("/posts/index")
    else
      render :edit, status: :unprocessable_entity
    end
  end
```

これで無事にエラーコードが表示されるようになった。



# なんで表示されるようになった？
参考にさせてもらった[こちら](https://losenotime.jp/rails7-errors_message-422/)によると、
>`status: :unprocessable_entity`は、HTTPステータス＝422を返しますという意味
>422はサーバ側がリクエストを理解しているのに, ユーザ側の問題で処理できないケース
>すなわちRailsでは, バリデーションエラーのときに返却するコード
>
>Rails7ではフロントエンド技術としてTurboが標準でインストールされ, サーバ側にPOSTリクエストが行われた場合, Turboは新しいビューに303リダイレクトされることを想定しています。

つまり、なにも指定しなければ303リダイレクトされてしまうので、エラーメッセージを表示させたい場合は422を返しますと明示的に宣言する必要がある。
brew servicesの使い方

## 前書き

systemdに慣れる方には、brew serviceはよく紛らわしい存在かなと思います。サービスの「起動」と「自動起動の有効化」が一つのコマンドに纏められたので、知ってる方には便利だけど、逆に動作がわからない感じもう生じますね。


## コマンド

### [sudo] brew services [サブコマンド]

macOSのlaunchctl(1)デーモンマネージャーを使用して、バックグラウンドサービスを管理します。

sudoが指定された場合、/Library/LaunchDaemons（起動時に開始）で操作します。そうでない場合は、~/Library/LaunchAgents（ログイン時に開始）で操作します。

### brew services [list] (--json)

現在のユーザー（またはroot）のサービス一覧を表示します。`list`は指定しなくてもいいです。

### brew services info (サービス名|--all|--json)

サービスの詳細情報します。

```bash
$ brew services info mysql
mysql (homebrew.mxcl.mysql)
Running: ✘
Loaded: ✘
Schedulable: ✘
```

### brew services run (サービス名|--all)
サービスを起動します。

### brew services start (サービス名|--all|--file=)
サービスを起動し、ログイン時にも自動起動するように登録します。

### brew services kill (サービス名|--all)
サービスを停止します。

### brew services stop (サービス名|--all)
サービスを停止し、ログイン時に自動起動の登録を解除します。

### brew services restart (サービス名|--all)
サービスを再起動し、ログイン時にも自動起動するように登録します。

### brew services cleanup
未使用のすべてのサービスを削除します。

### オプション

- --all：すべてのサービスに対してサブコマンドを実行します。
- --json：JSON形式で出力します。
- --file: Use the service file from this location to start the service.

## 参考

[公式サイト](https://docs.brew.sh/Manpage#services-subcommand)を参照すればすぐわかります。
私的データベースサーバー構築論


# データベースサーバーについて

弊社では、プログラム開発がメインでデータベースサーバーの構築を請けることは少ない。
すでにデータベースサーバーは構築された状態で、開発したプログラムの設定や、プログラム改修に合わせたデータベースの変更を適用したりがメインである。

まれに、この部分もやらせていただくことがあり、その時は、自社で構築している方法を提案させていただいている。
この記事では、この方法の紹介させていただきます。（数社、採用していただいています）

障害発生時の早期復旧、リカバリ機能の多重化に重きを置いて考えています。
ただし、サーバー管理専任者がいるような規模のシステムには向いていません。
また、最悪、前日までのデータが復旧できれば良いということで納得できるシステム向けです。


# 弊社提案データベースサーバー構築

## 構成

ディスクディバイスは、３台に分散します。
大容量のディスク１台を分割して使用するのでなく、３台に分散します。

３台の割り当てです。
１．サーバーＯＳをインストールします。(Cドライブとします)
２．仮想マシン化したデータベースサーバーを組み込みます。(Dドライブとします)
３．バックアップ or 仮想マシンなど。(Eドライブとします)
Hyper-Vについては、本体のライセンスで、2台まで仮想マシンが作成できます。
３の仮想マシンは、テスト用のデータベースを乗せるという使い道もあるし、リモートディスクトップで使うという使い道もあると思います。

３台に分散する意図は、ディスクアクセスを分散させるということを考えてます。
画期的に効果があるわけではないですが、大きなファイルを扱う場合など、ちょっとだけ効果があります。
また、３台まとめて同時に壊れる確率は少ないと思うので、修復コストを減らせると言う狙いもあります。


## バックアップ（仮想マシン）

２，３の仮想マシンがとりあえず、稼働状態までインストール出来たら、それぞれの仮想マシンにドライブを互い違いにコピーしておく。
Dドライブの仮想マシンをEドライブに、Eドライブの仮想マシンをDドライブにという具合に。
とりあえず、どちらかのドライブが故障しても、仮想マシンの初期状態のものはバックアップをとって、復旧時の手間を減らす意図です。
Dドライブが壊れた場合、Eドライブのバックアップから仮想マシンは復元でき、最新のデータのバックアップをリストアすることで前日までの状態に戻せることになる。

## バックアップ（ＤＢデータ）

ＤＢデータは、バッチファイルなどで、C,D,Eドライブにバックアップをとれば、3カ所にとることになる。
これプラス、NASなどにとっておけば、バックアップ先としては十分であろう。
バックアップバッチファイルは、ＡＭ１時ぐらいにスケジュールしておけば、前日分のバックアップはとれることになります。
バックアップのファイル名を工夫すれば、例えば曜日を入れるとかすれば、直近の1週間分はバックアップがあるということになる。
この辺りは、バッチファイルの作り方でいろいろ工夫できると思います。


# おわりに

## RAID組んでもデータベースのバックアップはしよう

RAIDが組んであれば、バックアップが必要ないと思っているサーバー機器販売事業者もいるようでバックアップをとることをしていないシステムをまれに見ます。
RAID-2を組んだシステムで運用されていたところで、ディスク障害が起きているようなので、一度見てくれないかと言われた会社での出来事です。
RAIDから障害が起きた旨のメッセージのようなものが出たようなのですが、英語でよくわからないメッセージだったのでそのまま無視して使用を続けたようです。
その後何度かサーバーの再起動がされたようで、健全なディスクから故障ディスクへのリカバリされていたようです（ただし、コピー先は故障中なので、一部欠損状態）
何度目かの再起動が行われたとき、逆方向、故障ディスクから健全だったディスクへのリカバリ処理が発生。
結果、最初に故障したディスクの内容が２台のディスクに残るということになってしまいました。（故障後の2台のディスク内容からの推測です）
データ復旧会社に復旧可能か確認したそうなのですが、最初に壊れたディスク時点の情報しか残っておらず、ちょっと古いデータが、取り出せるかどうかということだったようです。
その後、このサーバーがどうなったかは聞いていません。
とりあえず、新しいサーバーではバックアップをするように、弊社で作ったバックアップ用のソフトを渡しておきました。

## リストアのテストは、時々しよう

まれにバックアップ用のバッチファイルがまずくて、バックアップがうまく取れていないことがあったりするので、稼働後しばらくしてから一度リストアができるか、テスト機などにリストアのテストを行うようにしておくことをお勧めします。
バックアップとリストアのプログラムのバージョンが異なると、パラメータが若干変わっていたりします（経験済み。そのときはちょっと焦った）。その確認もできます。
Salesforce認定Platformアプリケーションビルダー試験の公式サンプル問題解説してみた-18

こんにちは
本橋孝昭です

Salesforce認定アプリケーションビルダーの公式練習問題があるのはご存じでしょうか

フラッシュカードで何度も解ける練習問題がございます

今回は
Platform アプリケーションビルダー試験に向けた学習
認定 Platform アプリケーションビルダー資格の受験準備: Data Modeling and App Deployment (データモデリングとアプリケーションリリース)

4問目を紹介します

https://trailhead.salesforce.com/ja/content/learn/modules/platform-app-builder-pt2/platform-app-builder-deployment?trail_id=platform-app-builder-certification-prep&trailmix_creator_id=welcome4&trailmix_slug=prepare-for-your-salesforce-platform-app-builder

![ふる.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4b03f87a-1b9d-0a5a-a11e-fd3d5f701041.png)

正解はAです

Sandboxはいくつか種類があり、特定の目的により特定のSandboxを正しく使用しましょう

![さんど.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/a7a7b6e5-51d4-e4aa-a64c-44daf5b9d022.png)

こちらのように本番環境に一番近い状態で作成できるSandboxは一番右のFull Sandboxです

Full Sandboxの詳細はこちらから確認できます
https://help.salesforce.com/s/articleView?id=sf.create_test_instance.htm&type=5

Full Sandbox は、テスト環境として使用されることを目的としています。パフォーマンステスト、負荷テスト、およびステージングをサポートするのは Full Sandbox のみです。Full Sandbox は、すべてのデータ (オブジェクトレコード、添付ファイルなど) とメタデータを含む、本番組織の複製です。Full Sandbox は更新間隔が長いため、開発には向いていません。

上記のようにFull Sandboxは今回のようにテストには向いてますが開発には向いていません

各々のSandboxの特性をよく理解しましょう


## ほかのSalesforce認定アプリケーションビルダーの問題の解説などはこちらから

https://qiita.com/Takaa/items/6434c5838e23f409d01f
ansibleで自動的にGitlabのIssueを作成してみた

## 背景
業務の中でansibleで自動的にGitlabのIssueを作成させる機会があったため、
備忘録的にplaybook等についてまとめておきます。

## 利用したもの
- Ansible
- Gitlab

### プログラム
汎用的なソースコードを以下に記載します。

- Playbook
```yml:main.yml
---
- name: GitLab issue variable 
  hosts: localhost
  vars:
    gitlab_api_token: "GitLabのAPIトークン"
    gitlab_project_id: "GitLabのIssue作成先プロジェクトID"
    gitlab_server: "GitLabサーバIPアドレス"
    issue_title: "Issueのtitle"
    issue_description: "Issueのdescription"
    issue_labels: "付与するラベル名"

  tasks:
    - name: Create Gitlab issue
      uri:
        url: "https://{{ gitlab_server }}/api/v4/projects/{{ gitlab_project_id }}/issues"
        method: POST
        headers:
          "PRIVATE-TOKEN": "{{ gitlab_api_token }}"
        body_format: json
        body:
          title: "{{ issue_title }} "
          description: "{{ issue_description }} "
          labels: "{{ issue_labels }}"
        status_code: 201
        validate_certs: no
      register: new_issue
```

また、既存のIssueをiidで指定して、更新することも可能です。

```yml
    - name: Update issue title with issue ID
      uri:
        url: "https://{{ gitlab_server }}/api/v4/projects/{{ gitlab_project_id }}/issues/{{ new_issue.json.iid }}"
        method: PUT
        headers:
          "PRIVATE-TOKEN": "{{ gitlab_api_token }}"
        body_format: json
        body:
          title: "{{ issue_new_title }}"
        validate_certs: no
      register: update_issue
```


## 工夫点
:::note info
ansibleで自動でGitLabのIssueを作成することで、手動で実施する手間を省くだけでなく、入力ミスなどを防ぎました
:::

## 終わりに
今回、GitLabのIssueの作成を実施しましたが、既存のIssueに対する処理や、クローズ処理なども自動化してより業務の効率化を図っていきたいと思います。
ChatGPTライクなUIを実装する【FastAPI + Next.js】

# 目次
[完成イメージ](#完成イメージ)
[バックエンド(FastAPI)の実装](#バックエンドの実装)
[フロントエンド(Next.js)の実装](#フロントエンドの実装)
[成果物](#成果物)

# 完成イメージ
ChatGPTのようにレスポンスを1文字ずつ表示する仕組みを作りたい。
![videos.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526938/50fbf0ca-c9c7-dbb6-eb98-55180f901902.gif)

# バックエンドの実装
* app/routers/chatai.py ファイルを作成し、streamレスポンスを返すプログラムを書く。
以下のファイルを作っただけではもちろん動かないので、main.pyで[インスタンスを書いて](https://zenn.dev/sh0nk/books/537bb028709ab9/viewer/86648d)あげよう。

```python
import openai
from fastapi import APIRouter, Request
from fastapi.responses import StreamingResponse

router = APIRouter()


def chatgpt_streamer(msg: str):
    openai.api_key = "ここにはあなたのopenaiのapiキーを書いてください"
    result = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": msg}],
        stream=True,
    )
    for chunk in result:
        if chunk is not None:
            content = chunk["choices"][0]["delta"].get("content")
            if content is not None:
                yield content


@router.post("/chatgpt")
async def chatgpt_stream(request: Request):
    # request.bodyはjson形式でリクエストが投げられることを想定
    # 例） {"message": "100文字の文章を書いて"}
    msg = await request.body()
    return StreamingResponse(
        chatgpt_streamer(msg=msg.decode()), media_type="text/event-stream"
    )
```

# フロントエンドの実装
サンプルではconsole.logで結果を表示しているが、本来はuseStateを使って文字列を画面に表示することになる。
```tsx
const response = await fetch(`/chatgpt`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ message: "100文字の文章を書いて" }),
});

const data = response.body;
const reader = data.getReader();
const decoder = new TextDecoder();
let done = false;
let result = "";

while (!done) {
    const { value, done: doneReading } = await reader.read();
    done = doneReading;
    const chunkValue = decoder.decode(value);

    result += chunkValue;
    console.log(result + (done ? "" : "▊"));
}
```

# 成果物
![sample_chagpt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526938/b7ab57a1-a8b1-0ca9-bbf6-fd44e6b413ac.gif)

:::note warn
ロードバランサ（BIGIPなど）を使っているとstreamができないように設定されているサービスもあるので、その場合は設定を変更してあげよう
:::
いつの間にかGitHubの認証方法が変わっていたので…

WebエンジニアからAWSメインのエンジニアになってGitHubを使う機会が減ってしまい(反省)、、

先日GitHubにコードをプッシュしようと思ったんですができませんでした。

どうやら、2021年8月13日をもってパスワード認証は廃止されアクセストークン方式に変更されたようです。

https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/

設定方法について忘れないように備忘録がてら記事を書いておこうと思いました。

# 自己紹介

- 都内のDevOps系の企業でエンジニアをやっています。
- 主にAWSとTerraformを扱っております。
- フルリモートで勤務しております。
- 大阪在住、年齢は27歳、趣味は古着屋巡りと映画鑑賞です。

# 本記事の内容
- GitHubでアクセストークンを使って認証する方式を紹介
- あくまで個人開発用(HTTPS認証)
- 初心者向け

# 環境
実行環境については以下を使用しています。
- Ubuntu 22.04.2 LTS(Docker上でコンテナ起動)
- ローカルにGitは導入されている前提です。
- Gitのインストール方法についてはこちらから↓

https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

# リポジトリの作成

リポジトリ名は「test_github」としました。

![スクリーンショット 2023-05-30 15.14.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/8cc459fc-d30f-5a15-99cb-ab983fb8ce81.png)

# アクセストークンの取得
試しにGit Cloneしてリポジトリ記載手順の通りPushしようと試みましたが案の定エラーがでました。

当然と言えば当然ですが…

```
git init
touch test.txt
git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/Jun-Honda-0326/test_github.git
git push -u origin main
```

エラー画面
※パスワード認証は廃止された旨のメッセージが確認できます。
![スクリーンショット 2023-05-30 15.41.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/f4257e82-b900-2617-51b1-1897aec82bb0.png)


以下ドキュメントを参考にアクセストークンを作成していきます。

https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token


![スクリーンショット 2023-05-30 15.48.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/3c508045-5bd0-d9e1-dac3-78449262edb0.png)

※beta版ではなくclassic版を使用しています。

beta版が本格運用されればまた試してみたいと思います。

今回はリポジトリへのアクセスができれば良いので「repo」にチェックを入れます。

[Generate token]を押します。

すぐにトークンが生成されるので一旦メモ帳アプリなどにコピペしてください。

# 使用方法
git pushする際に聞かれるパスワードにアクセストークンを入力すればOKです。

```
root@04503a78188d:~/develop/test_github
Username for 'https://github.com': Jun-Honda-0326
Password for 'https://Jun-Honda-0326@github.com': *************(アクセストークンを入力)
```

無事プッシュができました。

![スクリーンショット 2023-05-30 16.14.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/e5e66cf5-da90-9ff4-1a10-32859c38fb49.png)

ちなみにユーザー名とパスワード(アクセストークン)はデフォルトの設定では毎回聞かれる仕様になっているので以下設定で省略可能です。

```
git remote set-url origin https://ユーザ名:アクセストークン@github.com/ユーザ名/リポジトリ名.git/
```

# 注意事項
アクセストークンは最初に有効期限を設定しているはずなので期限が切れた場合は、以下画面から「Regenerate token」を押して再度トークンを生成し設定し直す必要があります。
※設定手順は同じ

![スクリーンショット 2023-05-30 16.24.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/026ccbc7-c2f3-3893-52ed-4c72a8da6968.png)


これで本記事は終了します。

今後も自分の備忘録やアウトプットをこのQitaに残していきたいと思いますのでよろしくお願いいたします。
ゲーム開発につながる近道「ThunderFire UX Tool」を紹介

# ThunderFire UX Tool：デザイナー向けUnity UIの解決案
![](https://storage.googleapis.com/zenn-user-upload/fe2369352450-20230530.png)
​
NetEase ThunderFire UX Centerが開発を手掛けるThunderFireUX Toolは、ゲーム開発中のUI問題を解決するために一体化される無料Unity解決案です。インターフェースのスティッチング、レイヤの管理、コンポーネントの統合といった機能を兼ね揃え、チュートリアル、多言語翻訳、レッドドット等のゲーム汎用機能を同時に持っているThunderFireUX Toolは、デザイナーがUnityのインターフェースのスティッチング作業を素早くこなし、複数のプラットフォームにて多言語対応のプロジェクトのリリースに役立ちます。
​
**ThunderFire UXTool v0.9 “BeeEater” は現在Unity Asset Storeで利用可能になりました！**
​


-----
​
# ツールの特徴
- 【多言語対応】
世界中の主流言語に対応可能。一つのツール、幾つの言語。
- 【ローコードインターフェース作成】
デザイナーでもデザインソフトを使うようにスティッチング作業を手軽に行える。
- 【ゲーム通常機能のカプセル化】
開発効率化に繋がる近道、無駄な重複作業を省くこと。
- 【複数の入力デバイスに対応】
キーボード・マウス、ジェスチャー、コントローラーなど様々な入力方式に対応可能。
​
-----
​
# 注目機能
​
### 1.**コンポーネントライブラリ**
プロジェクトでよく使用されるプリファブをコンポーネントの形で収納、分類、管理し、すばやく作成して使用できるシンプルで直接的な可視化ライブラリです。
- コンポーネントの収納と管理
- コンポーネントの作成と使用
![](https://storage.googleapis.com/zenn-user-upload/e1a0733a69e3-20230530.png)
​
### 2.**チュートリアル**
テンプレートセットでチュートリアルのインターフェイスをすばやく作成するか、お好みに合わせてテンプレートをカスタムしてみましょう。
- シリアライズチュートリアルの迅速配置
- 様々なジェスチャープリセットとカスタマイズ
- 強・弱・弱のチュートリアルに対応
- コントローラガイドの配置
![](https://storage.googleapis.com/zenn-user-upload/4c8f72fddaf9-20230530.png)
​
### 3.**ローカライゼーション**
ローカライゼーションツールは、現在の主流言語の配置と内容の切り替え、多言語テキストや画像のワンクリック導入と認識、エディターでのプレビューと切り替え機能を提供します。
- テキストのローカライズ
- 画像のローカライズ
- 文字なしモード
![](https://storage.googleapis.com/zenn-user-upload/a49fae815f4e-20230530.png)
​
### 4.**レイヤー管理ツール**
レイヤー管理ツールは可視化管理プロジェクト中のレイヤー関係に使えます。レイヤー管理ツールを通して、パネルで全てのインターフェースのレイヤーを確認したり変更したりして、タグでインターフェースを統合することができます。
- レイヤー可視化パネル
- レイヤーのクイック移動と分類
- プロジェクトデータの同期
![](https://storage.googleapis.com/zenn-user-upload/ec2f71e3ca4b-20230530.png)
​
### 5.**レッドドットツール**
ゲームのレッドドット通知機能のために設計されたレッドドットツールは、木構造でレッドドットの表示パスを管理し、ワンクリックでオン・オフ効果を変更することができます。

![](https://storage.googleapis.com/zenn-user-upload/6aa005ebd52a-20230530.png)
​

以上の機能の他に、ThunderFireUXToolは、インターフェイス作成をサポートするベースラインなどのレイアウトツール、背景画像を迅速に生成するクイックツール、Prefabプレビューツールなどを提供し、Unityのイメージとテキストのウィジェットを拡張して、開発の効率性と利便性を向上させます。

​
-----
​
# 提携事例
ThunderFire UXToolは、配信中または開発中の沢山のネットイーズゲームと連携し、インターフェースツール、リソース検査、パフォーマンス分析などのカスタマイズされたサポートを提供し、ゲーム開発のさまざまな段階に適用され、プロジェクト開発の経験を蓄積しました。
​
![](https://storage.googleapis.com/zenn-user-upload/d8cf4cd0a646-20230530.png)
Dunk City Dynasty

![](https://storage.googleapis.com/zenn-user-upload/7014ec5cba05-20230530.png)
​NARAKA:BLADEPOINT スマホ版

![](https://storage.googleapis.com/zenn-user-upload/1748b7879675-20230530.png)
NARAKA:BLADEPOINT コンシューマー版

​
-----
​
# ThunderFire UXTool
内部と外部で複数回テストを行った後、ThunderFire UXTool　v0.9「BeeEater」バージョンは現在Unityの公式ストアでリリースし、長期間のオープンテストを行う予定です。新規プロジェクトでも開発中のプロジェクトでも利用可能。今すぐダウンロードして、活用しましょう！
​
**使用中に不具合が発生した場合は、下記の連絡先までお問い合わせください。
1、公式サイト
2、ThunderFireUXTool@service.netease.com
3、公式Discord：https://discord.gg/PKS6DehrAc
**
​
​
​
Unity アセットストア：

https://assetstore.unity.com/packages/tools/utilities/thunderfireuxtool-241533


公式サイト：

https://uxtool.netease.com/ja
​

**他のゲーム開発者に共有していただければ幸いです。
ThunderFire UXToolで効率よく、容易く成功を収めましょう！**
今更ながら、Source Han Code JPをVSCodeに設定してみたらいい感じだった

# はじめに
みなさまは、IDEのフォントに何を用いていますか？
デフォルトの方もいれば、いわゆるプログラミング用フォントなどを用いている方もいるのではないでしょうか。

プログラミングフォントといえば、最近`0xProto`というフォントが公開されていました

https://github.com/0xType/0xProto

これはこれで、悪くないなぁと思いましたが、今回は私が気に入って使っている`Source Han Code JP`の紹介をします。

# VSCodeへの設定手順（Macの場合）
### 1. フォントをダウンロード

https://github.com/adobe-fonts/source-han-code-jp/releases

上記のリンクから、以下の`Source code(zip)`を選択してダウンロードしてください。

### 2.zipの展開
### 3. Font Bookを立ち上げる
Macは、`Font Book`というフォントを管理するアプリが標準であります。
LaunchPad > その他 > Font Bookを立ち上げてください。

![Screenshot 2023-05-30 15.54.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735195/d0ee4025-222c-79d2-230b-fb0a83da6cb1.png)

### 4. フォントの追加
MacOS 13.0.1(Venture)だと以下の画面になります。

![Screenshot 2023-05-30 15.59.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735195/7c8e0d74-5996-a0bd-f00c-f23ba471b0da.png)

この「マイフォント」タブを設定した上で先ほど回答したフォルダを丸ごとドラッグ＆ドロップしてください。
そうすると、「源ノ角ゴシック　Code JP」というフォントが追加されます。

これでフォントの追加は完了です。

#### 5. VScodeにフォントの設定をする
1. VS Codeを立ち上げる
1. 基本設定 > 設定を選択
1. 検索窓にフォントと入力
1. テキストエディター > フォントを選択
1. Editor: Font Familyの箇所に「`"Source Han Code JP"`」と入力する
※ 複数フォントを指定する場合、左から優先されます。
1. Editor: Font Ligaturesの箇所にある`setting.jsonで編集`をクリック
1. jsonの`"editor.fontLigatures"`を`true`に設定する

##### Jsonサンプル
```json
{
  ... 各種設定 ...
  "editor.fontFamily": "\"Source Han Code JP\"",
  "editor.fontLigatures": true,
}
```

### 見た目

![Screenshot 2023-05-30 16.07.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735195/edcf5400-6eb3-7361-877d-c361244f8095.png)

以上です！
みなさまもおすすめフォントあれば教えてください！
【Django】Djangoを用いたWebサービス（ユーザー登録）

## はじめに
Djangoを用いたWebアプリケーションでユーザー登録機能を実装しました。
Djangoはデフォルトでユーザーモデルが設定されていますが、今回はDjango-Allauthを用いて実装。
実装内容とCustomUserを実装する上でのtipを書いていきます。

## 概要
ユーザー登録の基礎にはAllauthを使用。
CustomUserモデルの追加には**AbstractUser**を使用。
Djangoでは、ユーザーモデルの変更には**AbstractUser**と**AbstractBaseUser**のどちらかを継承する方法がりますが、今回の変更はフィールドの追加のみであり、かつ早く開発したかったため**AbstractUser**を使用しました。

## usersアプリの追加
```python:setting.py
INSTALLED_APPS = [
    (中略  以下追加)
    #django-allauth
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    #myapp
    'teamup_site',
]

...
AUTH_USER_MODEL = 'teamup_site.CustomUser' # 追加

```
Setting.pyのINSTALLED_APPに、今回用いるallauthを適応させます。

その下に、デフォルトのユーザーモデルではなく、teamup_webアプリ内のCustomUserモデルを使用すると記述します。


## models
CustomUserモデルを作成していきます。

```python:models.py
from django.db import models
from django.contrib.auth.models import AbstractUser,

from django.utils import timezone
from datetime import date

class Gender(models.TextChoices):
    MAN     = 'Man'
    WOMEN   = 'Women'
    OTHER   = 'Other'

class Work(models.TextChoices):
    SOFTWARE_ENGINEER       = 'Software Engineer'
    DESIGNER                = 'Designer'
    PLANNER                 = 'Planer'
    INFRASTRUCTURE_ENGINNER = 'Infrastructure Engineer'
    DATA_ENGINNER           = 'Data Engineer'

class CustomUser(AbstractUser, PermissionsMixin):
    username        = models.CharField(max_length=25)
    WORK_CHOICES    =[(w.value, w.name) for w in Work]
    your_job        = models.CharField(max_length=25, choices=WORK_CHOICES, default=Work.SOFTWARE_ENGINEER)
    GENDER_CHOICES  = [(g.value, g.name) for g in Gender]
    your_gender     = models.CharField(max_length=25, choices=GENDER_CHOICES, default=Gender.OTHER)
    birth_date      = models.DateField(blank=True, null=True,)
   
    def __str__(self):
        return self.username

```
書き方は、普通です。
特に追加する必要がない場合は、passで大丈夫です。

今回は、ユーザーの情報の他に職業の選択と性別の選択を追加しました。
どちらともTextChoicesを用いて列挙型で指定。

:::note warn
**もし、デフォルトのユーザーモデルのみで良い場合でもCustomUserを作成することをおすすめします。**
一度マイグレーションをするとDBの参照先モデルはデフオルトのユーザーモデルとなります。そこから追加したCustomUserモデルに変更するのはとても大変な作業なので、事前にCustomUserモデルを作成して参照先をそちらに変えておけば今後の変更等がより簡単になります。
:::

## forms
```python:forms.py
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class SignupForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = CustomUser
        fields = ["username", "email"]

```
ここではユーザー登録後、プロフィールページにて情報を入力すためのフォームを作成します。
とりあえず

## admin
```python:admin.py
from django.contrib import admin
from .models import CustomUser

# Register your models here.

admin.site.register(CustomUser)
```
最後に、管理ページでCustomUserをCRUDするためにCustomUserを指定します。
【Django】Djangoを用いたWebサービス（概要と構成）

## はじめに
今回、初めて個人でWebサービスの開発を行ってみました。
数あるWebフレームワークの中からDjangoを選び、手探り状態でなんとか**動く**ようにしてみました。

## サービス概要
サービス名teamup

プロジェクトの立案者（以下オーナー）と、そのプロジェクトへの参加を希望する人（以下ワーカー）を繋げるという設定のWebサービス。
オーナーは、Teamupにてプロジェクトを投稿、ワーカーは参加したいプロジェクトを選び、オーナーに対して参加申請を行い、オーナーが参加希望者の中からワーカーを選びプロジェクトへ参加してもらうサービスです。

## 環境
### 開発環境
・Windows 10 64bit
・python 3.10.6
・Django 4.2
・MySQL
・Bootstrap5

## 構成
### Django
今回は、タイトルに書いてあるとおり、PythonのWebフレームワークである**Django**を使用。
templatesフォルダとstaticフォルダを、アクセス。管理しやすいようにBASE_DIRに設置しました。
#### フォルダ構成
```
root/
  ├ config/     #setting.py等
  ├ teamup/     #teamupのメインアプリ
  ├ templates/     #テンプレート用フォルダ
  │     ├ accounts/     #main/users/用のテンプレートフォルダ
  │     └ common/     #main/teamup/用のテンプレートフォルダ
  ├ static/     static用フォルダ
  │     ├ css/     css用フォルダ
  │     ├ js/     javascript用フォルダ
  │     └ medias/     画像用フォルダ
  │           ├ bio/     プロフィール画像
  │           ├ project/     プロジェクト内の画像
  │           └ other/     その他の画像
  └ manage.py
``` 

### インフラ関係
今回はAWSのEC2へデプロイを行い公開します。
**※現在記事作成中**


## 実装した内容
### ユーザー登録
Djangoにデフォルトで組まれているUserモデルに対して、AbstractUserを用いて情報を追加。
Djangoに内包されているユーザーモデルを元に、CustomUserを実装。
フィールドを追加するのみであり、早く実装したかったのでAbstractUserを用いました。
詳細は以下のリンクを参照してください。

https://qiita.com/kelp-shi/items/259e3f7185712911e759


### プロジェクトの投稿
プロジェクトをオーナーが投稿する機能です。
タイトル、コンテキスト、画像、タグ等を入力して投稿します。
詳細は以下のリンクを参照してください。

https://qiita.com/kelp-shi/items/9ee5bfbe811b3a33c23a


### プロジェクトへの参加申請
**現段階では未実装（2023-05-30）**
投稿されたプロジェクトに対して、ワーカーが参加申請を送ります。
参加申請後は、オーナーに通知が送られ、オーナーはユーザープロフイールからワーカーを選任します。

## さいごに
未経験のことで回り道や失敗を多くしましたが一応**動く**ものができましたが、知識や経験不足による開発速度の遅さを強く感じております。
今後はこのサービスを発展させる他、Django以外のwebフレームワークの挑戦も行ってまいります。
今回開発を進めていく上で学んだ事や経験したことを糧に、今後も様々なモノを作っていきます。
LARAVELで設定を変更しようとするとコード合っているのにエラーが出る

LARAVELで設定を変更しようと思い、[docker-compose.yml ] に1行追加しました。
んで設定反映のため再起動```sail down```を実行しようとするとエラーが...
```
parsing /Users/ユーザー名/example-app/docker-compose.yml: yaml: line 45: found character that cannot start any token
```
45行目はさっきコードを追加した場所
![エラーの場所](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538095/e8492d33-49e8-0619-f2f1-38c0f6a3d635.png)
名前もあっているし、場所もあってる...原因は何だ...ひたすら格闘しました。
そしてふとなんとなく```:set list```を入力しました。すると...
![変な文字](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538095/2d876867-14d4-cbba-8187-06310d22231c.png)
目には見えない文字がある...
これ、インデントを揃えようとして[Tab]を押したのが原因のようです...
見た目を揃えたい場合は[Tab]ではなく半角スペースを連打するのがここでは良いみたいです...
なんじゃそりゃ！
現場からは以上です！
pandas groupby　メモ

group by でsumをしようとするとdepricatedという警告が出るので、別のやり方をstackoverflowで探したら載っていました。そして真似したら動いたのでメモ。

https://stackoverflow.com/questions/46431243/pandas-dataframe-groupby-how-to-get-sum-of-multiple-columns

```python
data = testdata.groupby(['store','cat1','cat1_desc'], group_keys=True)[['sales_amt','price_chg']].apply(lambda x: x.astype(int).sum())
```

- 集計するカテゴリー：店番号、商品カテゴリー
- 上記カテゴリーごとに集計したい値: 売上、売価変更金額

この時にlambda式の中でsumをやれば動きました。
PolarDBと AWS Auroraにおける最大接続数(max_connections)の変更について

# AWS Aurora
- インスタンスのスペックによって、デフォルトの`max_connections`値があります。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Performance.html#AuroraMySQL.Managing.MaxConnections

- デフォルトの`max_connections`値は最大16,000に変更できるが、バッファープールやクエリのキャッシュなど他の箇所も含めて調整されているため、直接max_connectionsを変更することはお勧めできません。
もっと接続が必要な場合は、もっと大きい インスタンスサイズにアップグレードすることをお勧めします。

https://kakkoyakakko2.hatenablog.com/entry/aws/aurora/max-connections


# PolarDB
- デフォルト利用できる、しかも無料のPolarDB Proxyでは最大接続数に制限はありません。
- 一方、バックエンドのインスタンス(compute node)では最大接続数に制限はあります。インスタンスのスペックによって、最大接数、つまり`max_connections`も異なります。

https://www.alibabacloud.com/help/en/polardb/latest/limits

- Auroraと違って、PolarDBの`max_connections`は変更できない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/0d30f675-34cf-cac2-db40-85672a921c9c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/7ee6f492-0bb3-dbba-bda1-d3a7c70055f5.png)

- 接続数足りない場合はどうしますか。
    - PolarDBのProxyに提供されているクラスターendpointでは以下の２つの[モード](https://www.alibabacloud.com/help/en/polardb/latest/configure-polarproxy)が存在している。

    
        1. 読み書きモード(Read and Write mode、Automatic Read-write Splitting)：
           - アプリケーション接続はバックエンドデータベースの各コンピュートノードへの接続を確立するので、アプリケーションが使用できる最大接続数は1つのコンピュートノードへの最大接続数です。
           - Proxyの[connection pool](https://www.alibabacloud.com/help/en/polardb/latest/connection-pools#concept-2047430
    )という機能を使えば、アプリケーションで使用できる最大接続数が増やせます。
    
        2. 読み取り専用モード(Read Only mode)：
           - アプリケーション接続はバックエンドデータベースの1つのコンピュートノードへの接続のみを確立するので、アプリケーションが使用できる最大接続数は読み取り専用クラスタのすべての読み取り専用ノードへの最大接続数の合計となります。 アプリケーションが使用できる接続の最大数は、Proxyの配下にあるすべての読み取り専用ノードへの接続の最大数の合計になります。
           - つまり、読み取り専用ノードを追加すれば、全体の最大接続数も増えることになります。
【jQuery】$(function(){ ~ について

`jQuery`で、js側のコードを実装する上で、`$(function () {`の記述方法が、まず最初に出てきます。`$(function () {`を書く理由としては、`Html`の読み込みが終わった後に、js側の処理を行うためです。
以下に例を挙げると、`$(function () {`を使わずに`<p>`のテキストをコンソールに出力する場合、コンソール出力を行うより先に、`<p>`が生成されている必要があります。
```html
<p class="test">text</p>
<script>// "test"のラベルをコンソール出力処理 </script>
```

しかし、`$(function () {`を使えば、`<p>`のテキストのコンソール出力の処理を`<p>`の生成より先に記述していても、`<p>`の生成後にコンソール出力の処理を行うことができます。
```html
<script>
    $(function () {
        // "test"のラベルをコンソール出力処理
    });
</script>
<p class="test">text</p>
```

つまり、`$(function () {`で jsの処理を書くことで、`Html`のコード読み込み完了の前後を考慮せず、自動的に「`Html`の読み込みが完了」->「`$function(){`の中の処理を実行」の流れが実装されることになります。
Meilisearchのバージョンアップ手順(Docker版)

Docker版Meilisearchをv0.29.1からv1.1.1(prototype-japanese-2)にバージョンアップしたのでその手順です。

(2024.04.10追記)prototype-japanese-10まで同様の手順でバージョンアップできました。


Docker版Meilisearchはこちら。
https://www.meilisearch.com/docs/learn/cookbooks/docker

基本的には下記アップデート手順をDocker向けにしただけです。
https://www.meilisearch.com/docs/learn/update_and_migration/updating

composeを利用してDocker運用していることとします。
```yml
version: "3"
services:
  meilisearch:
    container_name: meilisearch
    image: getmeili/meilisearch:{{ tag }}
    volumes:
      - /meili_data:/meili_data:cached
    environment:
      - MEILI_MASTER_KEY={{ master_key }}
      - MEILI_ENV={{ target }}
    ports:
      - "80:7700"
    restart: always
```

## データをDumpsする

```sh
curl \
  -X POST 'http://<<MeilisearchのFQDN>>/dumps' \
  -H 'Authorization: Bearer <<APIKey>>'
```

タスクIDが返却されるので控えておく。

## タスクを監視してsucceededを待つ

```sh
curl \
  -X GET 'http://<<MeilisearchのFQDN>>/tasks/<<タスクID>>' \
  -H 'Authorization: Bearer <<APIKey>>'
```

## ダンプファイル名を確認する（下記にあるのでファイル名を控えておく）

```
/meili_data/dumps/<<ダンプファイル名>>
```

## Dockerを停止する

```
docker compose stop
```

## データを移動

```sh
sudo mv /meili_data/data.ms /tmp/data.ms
```

このファイルはバックアップなので、万が一アップデートが失敗した場合はバージョンを戻してファイルを元の場所に移動してください。

## docker-compose.ymlのバージョンを meilisearch:prototype-japanese-2 にする

image: getmeili/meilisearch:prototype-japanese-2

（2023.5.30時点のものです）

## バージョンアップ

```sh
docker compose pull
```

## Dumpを取り込む

```
docker run -it --rm -p 7700:7700 -v /meili_data:/meili_data getmeili/meilisearch:prototype-japanese-2 meilisearch --import-dump /meili_data/dumps/<<ダンプファイル名>>
```

※dockerのイメージのバージョンに応じてコマンドを変更してください。
※最後、Ctrl-C等で抜けてください。

## Meilisearchを起動

```sh
docker compose up -d
```
Swiftで解くAtCoder（ABC303）

# 1.はじめに
この記事では、[AtCoder（ABC303）](https://atcoder.jp/contests/abc303)のA~C問題をACしたコードの公開, 解説を行います。
Swiftを使ってコンテストに参加する方の参考になれば幸いです。

# 2.事前準備
標準入力を読み込むためのメソッドです。
コードの先頭に貼り付けて、適宜使用します。
```Swift
import Foundation

// 標準入力から整数を読み込む
func readInt() -> Int{
    return Int(readLine()!)!
}

// 標準入力から整数列を読み込む
func readInts() -> [Int]{
    return readLine()!.split(separator:  " ").map { Int(String($0))! }
}

// 標準入力から文字列を読み込む
func readString() -> String{
    return readLine()!
}

// 標準入力から文字列配列を読み込む
func readStrings() -> [String]{
    return readLine()!.split(separator:  " ").map { String($0) }
}
```

# 3.A - Similar String
問題文や制約は[こちら](https://atcoder.jp/contests/abc303/tasks/abc303_a)からご確認ください。
[AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)によるDifficultyは22になります。
```Swift
let N = readInt()
let S = Array(readString())
let T = Array(readString())

var check = true
for i in 0..<N {
    if S[i] != T[i] {
        if S[i] == "1" && T[i] == "l" || S[i] == "l" && T[i] == "1" {
            
        }else{
            if S[i] == "0" && T[i] == "o" || S[i] == "o" && T[i] == "0" {
                
            }else{
                check = false
            }
        }
    }
}

print(check ? "Yes" : "No")
```

# 4.B - Discord
問題文や制約は[こちら](https://atcoder.jp/contests/abc303/tasks/abc303_b)からご確認ください。
[AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)によるDifficultyは112になります。
```Swift
let line1 = readInts()
let N = line1[0]
let M = line1[1]
var a = [[Int]]()
for _ in 0..<N {
    a.append(readInts())
}

var count = 0
for i in 1..<N+1 {
    for j in i+1..<N+1 {
        var check = false
        for k in 0..<M {
            if abs(a[k].firstIndex(of: i)! - a[k].firstIndex(of: j)!) == 1 {
                check = true
                break
            }
        }
        if !check {
            count += 1
        }
    }
}

print(count)
```

# 5.C - Dash
問題文や制約は[こちら](https://atcoder.jp/contests/abc303/tasks/abc303_c)からご確認ください。
[AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)によるDifficultyは417になります。
```Swift
let line1 = readInts()
let N = line1[0]
let M = line1[1]
var H = line1[2]
let K = line1[3]
let S = Array(readString())
var xy = Set<[Int]>()
for _ in 0..<M {
  xy.insert(readInts())
}

var check = true
var tx = 0
var ty = 0
for i in 0..<N {
  H -= 1
  if H < 0 {
    check = false
    break
  }
  switch S[i] {
    case "R":
      tx += 1
    case "L":
      tx -= 1
    case "U":
      ty += 1
    case "D":
      ty -= 1
    default:
      break
  }
  if H < K {
    if xy.contains([tx, ty]) {
      H = K
      xy.remove([tx, ty])
    }
  }
}

print(check ? "Yes" : "No")
```

# 6.最後に
間違いや改善点等あれば、ご指摘いただけると幸いです。
何卒よろしくお願いいたします。
Vue.js＋Laravel　LaravelのStorage内の画像を表示する

# この記事の目的  
ずっとNuxt.jsを利用していたので、Vue.js復習として。
環境変数を利用してのimg表示に手こずったので備忘録として記述します。

# 環境  
Vue.js　3.3.4
Laravel 10

# 前提  
vue.js,Laravelのプロジェクト作成ができていること。

# 手順  
・Laravel側の設定  
"storage/app/public"にある画像をVue.js表示するためにはシンボリックリンクを貼る必要があります。この辺りは検索するとたくさん出てくるので割愛します。

```
php artisan storage:link
```

これだけは忘れずに・・・！  
  
<br>
<br>
・Vue.js側の設定  
今回こっちが本題でした。Vue.jsプロジェクト直下に.envファイルを作成します。Vue.jsではVUE_APPを頭につける必要があるそうです。axiosを利用しているので同じbaseURLを利用しました。



```
// .env

VUE_APP_BASE_URL="http://127.0.0.1:8000/"
```
開発環境localであれば上記の通りです。
<br>
<br>

```
<template>
  <div>
     <img :src="imgPath" alt="画像説明" />
  </div>
</template>

<script>
export default {
  name: "HomeView",
  data() {
    return {
     img: 'img.png',
  },
  computed: {
    imgPath() {
      return       
   `${process.env.VUE_APP_BASE_URL}storage/${this.img}`;
  },
  }
```



あとはこれだけ！
src=""　でなく　:src=""　なので注意！
実際はストレージを借りたりすると思うので、baseURLでなく、例えば、


```
// .env

VUE_APP_STORAGE_URL="ストレージサービスのURL"
```

<br>
<br>

などにして置き換えたらいいかと思います。
良い復習になりました。
crontabコマンドの使い方

# crontabコマンドのオプション
そろそろ覚えなさいよ、と自分に言い聞かせながら作成しています。

## crontabの使い方
`crontab -l` 　crontabファイルの中身を確認
`crontab -e`　 crontabファイルを編集
`crontab -r`　 crontabファイルを削除

## 最後に
何回使っても1カ月使わなかったら忘れるのでメモです。
次こそ検索せずに使えますように。
GitHub Pagesで作ったMarkdownドキュメントにTable of Contents (TOC) を付ける方法

GitHubに作った自作プロジェクトのドキュメントをMarkdownで書いたら長くなったのでTable of Contents(TOC)すなわち目次を付けたくなった。2023年5月末時点のGitHubで何ができるかを調べた。いとも簡単にできた。

## READMEにTOCを付けたい

プロジェクトのルート・ディレクトリ直下に置いた`README.md`ファイルに２つ以上のheaderつまり先頭が`#`で始まる行があれば、それだけでOK。何もしなくても、GitHubの画面上でTOCが表示されました。

サンプルを示そう。たとえば

- https://github.com/kazurayam/adoc2md/

をブラウザで開くとファイル名の左隣にボタンが表示されている。

![スクリーンショット 2023-05-30 14.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/5e4e327c-42ee-c147-8845-47f2fe102ce9.png)

そのボタンをクリックするとTOCが表示された。

![スクリーンショット 2023-05-30 13.58.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/6a2ae5df-5403-aee4-fe24-c02760740785.png)

このTOCはGitHubのアプリが自動的に生成したもの。`README.md`ファイルの中にはこのTOCに相当する行はない。GitHubのサーバーアプリが`README.md`ファイルを読み込み`#`で始まるheader行を選択して、それに基づきリンクメニューとしてのTOCを動的に生成してくれる。

## GitHub Pagesを使って作ったドキュメントにTOCを付けたい

プロジェクトのルートディレクトリの下に `docs` ディレクトリを作り、その中に　 `index.md` ファイルを作った。最初作った `index.md` ファイルは次のようなもの:

```
# Lorem ipsum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

## Ut enim ad minim veriam

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

...
```

みての通り、行頭が`#`で始まるheader行と平文があるだけで、TOCを生成するための呪文は書いていない。このままでTOCは生成できない。そこで"GitHub Pages Markdown TOC"とキーワードを指定してGoogle検索した。そうしたら次のページに遭遇した。

- http://www.seanbuscay.com/blog/jekyll-toc-markdown/

このページの教えに従って `docs/index.md` ファイルを次のように修正した。ファイルの先頭に呪文を2行だけ追記した。

```
- Table of Content
{:toc}

# Lorem ipsum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

## Ut enim ad minim veriam

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

...
```

修正したMarkdownファイルをaddしてcommitしてpushした。

- https://kazurayam.github.io/adoc2md/

![スクリーンショット 2023-05-30 14.38.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52995/80f10c0a-308a-cd55-6843-b3c54ce1a463.png)

ご覧のとおり、GitHub Pagesの応答画面上でTOCが付加されて表示されている。

TOCの各行がlinkになっている。TOCのlinkをマウスでクリックすればドキュメントの中のheaderへジャンプする。link切れがないかどうか調べようと全部試した。headerの文中に&、-、_などの特殊記号を含む場合もリンク切れしていない。headerの文が英数字ではなく日本語の漢字ひらがなカタカナ文字を含む場合もリンク切れしていない。完璧だ。

## はてな？　いつから？

2022年4月にわたしはGitHub Pagesに作ったMarkdownドキュメントにTOCを付けたいと思って実現方法を調べた。その時点ではGitHubがTOCを組み込みで提供してくれていないと了解した。そこで外付けのツールを使ってHTML要素`<a href="#target">`から成るTOCを生成し`.md`ファイルに挿入する方法を試した。この方法で書き換えた.mdをブラウザで開くと、GitHubが.mdをHTMLに変換したものをブラウザ上で見ることになる。ところが残念ながらTOCから本文へのリンクが切れてしまっているケースがあった。見出しの中に:や&などの特殊文字が含まれているとダメだった。今回、2023年5月、GitHubを調べ直した。そしたらなんと、TOCが組み込みでサポートされていることに気づいた次第。

いつからTOCがGitHubに組み込まれたんでしょう？　もともとOKだったのか？不覚にも小生、今まで気づきませんでした。
ヘッドレスCMSで活用される主要技術

ヘッドレスCMS（Content Management System）はデジタルコンテンツ管理の新しいアプローチで、前端（フロントエンド）と後端（バックエンド）が分離されています。この記事では、ヘッドレスCMSで主に使用される技術について解説します。

## 1. RESTful APIとGraphQL
ヘッドレスCMSの中核をなすのはAPI（Application Programming Interface）です。APIを通じて、CMSのバックエンドからデータを取得し、任意のフロントエンドでそれを表示することが可能です。主に使用されるAPIの形式は、RESTful APIとGraphQLです。

RESTful APIはWeb開発で広く利用されているAPIの形式で、特定のURL（エンドポイント）へのHTTPリクエスト（GET、POST、PUT、DELETEなど）によってデータを操作します。

一方、GraphQLはFacebookによって開発された新しいAPIの形式で、クライアントが必要なデータの構造を指定できるという特徴があります。これにより、不要なデータの転送を避けることができ、パフォーマンスの向上に寄与します。

## 2. JavaScriptフレームワークとライブラリ
ヘッドレスCMSは、フロントエンドの開発における技術選択の自由度が非常に高いです。そのため、現在最も人気のあるJavaScriptのフレームワークとライブラリ、例えばReact、Vue.js、Angularなどが頻繁に用いられます。

これらのフレームワークやライブラリを用いることで、コンポーネントベースの開発が可能となり、コードの再利用性を高めつつ、複雑なユーザーインターフェースを効率よく構築することができます。

## 3. Jamstack
Jamstack（JavaScript、APIs、Markupの略）は、モダンなウェブ開発のアーキテクチャで、ヘッドレスCMSと非常に相性が良いです。Jamstackは静的サイト生成（SSG）とクライアントサイドのJavaScriptを中心に据え、APIを用いてデータを操作します。

静的サイト生成ツール（例えばNext.js、Gatsby、Nuxt.jsなど）と組み合わせることで、高速でセキュアなウェブサイトを構築することが可能となります。

## 4. データ形式：JSONとMarkdown
ヘッドレスCMSでは、コンテンツは主にJSON（JavaScript Object Notation）という形式で取り扱われます。JSONはデータの交換フォーマットとして広く利用されており、その構造が人間にも機械にも理解しやすいという特性から好まれます。APIを通じてヘッドレスCMSからデータを取得する際、そのレスポンスは通常JSON形式で提供されます。

また、コンテンツ作成においては、Markdownという軽量マークアップ言語もよく用いられます。Markdownはシンプルな記法で文章の書式を設定することができ、HTMLに変換するのが容易なため、ブログ記事やドキュメンテーションの作成に適しています。ヘッドレスCMSでは、記事の本文などをMarkdownで書いて保存し、必要に応じてHTMLに変換してフロントエンドに表示するという使い方が一般的です。

## 5. ホスティングとCDN
ヘッドレスCMSのコンテンツは、一般的にクラウドベースのホスティング環境に保存されます。AWS、Google Cloud、Azureといった大手クラウドプロバイダはもちろん、VercelやNetlifyのような静的サイト向けのホスティングサービスも多く利用されています。

また、ヘッドレスCMSはCDN（Content Delivery Network）と組み合わせることが一般的です。CDNは全世界に分散されたサーバーからユーザーに最も近い位置でコンテンツを配信することで、ウェブサイトの読み込み速度を大幅に向上させることができます。

## まとめ
ヘッドレスCMSは、RESTful APIやGraphQL、各種JavaScriptフレームワーク、Jamstackといったモダンなウェブ開発技術を活用して、効率的かつ柔軟なコンテンツ管理と配信を実現します。その背後には、JSONやMarkdownといったデータ形式、さらにはクラウドホスティングとCDNといったインフラが支えています。これらの技術の組み合わせによって、ヘッドレスCMSはウェブ開発の新しい可能性を切り開いています。
PowerAutomate：会議の出席者追加時に出席者全員に通知したくない

久しぶりにPowerAutomateハウツーです。
今回はわりと特殊な事例です。

:::note info
2023/07/11更新
"Solution 2. Microsoft Graphを使う" を加筆。元々ご紹介していた方法では出席者の「追加」は処理できても「削除」はできませんでした。"Solution 2"ではこの問題が解消されています。
:::

# Background

* 組織内で運用している「とある制度」のため、PowerAutomateワークフローを利用して、組織の特定メンバーあてにTeams会議の会議出席依頼を送付している。
* Teams会議の会議出席依頼を初回送付したあと、会議の参加者が増減することがあり、その場合Teams会議の出席者の情報（Outlookでいえば `to` ）を変更する必要がある。
* 参加者が多数におよび、かつ「参加者の増減」の後追いで幾度も発生する想定であるが、参加者（出席者）への通知は最小限としたい。

PowerAutomateで Teams会議を作成したあと会議情報を更新する場合、通常は次のような流れとなる：

1. 「Teams会議の作成」アクションでTeams会議を作成（Outlookで自動的に会議出席依頼のメールが送信される）
1. アクションの出力（Outputs）として得られるIDをどこかに記録しておく
1. 後日出席者の追加が必要になったら、「イベントの更新」アクションで記録しておいたIDをキーにしてTeams会議（イベント）を更新（ここでもメールが自動送信される）

あえて1つのフローでやるとしたらこう：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/f800e217-012a-e420-2234-ac37e7cc5546.png)

:::note warn
実際には「Teams会議の作成」と「イベントの更新」は別々のフローで、別々のタイミングで実行されることになるはずです。
:::

# Problem

先ほどの方法では 「イベントの更新」アクションが実行され、出席者が増減するたびに、出席者全員に Teams会議内容の更新を知らせるメールが送信されることになってしまう。
これでは参加者（出席者）への通知は最小限としたいという要件が実現できない。

:::note info
Outlookで（人手で）同様のことをする場合、追加ないし削除された出席者にのみ通知を送るか、それとも全員に送るかを選択できます。
PowerAutomateでする場合、残念ながら少なくとも現時点では、選択肢はありません。
:::

# Solution 1. メール転送を使う

:::note warn
この方法はシンプルで比較的ローコードに要件を実現できるものの、出席者の「追加」はできても「削除」ができない問題を抱えています。これを回避するには "Solution 2. Microsoft Graphを使う" を採用してください。
:::

出席者の「追加」について言えば、次のようにフローを変更することで、出席者全員への通知を回避できる：

1. 「Teams会議の作成」アクションでTeams会議を作成、このとき会議のタイトルに何かしらの識別子を含めるようにする（Outlookで自動的に会議出席依頼のメールが送信される）
1. 識別子をどこかに記録しておく
1. 後日出席者の追加が必要になったら、「メールを取得する」アクションで #1で自動送信されたメッセージを取得
1. アクションの出力（Outputs）として得られるメールのIDを使い「メールの転送」アクションを実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/ec769243-2b77-adc6-a484-326344f32360.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/bbb062a4-6249-cb24-3de8-066655b72da4.png)

これで、他の出席者への通知なしにTeams会議を更新することができる。オペレーションとしてはメールの転送であるが、それに紐づくTeams会議の情報（出席者）も更新されている。

# Solution 2. Microsoft Graphを使う

Microsoft Graph APIを使用して、出席者の追加や削除を行う。

先程の方法（メール転送を使う）では、出席者の「追加」はサイレントに行えるが「削除」はできない。
削除についてサイレントに行える方法はないか探したところ、こちらの記事を発見した：
  [Add an attendee to an invite without emailing exis... - Power Platform Community](https://powerusers.microsoft.com/t5/Building-Flows/Add-an-attendee-to-an-invite-without-emailing-existing-attendees/td-p/942317)

ここで紹介されている方法は、 Office 365 Outlookコネクターの「HTTP要求を送信します」アクションによりMicrosoft Graph APIをコールするもの：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/515b84eb-2a7d-6380-89f9-947248b5318a.png)

各パラメーターは：

| Left align | Right align | Center align |
|:-----------|:------------|:------------|
| URL       | https://graph.microsoft.com/v1.0/me/calendars/ `CalendarID` /events/ `EventID`        | `EventID`は「Teams会議の作成」アクションの出力から得られる。 `CalendarID`は「カレンダーの取得」アクションの出力から得られる。  |
| メソッド     | PATCH      | 固定値       |
| 本文       | `{"attendees": ... }}`        | `attendees`プロパティのオブジェクトの構造（スキーマ）は、「イベントの取得」や「Teams会議の作成」アクションの出力内容を参照するとわかる。 |
| コンテンツの種類 | application/json |  |

本文で指定した `{"attendees": ... }}`の内容に基づいて出席者一覧が更新されるが、このとき差分の出席者（追加された方と削除された方）にのみメール通知が送信れる。
追加だけでなく削除のシナリオでも用いられる。
Windows ServerにPython（pandas）環境を構築する

# 背景
Windows ServerでPythonのバッチファイルを動かす要件があり、環境構築しました。
サーバーはWindows Server 2022です。

# 手順
## Pythonインストール
1. 以下からインストーラーをダウンロードする。
https://pythonlinks.python.jp/ja/index.html

2. ダウンロードしたインストーラーを右クリックし、「管理者として実行」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/0a0d7fee-91e0-d6a3-e578-164b70af662c.png)

3. 「Add python.exe to PATH」をチェックして、「Install Now」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/334a4496-1682-1206-090e-e4f9bacd015c.png)

4. インストール完了後、コマンドプロンプトを起動し、バージョン確認できればPythonのインストール完了となる。
    ```
    > python -V
    …
    Python 3.X.X
    ```

## pandasインストール
1. 続けてコマンドプロンプトでpandasをインストールする。
    ```
    > python -m pip install pandas
    ```

2. pythonを起動し、以下のコマンドでバージョンが表示されればpandasのインストールも完了となる。
    ```
    > python
    …
    >>> import pandas as pd
    >>> print(pd.__version__)
    2.0.2
  
    exit()
    ```

# 参考URL
https://www.python.jp/install/windows/install.html
Alfredを使ってGoogle Chromeのパスワードマネージャを開く方法 - ワンクリックでセキュリティを管理

# はじめに
この記事では、Alfredのworkflowを使ってGoogle Chromeのパスワードマネージャをすぐに開く方法を紹介します。workflowを利用するので、powerpackを購入していることを前提としています。workflowの作成方法がわからなくても大丈夫です。

# 背景
chromeのパスワードマネージャを開かないといけないことが度々あるのですが、毎回開くのも面倒なので簡単にしたと思いました。そこで、Alfredを使って簡単にパスワードマネージャを開けるようにしました。

# やりたいこと
Alfredからキーワード（pwとか）を入力するだけでchromeのパスワードマネージャを開けるようにしたい。

# 使うもの
- Alfred（有料版）
- AppleScript

# 手順
## 1.　新規Workflowの立ち上げ
初めに、Alfredの［環境設定］→［Workflows］を選択します。そして、サイドバーの下にある「＋」ボタンからBlank Workflowを選択します。すると下のような画面が出るので、workflowの名前を設定して「Create」ボタンを押してください。
![スクリーンショット 2023-05-30 13.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461593/1871d169-6932-db2d-fd05-24a3f38d68b1.png)


## 2. キーワードを設定する
次にトリガーを設定します。まず、右のサイドバーから[Inputs]→[keyword]を選択します。するとworkflow objectが生成されます。生成されたworkflow objectをクリックするとkeywordとTitleを設定できるので、設定できたら「Save」をクリックしてください。
![スクリーンショット 2023-05-30 14.28.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461593/9972b7b9-eab7-8a74-4560-30f3f8075c06.png)
これでキーワドの設定が完了しました。

## 3.　scriptを設定する
先ほど作成したworkflow objectから繋いで新しいworkflow objectを作成します。[Actions]→[Run Script]を選択するとscriptの記述画面が表示されるので、左上のlanguageに「/usr/bin/osascript(AppleScript)」を選択してください。そしてKeywordの右にあるプルダウンメニューから「No Argument」を選択します。選択できたら以下のscriptを記述します。
![スクリーンショット 2023-05-30 14.09.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461593/31ce2321-7134-d3e9-c631-4008491fa15b.png)

    tell application "Google Chrome"
        activate
        open location "chrome://settings/passwords"
    end tell

記述できたらSaveしてください。

## 4.　正しく動くかチェック
以上の設定が終われば、設定したホットキーを押すことでChromeのパスワードマネージャを開くことができます。これでパスワードマネージャを簡単に開けるようになりました。
![スクリーンショット 2023-05-30 14.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461593/52a92b4e-9d3a-c483-cfcf-fbaa9b12047d.png)

# 5.最後に
これでchromeのパスワードマネージャを瞬時に開けるようになりました！
ページネーション機能をkaminari→pagyに変更したときに起きたエラー

エラーの原因は単純ですが、pagyを用いる際にエラーが起きて手間取ったので、備忘録がてら書いていきます。

# やりたいこと
kaminariでページネーション機能をつけていたのを、仕様はそのままでpagyに変更したい。

# 起きたエラーと解決法
```users_controller.rb
def timeline
  @feed_items = current_user.feed
  @pagy, @feed_items = pagy(@feed_items) if @feed_items.present?
  @user = User.find_by(params[:user_id])
end
```
↓
エラー
```
NoMethodError in UsersController#timeline
undefined method `offset' for [#<ListMovie id・・・
```
エラーメッセージによれば、```undefined method 'offset'```は、```@feed_items```が```offset```メソッドを持っていないことを示しています。```offset```はActiveRecordのメソッドで、通常はデータベースからのレコードセットに対して使用されます。しかし、```@feed_items```は配列なのでエラーになっています。

これを解決するには```pagy_array```を使用して```@feed_items```をページネートする必要があるので、以下のように修正します。
```users_controller.rb
def timeline
  @feed_items = current_user.feed.to_a
  @pagy, @feed_items = pagy_array(@feed_items) if @feed_items.present?
  @user = User.find_by(params[:user_id])
end
```
上記では```to_a```メソッドを使用して```@feed_items```を配列に変換し、その後```pagy_array```を使用して配列をページネートしています。
↓
またもやエラー
```
NoMethodError in UsersController#timeline
undefined method `pagy_array' for
```
```pagy_array```が未定義とのこと。
今回の原因はPagyのArrayサポートが有効になっていないためでした。```Pagy::Backend```モジュールは```pagy_array```メソッドを提供しますが、そのためには```Pagy::Array```モジュールが必要です。

下記のコードを追記して、pagy.rbでPagyのArrayサポートを有効にします。

```config/initializers/pagy.rb
require 'pagy/extras/array'
```

この変更を加えた後、サーバーを再起動して変更を有効にする必要があります。

これにより、Pagy gemは配列に対するページネーションをサポートするようになる。 
→ pagy_arrayというメソッドが利用可能になります！
Xpath記述、健忘録用


要素の最後
/div[@id='aaa']/a[position()=last()]


テーブルの項目名で指定
//table[@class='aaa']//tr/td[preceding-sibling::th='お肉']

dl/ddタグの場合
//div[@class='aaa']//dl/dd[preceding-sibling::dt='お魚']


テキストで取得
//a/text()

要素を取得
//input[@name='aaaa']/@value
//input[@class='aaaa']/@href


ディスクリプションを取得
//meta[@name='description']/@content

特定の文字を含む
//a[contains(@class, 'aaaa')]/@href


and o notも使えるらしい
//a[contains(@href,"S_20") and contains(@href,"pdf")]


※後日整える予定