OmniAICreator/Qiita-1.07M huggingface dataset:
Beautiful Soupを使ってWebスクレイピング Part2

前回の記事では、Beautiful Soupを使った基本的なウェブスクレイピングの方法を紹介しました。
今回は、実用的で高度なテクニックについて解説します。


#### 1. 複数ページにまたがるデータの取得

多くのウェブサイトでは、データが複数のページにまたがっています。
これをスクレイピングするために、ページネーションを処理する方法を紹介します。

```python
import requests
from bs4 import BeautifulSoup

# 基本URL
base_url = 'https://example.com/page/'

# ページ数の設定
num_pages = 5

# 各ページのデータを取得
for page in range(1, num_pages + 1):
    url = f"{base_url}{page}"
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')

    # ページごとのデータを解析
    items = soup.find_all('div', class_='item')
    for item in items:
        title = item.find('h2').string
        print(f"ページ {page} のアイテム: {title}")
```

#### 2. JavaScriptで生成されたコンテンツの取得

一部のウェブサイトでは、コンテンツがJavaScriptによって動的に生成されます。
これを取得するために、Seleniumなどのライブラリを使用します。

```python
from selenium import webdriver
from bs4 import BeautifulSoup

# WebDriverの設定
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')

# URLの指定
url = 'https://example.com'

# ページを開く
driver.get(url)

# ページの読み込みを待つ（必要に応じて調整）
driver.implicitly_wait(10)

# ページソースの取得
html = driver.page_source

# BeautifulSoupで解析
soup = BeautifulSoup(html, 'html.parser')

# 必要なデータを抽出
items = soup.find_all('div', class_='item')
for item in items:
    title = item.find('h2').string
    print(f"アイテム: {title}")

# ドライバーを閉じる
driver.quit()
```

#### 3. データのクリーニングと保存

スクレイピングしたデータをそのまま使用するのではなく、データを整形し、CSVやExcelに保存する方法を紹介します。

```python
import csv
import pandas as pd

# サンプルデータ
data = [
    {'title': 'Item 1', 'price': '$10'},
    {'title': 'Item 2', 'price': '$20'},
    {'title': 'Item 3', 'price': '$30'}
]

# CSVに保存
with open('output.csv', 'w', newline='') as csvfile:
    fieldnames = ['title', 'price']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()
    for row in data:
        writer.writerow(row)

# Excelに保存
df = pd.DataFrame(data)
df.to_excel('output.xlsx', index=False)
```

#### 4. 認証が必要なウェブサイトへのアクセス

認証が必要なウェブサイトからデータを取得する方法を紹介します。
ここでは、Requestsライブラリを使った例を示します。

```python
# 認証情報の設定
auth = ('username', 'password')

# URLの指定
url = 'https://example.com/login'

# 認証付きのGETリクエスト
response = requests.get(url, auth=auth)

# ステータスコードの確認
if response.status_code == 200:
    print("認証に成功しました")
    # BeautifulSoupで解析
    soup = BeautifulSoup(response.content, 'html.parser')
    print(soup.prettify())
else:
    print("認証に失敗しました")
```

#### 5. プロキシを使ったスクレイピング

特定のウェブサイトでは、アクセス制限やIP制限がかかっていることがあります。
この場合、プロキシを使ってリクエストを送信します。

```python
# プロキシの設定
proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.10:1080',
}

# URLの指定
url = 'https://example.com'

# プロキシ付きのGETリクエスト
response = requests.get(url, proxies=proxies)

# ステータスコードの確認
print(f"ステータスコード: {response.status_code}")
print(f"レスポンス内容: {response.text}")
```

以上
---

前回

https://qiita.com/benjamin1gou/items/b063b957ee6244262735
[docker][MySQL]古いバージョンを使おうとするとCompose upで死ぬ件

# 動け!! 動けよ!! 動いてよ!!!!
プログラマーなら、自分のコードが動かないときに大体思うよね。
「今やらなきゃ、みんな死んじゃう（デスマな）んだ!!そんなのもう嫌なんだよ。だから __動いてよ!!__」

# DockerでMySQLの5.6を動かそうとして↑な状況になった件について
※2024/06/17時点で起こったこと

とりあえず最初に作ったDockerfileを見ておくれ

```dockerfile:dockerfile
FROM mysql:5.6.36
RUN apt-get update && \
    apt-get install -y locales vim && \
    rm -rf /var/lib/apt/lists/* && \
    echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen ja_JP.UTF-8
ENV LANG ja_JP.utf8
RUN { \
    echo '[mysqld]'; \
    echo 'character-set-server=utf8'; \
    echo 'collation-server=utf8_general_ci'; \
    echo '[client]'; \
    echo 'default-character-set=utf8'; \
} > /etc/mysql/conf.d/charset.cnf
```

これでcompose upすると、apt-getで404エラーが発生しました。

Linuxをイジってる人ならすぐに「あぁdebianのパッケージの場所が変わったんだな」ってお察しでしょうが、
基本的にWindowsしか使ってこなかった勢からすると「404ってサイトが見つからないってことだよね、公式とか他の人のサイト通りに書いてるのに、なんで動かないだよ。。。動いてよ!!」ってアレになるかと思うので備忘録的な意味で、追加設定を入れた版で残しておきますね。
```dockerfile:dockerfile
FROM mysql:5.6.36
RUN echo "deb http://archive.debian.org/debian/ stretch main" > /etc/apt/sources.list && \
    echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list && \
    apt-get update && \
    apt-get install -y locales vim && \
    rm -rf /var/lib/apt/lists/* && \
    echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen ja_JP.UTF-8
ENV LANG ja_JP.utf8

RUN { \
    echo '[mysqld]'; \
    echo 'character-set-server=utf8'; \
    echo 'collation-server=utf8_general_ci'; \
    echo '[client]'; \
    echo 'default-character-set=utf8'; \
} > /etc/mysql/conf.d/charset.cnf
```
【備忘録】GASで最初のWebアプリをつくる

# はじめに

GASでWebアプリを作成する際の備忘録

# 新規作成

右上のメニューより、Google Apps Scriptを選択し、新規作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/f96e4311-5eb2-e3c8-a8e5-114461b3ef58.png)

最小限のプログラムを作成し、保存する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/d8180502-6e88-f185-34dd-90ba03115e65.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/3d3fb325-0a43-bc25-82d7-620e534621e2.png)

# デプロイ

Webアプリとして「新しいデプロイ」を実行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/586b875c-5f50-18a2-275a-70cd70c323fb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/102a2c74-0a0a-e635-2bfa-cc23e9578b4b.png)

リンク先に移動するとindex.htmlの内容が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/f0e536a3-2a63-1061-d7dc-aa2d92ed49cd.png)


# 更に機能を追加する

https://qiita.com/firesign2023/items/5d3c76d5fef4e4e233d3

https://qiita.com/firesign2023/items/a2bccf87ddf973587aef

https://qiita.com/firesign2023/items/6d72f0814b6bb9a2fe02

https://qiita.com/firesign2023/items/c89eb2af8ea66ed5efea

https://qiita.com/firesign2023/items/148d6ac6e82f0e7f6b32
PC 開いたら Commandprompt から曲かけたくない？

# 初めに
**ド偏見** かもしれませんが、やっぱり **コマンドでパソコン操るってカッコイイ** （く見えることがあるかもしれない）

ということで、作業に集中するために音楽を聴きながら作業する際に、いちいちミュージックファイルを開いたりといったことがなんとなくカッコワルク感じてしまったこの頃なので、**Commandprompt から実行しようよ！** というお話です。

レデイ後

# How to command
1. windows key を click
1. cmd と入力
1. cd music と入力（お好きなミュージックフォルダへお飛びください）
1. start music.mp3 と入力（お好きなミュージックファイルを入力してください）
1. exit と入力（command prompt に用がなくなれば）

上記をまとめると、
```
$ cd [path/to/music_dir] && start [music_file] && exit
````
となります！

Very easy !!!!

# 最後に
私は windows user なので、mac については木っ端みじんに存じ上げませんが、今回は **PC 開いたら Commandprompt から曲かけたくない？** ということで、紹介させていただきました。

今、思いましたが、**なんかコマンド叩いていてすごく見えるけど結局は音楽を再生しただけなの？（w** とか言われそうですね。

言われたら悲しいですね。本来の目的と違って **ダサい** です。

乱用には注意しましょう

最後まで読んでくれてありがとう！！
データ検証で大活躍!! VS CodeのCSV拡張機能

# 背景
最近、業務でシステムのリファクタリングを行う中でデータをCSV出力し、検証を行う中でどうすればより効率的に検証を行うことができるだろうかと考えていました。
MacOSXの標準で起動する`Numbers`や`スプレッドシート`にてデータを加工する中で、VSCodeの拡張機能に出会い、もうあの頃には戻れない体になってしまいました。
この記事ではそんな優秀なVS CodeのCSV拡張機能を紹介したいと思います。

# 直感的に操作できるEdit csv
## 主な用途
- カラムの入れ替え
- カラム削除
- ソート
## 使い方
拡張機能からEdit csvを有効にするとCSVファイルを開いた時に、VS Coceの右上に`Edit csv`とういボタンが表示されます。それをクリックすることでEdit csvのCSVエディタが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1045272/4f2a98da-d39f-a59b-4ad2-0756a944c16c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1045272/799ea9b4-a069-70ab-b7a4-e6a655d5e41e.png)
Edit csvは直感的に操作できます。
スプレッドシートのように、カラムの入れ替え、削除、ソートを行うことができます。
編集した後は好みに応じて`Apply changes to file and sav`、または、`Apply changes to file`をクリックすることで元のcsvファイルに編集内容が反映されます。

# データを抽出できるRainbow csv
## 主な用途
- データ抽出
## 使い型
CSVファイルを開き、コマンドパレットで`RBQL`と入力・クリックして、RBGLの画面を表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1045272/db910d02-0aab-d765-f31d-9cade618dae1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1045272/77fb09e0-1cde-4c31-27a7-2df3744766d6.png)
後はSQLライクにデータを抽出することができます。
Encodingは`shift-jis`に対応していないので、その場合は検証前に`UTF-8`に変更して作業しましょう。

# 参考
今回のCSVデータは以下のリンクから取得しました。
https://www.e-stat.go.jp/stat-search?page=1
Ruby エイリアスメソッド

# エイリアスメソッドについて
Rubyには全く同じ機能でありながら異なる名前のメソッドが複数存在します。これらのメソッドのことをエイリアスメソッドと呼びます。
可読性向上やプログラマーの好みによって使い分けられています。（メソッドによっては派閥がわかれているとか…）

以下にエイリアスメソッドの一例を記載します。

# エイリアスメソッド一覧

## Array クラス

- `map` と `collect`
- `size` と `length`
- `slice` と `[]`
- `append` と `push`
- `prepend` と `unshift`

## Hash クラス

- `store` と `[]=`
- `size` と `length`
- `key` と `index`
- `to_s` と `inspect`

## String クラス

- `size` と `length`
- `slice` と `[]`
- `to_s` と `to_str`

## Enumerable モジュール

- `collect` と `map`
- `find_all` と `select`
- `reduce` と `inject`
- `member?` と `include?`
- `detect` と `find`

## File クラス

- `exists?` と `exist?`

## Math モジュール

- `atan2` と `atan`

## IO クラス

- `gets` と `readline`
- `print` と `write`

## Kernel モジュール

- `fail` と `raise`
- `sprintf` と `format`
- `Array` と `to_a`
- 
## 使い分けの例

### Array#map と Array#collect

`Array` クラスには、`map`と`collect`というエイリアスメソッドがあります。どちらも、配列の各要素に対してブロックを評価し、新しい配列を返すメソッドです。
```ruby
array = [1, 2, 3, 4]
mapped_array = array.map { |num| num * 2 }
# => [2, 4, 6, 8]

collected_array = array.collect { |num| num * 2 }
# => [2, 4, 6, 8]
```

`map`はより短く、広く一般的に使用されています。一方、`collect`は自然言語に近い表現で、読みやすさを重視するプログラマに好まれることがあります。

### Hash#key と Hash#index

`Hash` クラスには、`key`と`index`というエイリアスメソッドがあります。どちらも、指定した値に対応するキーを返します。
```ruby
hash = {a: 1, b: 2, c: 3}
key_for_value = hash.key(2)
# => :b

index_for_value = hash.index(2)
# => :b
```

`key`は直感的であり、`index`はより技術的な背景を持つ表現です。

# 歴史的背景

Rubyは日本で生まれたプログラミング言語であり、設計者のまつもとゆきひろ氏（Matz）は、プログラマが自然で直感的なコードを書けるような言語を目指しました。その中で、異なるバックグラウンドやプログラミングスタイルを持つプログラマがより快適かつ直感的にコーディングできるようにするため、エイリアスメソッドが多く存在します。


# エイリアスメソッドのメリット

1. **可読性の向上**: プログラムの意図が明確になる。
2. **柔軟性の提供**: 異なる表現を使うことで、プログラマが慣れ親しんだスタイルでコーディングできる。
3. **互換性の確保**: 古いコードベースとの互換性を保ちながら、新しい表現を導入できる。

# エイリアスメソッドのデメリット

エイリアスメソッドは便利な反面、異なるメソッドを混在させるとコードの可読性が損なわれ、思わぬエラーやバグが発生する可能性があります。
それを避けるためにも、プロジェクトやチーム内で使用するメソッド名は統一することが重要です。

# まとめ

エイリアスメソッドは、Rubyの柔軟性と使いやすさを象徴する機能の一つです。プログラマは、自分の好みやチームのコーディングスタイルに合わせてメソッドを選ぶことができます。

---
Chrome Manifest V2を 2025年6月まで使用する方法 (Mac)


## 結論

ターミナルから下記コマンドを実行、その後にChromeを再起動

```
defaults write com.google.Chrome ExtensionManifestV2Availability -integer 2
```

### 確認

Chrome アドレスバーに chrome://policy を入力
ExtensionManifestV2Availability に 2 が設定されていれば成功です

![policy](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584829/79413e08-503a-56ea-c716-96a4a918579e.png)


## 説明

- Chrome(Chromium) は2024/05/30 より Manifest V2 -> Manifest V3 への段階的な移行を開始しました
- 数ヶ月後には Manifest V3 に対応していない拡張機能は使用できなくなります
- その期限を 2025/06 まで延長する設定が本記事の内容です

## 参考URL

https://gigazine.net/news/20240616-chrome-block-manifest-v3/

https://blog.chromium.org/2024/05/manifest-v2-phase-out-begins.html
【HTML】ボタン要素にdisabled属性をつけるのをやめませんか？

## はじめに

みなさんは、フォームなので必須項目が入力されてない時、Submitボタンに `disabled` をつけて押せないようにしていませんか？

この記事では、ボタンに`disabled`属性をつけない方がいい理由と`disabled`をつけない方法を紹介します。

## disabled属性をつけない方がいい理由

`disabled` 属性をつけると、ユーザーがボタンを操作することを防ぎます。
そのため、キーボード（Tabキー等）で操作している時フォーカスが当たらないため、ボタンの存在が認知できません。

disableがない時 | disableがある時
:-:|:-:
![3つのボタンにフォーカスが当たっているgif動画](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/b80e010c-a055-02c6-0e98-59d6c37c6896.gif)|![3つのボタンの中に1つdisabledのボタンがあり、2つのボタンにフォーカスが当たっているgif動画](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/4316c29e-657b-6b20-63d9-fe3219a195f8.gif)

ボタンの存在が認知できないため、支援技術（スクリーンリーダ等）で操作しているユーザーにとって、「送信ボタンどこだろう？」と思ってしまったり、「なんで送信ボタンが出てこないんだろう？」と思ってしまい、操作を完了させることができなくなります。


## `aria-disabled` 属性を使って作ろう！
上記のように、`disabled` 属性をつけるとボタンの存在が認知できないので、`disabled` 属性をつけるのは良くないですが、「特定の条件の時にボタンを押せるようにする」という挙動を作りたいという時はあると思います。

そのような時は、`aria-disabled` 属性を使って作りましょう。

### サンプル

<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="zYQpGme" data-pen-title="disabledとaria-disabled" data-editable="true" data-user="sp_degu" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/zYQpGme">
  disabledとaria-disabled</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### ポイント
**⚪︎ `aria-disabled` を使って、不活性を表現します。**
hoverした時に、ボタンが押せないように `cursor: not-allowed;` を記述しています。

```sample.css
button[aria-disabled="true"] {
  cursor: not-allowed;
  /*不活性のスタイルを記述する*/
}
```


**⚪︎ クリックイベントが発火しないようにする**
`aria-disabled`属性だけでは、クリックイベントが発火していまうので、イベントは発火しても、処理が行われないように`return` する

```sample.js
let disabled = true; /* ボタンがdisabledにするかしないかを決めるフラグ */

button.addEventListener('click', (event) => {
  if (disabled) { return }
  /* ボタンを押した時の処理を書く */
});
```

## まとめ
この記事では、ボタンに`disabled`属性をつけない方がいい理由と`disabled`をつけない方法を紹介しました。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
プログラミング初心者はオセロ制作がオススメという話

# はじめに。
皆さんはプログラミング初心者に対して助言をする場面において、初心者向けの基礎教材を終えた後、次の段階で何をするべきと伝えますか?基本的には何か簡単なアプリを作ることを勧めると思います。しかし、この最初に作るアプリの内容次第では、技術的ハードルの高さや時間がかかり、諦めてしまうことがあるかもしれません。例えばゲーム制作で言えば、RPGゲームを作ろうとするとゲームシステムとストーリーが必要であり、時間が非常にかかります。

特に最初のステップでは、継続して続けられるものにすることが重要であり、それがその後の意欲にも影響します。私はその最初に作る作品としてボードゲーム、特にオセロをお勧めします。

この記事では、そう考える理由を書いて行きます。

:::note warn
あくまで一個人の考えです。参考程度に読んでいただけますと幸いです
:::

# 想定している対象
- 独学で基礎はやったが、その後何すればいいか迷ってる初心者
- 学校の授業で習った後により力を付けたい学生
- 初心者を指導する立場にある人

# ボードゲームで楽しみながら制作する
何事も重視すべき項目は「**モチベーションを保つ**」ことであり、その観点においてボードゲームは「楽しみながら」制作ができるためモチベーションの維持がしやすいと考えています。

基本的に何らかのツールやゲームを数時間や1,2日で作ることは難しいです。類似したものを作った経験がなければ、経験からアルゴリズムやシステム構成を考えることができないため、制作時間が長期化しやすいです。これに加えてデバッグにも時間がかかり、この間モチベーションを保ち続ける必要があります。
そして、作ったものが自分や他人に使われなければ、やる気をなくすでしょう。

例えばツールであれば特別なアイデアがない限り、途中で「何でこれを作っているのか？」と感じるかもしれません。それは大体の場面において、既に世の中には優れたものがあり、大体の開発が「[車輪の再開発](https://ja.wikipedia.org/wiki/車輪の再開発)」となり、自分でも使わない代物が出来上がる可能性があります。

その点、ボードゲームは以下のメリットがあります。
- 開発期間が短い
- 実用に耐えられるレベルにするのがツールと比べれば容易
- デバッグをゲームしながらできるため楽しい
- 友人などの共有した時に**遊んで貰いやすい**(体感)

このようなメリットがボードゲームにはあると考える中で、私は特にオセロを勧めます。

# オセロ制作のメリット
## ルールが簡単で理解しやすい
オセロのルールは非常にシンプルで、多くの人が[プレイしているゲーム](https://www.othello.gr.jp/r_info/100/020/#:~:text=現在の日本のオセロ,してもダントツです。)であり、ゲームのルールを説明せずともプログラミングに集中して行えます。
仮に分からなかったとしても、オセロを表すキャッチャーフレーズに「**A minute to learn, a lifetime to master（覚えるのは１分、極めるのは一生）**」[^1]があるように、誰でも簡単にルールを覚えることができます。

子どもでも理解できるほどゲームルールはシンプルであり、将棋や囲碁のように役がない上に禁じ手はありません。この特徴はプログラムとして書き出すのには最適で、その分だけ状態の数が少ないため条件分岐を減らすことができます。

そして、このような理由からか、インターネットで「オセロのプログラミング」に関する記事を調べてみると多くの記事が見つかります。仮にプログラミングにて詰まったとしても参考にできる記事が多くあるため、完成形に持っていくということはほぼ確実に出来るはずです。
 
## 必要なスキルレベルが低め
オセロはゲームルール自体が単純であり、禁じ手がなく、局面数も多くなりません。そのため、コアとして必要な処理は置いたときにひっくり返す処理が一度できれば他に必要な処理はだいたい出来るはずです。そのため、forと標準入出力、配列といった基本的なプログラミング知識さえあれば、高いアルゴリズムの実装能力であったり、その他のサーバーやデータベースなどの知識が無くても作ることができます。

また、基本的な処理が完成した後、AIの実装やオンライン対戦などを追加しようとした際には、インターネットの既にあるゲームから参考にしつつ、自身の興味とスキルに応じて機能の追加できる点も更なるステップが見込めてよい点であると考えています。


# 他のボードゲームとの比較した時のメリット
まずオセロは、[二人零和有限確定完全情報ゲーム](https://ja.wikipedia.org/wiki/二人零和有限確定完全情報ゲーム)に分類されるゲームで、これに分類されるゲームとしてはチェス・将棋・チェッカー・囲碁・五目並べなどがあります。わざわざオセロじゃなくても、これらのゲームでもよいと考える人がいるかもしれませんが、実装がめんどくさいと思うので最初に作るものとしては選ばない方がよいです。

チェスや将棋なら駒に種類があり、複雑な動きを再現するために実装の手間が増えます。また将棋は、取った相手の駒が自分の駒として使えるようにする処理も必要です。囲碁だと勝敗を決めるのは「石で囲んだ陣地の数」であるため、その分アルゴリズムは複雑になります。

また、オセロは10^28、チェスは10^44、将棋は10^71[^2]、囲碁は10^170局面[^3]であり、AIを作ろうとした場合に実現可能局面数が少ないオセロの方が探索しやすいかと思います。


# おわり
今回は、オセロがプログラミング初心者にとって最適な題材である理由についてお話ししました。オセロはルールが簡単で、初心者でも自力で取り組みやすく、楽しみながら制作できるため、モチベーションを維持しやすい点が大きなメリットです。
まだ作ったことがない方も、ぜひオセロの制作に挑戦してみてください。

[^1]: https://www.niigata-nippo.co.jp/articles/-/14901
[^2]: https://diamond.jp/articles/-/327877
[^3]: https://tromp.github.io/go/legal.html
Salesforceレポートで表示させる項目を増やす方法

本橋孝昭です。

Salesoforceレポートで表示させる項目を増やす方法をご紹介します

例として商談の一覧をレポートに出す際に標準レポートタイプ「商談」レポートで表示させようとします


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/790cff1d-e390-7698-87de-ba9f685c0f5e.png)


しかしこれではたとえば「商談所有者の最終ログイン日」などを標準レポートタイプ「商談」レポートで表示させることはできません

では、このように通常の標準レポートタイプでは表示させられない項目を表示するにはどうすればいいでしょうか
それはカスタムレポートタイプを作成することです。


## ステップ1 カスタムレポートタイプを作成しよう

まずはカスタムレポートタイプを作成します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/00a47dea-5cd4-2743-441c-76d32ae60093.png)

## ステップ2 カスタムレポートタイプを編集

下記画像の「レイアウト編集」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/63763246-1934-1b54-9903-4cdab8e38dce.png)



「参照先の項目」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f9e73c15-8330-a71f-a641-4023a148f151.png)


商談所有者＞をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/c4433d93-8510-d752-5ca6-71ac1e6a90f5.png)


「最終ログイン」をクリックしてOKをクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/905820e0-66cd-c824-1262-7b3f231f1548.png)

項目レイアウトにあることを確認し保存をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/9bbc4d75-4012-99c9-9c20-783123e73878.png)



このように先ほど作成したカスタムレポートタイプでは商談所有者の「最終ログイン」を確認することができます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1a4bd1f3-f263-e22e-ec28-00aa909eb9a5.png)
RustでかわいいSPA：SycamoreでもTailwindCSSが使いたい


## 背景

SycamoreというRustでSPAを作るためのライブラリがあります。このSycamoreを使ったSPAをビルドするときにはTrunkを使います。そしてこのTrunkがTailwindCSSに対応していた事実にいまさら気づいたのでお試ししてみたくなりました。

Trunkを使うのはCargoやwasm-packとは異なり、RustのWebアプリをビルドしたり動かしたりする時の作業を自動化することができて、静的なファイルの管理が簡単になるからです。

特に今回Trunkを使う理由として大きいのは、Node.jsやnpmやnpmみたいな役割のコマンドを使うことなくTailwindCSSを自動化する部分を使いたいというところです。

## 準備

Rust、Cargo、Trunkをインストールしておきます。環境次第なので説明はふんわりさせてください。

https://rustup.rs/

https://trunkrs.dev/

一般的にはこのへんを参考にがんばるようです💪

## Sycamore＋TailwindCSSなSPAを作る



今回はTailwindCSSを使うのが実質本題なのでここを重点的に参考にします。

https://trunkrs.dev/assets/#tailwind

```html:index.html
<!doctype html>
<html>
	<head>
		<meta charset="UTF-8" />
		<link data-trunk rel="rust" href="./Cargo.toml" />
		<link data-trunk rel="tailwind-css" href="./globals.css" />
	</head>
	<body>
	</body>
</html>
```

こんな感じに書きますが、特に

```html:index.html（抜粋）
		<link data-trunk rel="tailwind-css" href="./globals.css" />
```

↑ここがポイントです！

```css:globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

ここはいつものやつです。

次にここを参考に設定ファイルを書きます。

https://tailwindcss.com/docs/configuration

```js:tailwind.config.js
module.exports={
	content:[
		'./src/**/*.rs',
		'./index.html',
	],
};
```

ここでRustのファイルを全部指定します。

あとはRustの部分を書きます。

まずもちろんパッケージをSycamoreに依存させます。

```toml:Cargo.toml（抜粋）
[dependencies.sycamore]
version="^0.9.0-beta.2"
```

```rust:src/main.rs
use sycamore::prelude::*;

fn main(){
	sycamore::render(||view!{
		h1(class="text-blue-500"){
			"hello world"
		}
	});
}
```

お試しするにはこれで十分です。

```rust:src/main.rs（抜粋）
		h1(class="text-blue-500"){
```

ここがポイントで、ここにTailwindCSSのクラスをなんか指定します。今回は水色にしてみます。

## 確認してみる

こんな感じのコマンドを実行して……

```bash:ターミナルで実行
trunk serve
```

ブラウザで開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782801/eb214436-2489-3e87-dea4-01cf4636c140.png)

もう十分申し訳程度にはかわいいです🎉

## 感想

これでTailwindCSSを使うためだけにnpmのpackage.jsonを書かなくていいのはありがたみを感じました。
プロセスとVBOの一覧をラクに作成する #blueprism

# プロセスとVBOの一覧と各内容をドキュメント化する（面倒）
一覧をドキュメントにして管理するっていうのは普通にやるべき業務です。
だけどこれめんどくさいのですよね。
プロセスやVBOの新規作成や内容更新があってもドキュメントまで更新してくれるわけでもなく、だんだん現状とドキュメントが乖離する。あるあるです。
いまここに現物があるんだから、それを見て最新の内容を自動でドキュメントにしてくれればいいのに。
君はRPAなんだからそういうのも自動でやってほしい……。

UiPathはここに記事があります。
[【UiPath】プロジェクトの内容をドキュメント化したい(みやぎさんの記事)](https://qiita.com/miya_gis/items/fb65d758d074e8974790)

いいなーUiPath…… と思ったBP使いのあなた。
あるんやで。
BPにも。
すごくいいやつが。

# 困ったときのDX
そういうことを考える怠惰エキスパート的な先達はだいたいいます。
つまりDXにあります。
[Utility Program for Business Object Library Snapshot Generator](https://digitalexchange.blueprism.com/cardDetails?id=131020)
もうこれがあったら人間が書かなくてもよくない？ってくらい出来のいいのが出て来ます。

# どんなものが作れるのか
ブラウザベースで閲覧する体裁です。

+ プロセスとVBOの一覧
プロセスはページごと、VBOはアクションごとで1行。ODIみたいなフォーマットです。
上にリンクを貼ったDXのページにも画像がありますが、一覧はこんな見た目です。
![Screenshot_20221129_121220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/90635474-4925-97ea-2a38-2183fc056a11.png)
これの素晴らしいところは、参照しているVBOやプロセス名がリンクになっていて、クリックすると当該のプロセスやオブジェクト自体の情報が見られるところです。
紙ベースじゃこうはいかないし、Excel台帳でこれを作るのは相当めんどくさいです。
この一覧表で得られる情報は
    + ページ名
    + 参照しているアクション
    + 入出力引数
    + おおよその処理フロー（ステージごとにログの「有/無/エラーのみ」が判別できるアイコンがつきます）
　
+ プロセスとVBO全部のXML
上の一覧表を作成する際の副産物ですし容量も食いますが有用です。
なんなら現時点でのプロセスVBOの退避用としても。



# 使い方
## 準備
### DLLを配置
DLしたファイルの中に入っているDLL（2個）を、Blue Prismの実行ファイルと同じ場所に置きます。

### 出力用のフォルダを作成する
実行RRから見えるところ。
プロセスのデータアイテムのデフォルト設定は C:\BluePrism\BOL、その中にinputフォルダとoutputフォルダ
容量はけっこう空けてください。XMLが全部出るのでファイル数もサイズも相当必要です。

### このプロセスが使用するためのユーザーアカウントを作成する
このプロセス専用のユーザーを1個作って権限を付与します。

### リリースのインポート
リリースはDLした中にDLLと一緒に入っています。

### プロセスのデータアイテムに値を設定する
設定するのは下図参照。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/8bf7cf23-7f50-428e-e0e7-e46e9b5641a3.png)

### 認証情報に値を設定する
このプロセスで使う認証情報も設定しておいてください。
リリースをインポートしたときに「Blue Prism BOL」みたいな名前で認証情報のガワもできているはずです。
そこに「このプロセスが使用するためのユーザーアカウントを作成する」で作成したユーザのID/PWを設定します。

## 実行
あとはプロセスを実行するだけ。
開発規模にもよりますが、何時間単位でめっちゃ時間かかります。リソースと時間に余裕のあるときにどうぞ。

# 終わりです
現状を反映していないExcel台帳を後生大事にとっとくよりも、こういうやつで定期的に最新版を作っとくのがいいですよね。
そしてDXはほんとに便利。検索機能がアレなので探すときにイラッとしますが、宝探しだと思って根気よく発掘してください。実は使えるやつがいっぱいあります。
PostgreSQL を Windows11 にインストール

# はじめに
この記事では、PostgreSQL を Windows11 にインストールする手順について記載します。

https://www.postgresql.org/

# 開発環境
- Windows11
- PostgreSQL 16.3

# インストーラーのダウンロード
まず、以下のページから Windows x86-64 のインストーラーをダウンロードします。

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/363b9911-4efc-2696-0914-c205abeffb87.png)

# インストール
ファイルをダブルクリックして、インストーラーを起動します。

インストーラーが起動したら「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/1ee62b19-425f-7608-bbd6-704a5fbd4b21.png)

インストール先のフォルダを指定します。
今回はデフォルト値（`C:\Program Files\PostgreSQL\16`）のまま「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/791a2c06-6906-36aa-479b-b42c43917d28.png)

インストールするコンポーネントを指定します。
こちらもデフォルト値のまま「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/e997e36b-0c35-2798-53c7-7edba5c96935.png)

データベースを保存する先のフォルダを指定します。
こちらもデフォルト値（`C:\Program Files\PostgreSQL\16\data`）のまま「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/5e8ccb14-24cd-1732-447a-124a4d8603a6.png)

スーパーユーザーのパスワードを指定します。
入力できたら「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/d80c6a50-3483-487b-79cf-c350297f48c7.png)

クライアントからの接続を受けるポート番号を指定します。
デフォルト値のまま「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/9ecca356-6703-3f0d-811b-4d4df9cbb5f6.png)

ロケールを指定します。
ロケールを使用するとパフォーマンスが落ちるようなので、ロケールを使わないことを示す `C` を選択して「Next」をクリックします。[^1]

[^1]: https://www.postgresql.org/docs/current/locale.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/e82705d2-101f-4faa-526c-55a688a318c6.png)

インストールの設定内容が表示されます。
確認して問題がなければ、「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/4ba9a9b8-59b3-2bf5-a488-f50b820f4441.png)

「Next」をクリックすると、インストールが開始されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/86c37dd8-c6a1-2957-3747-ef0b9b04e2f4.png)

インストールが完了すると、以下の画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/778e0904-0c4c-9a7b-90ed-2d281417a89f.png)

# Path を設定する
環境変数の Path に今回インストールした PostgreSQL の Path（以下）を追加します。

```
C:\Program Files\PostgreSQL\16\bin
```

Path が正しく設定できたか確認するため、Windowd PowerShell で以下のコマンドを実行します。

```powershell
psql --version
```

バージョンが表示されれば、正しく設定できています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/2440b237-c397-a617-348c-73d0ae489037.png)

:::note warn
Windowd PowerShell は、環境設定が完了してから開く必要があります。
:::



# 参考
- [PostgreSQL: Documentation: q6: 24.1. Locale Support](https://www.postgresql.org/docs/current/locale.html)
- [PATHを設定する](https://www.javadrive.jp/postgresql/install/index3.html)

# 関連記事
https://qiita.com/Yasushi-Mo/items/fe67cae83a71840460ea
【Python】tkinterを使用してキーバインドに対応する方法

# 1.はじめに
Pythonでtkinterパッケージを使用して、簡易的なGUIアプリを自作していたのですが、
キーバインドをbindメソッドで行う方法がネット上にあまり確認できなかったので、本記事を投稿しました。
tkinterを使ってGUIアプリを作る際に、「CTRL+s」を押したら名前を付けてファイルとして保存する関数を実行させたり、「CTRL+f」を押したら単語を検索する関数を実行させたりなど、キーと関数を結び付けたいと思った際に、参考にしていただけたら幸いです。

### 開発環境
・WSL2/Ubuntu環境
・Python: 3.10.12

# 2.tkinterの紹介

tkinterパッケージはWindowsや macOSなどに対応しているクロスプラットフォームなGUIライブラリです。tkinterはPythonに標準で付いているため、気軽に使用できます。ウィンドウやボタンなどGUIアプリに必要な様々な部品を構築できます。

https://docs.python.org/ja/3/library/tkinter.html

# 3.tkinterを使用してキーバインドに対応する方法

動作確認するためのサンプルプログラムとして以下プログラムを作成しました。

```Sample.py:
import tkinter as tk
from tkinter import filedialog, Text


# Function to save file
def Sample_SaveFunc(event=None):
    savefilepath = filedialog.asksaveasfilename(
        filetypes=[("Text files", "*.txt")],
    )
    if savefilepath:
        with open(savefilepath, "w") as file:
            file.write(text.get(1.0, tk.END))


# configure root
root = tk.Tk()
root.title("bind_sample")
root.geometry("800x600")

# configure text
text = Text(root, wrap="word", undo=True)
text.pack(fill="both", expand=True)

# configure key-bind
root.bind("<Control-s>", Sample_SaveFunc)
root.bind("<Control-S>", Sample_SaveFunc)

# display window
root.mainloop()
```

### プログラムの動作
キーボード操作で「Controlとs」を押すとSample_SaveFunc関数が呼ばれ、Sample_SaveFunc関数では現在text領域に記載されているデータを.txt形式で保存します。

### 2024/06/29 プログラムに追記
当初プログラムの「# configure key-bind」の項目には以下コードのみを記載していました。
```
root.bind("<Control-s>", Sample_SaveFunc)
```

「コメント欄」にて、上記コードのように「Control-s」のみの場合CapsLockが有効の際にショートカットキーが動作しないとのご指摘を頂き、CapsLockが有効の際でもショートカットが動作するように以下コードを追記しております。

```
root.bind("<Control-S>", Sample_SaveFunc)
```

### bindメソッドの使い方
bindメソッドの使い方ですが、以下のサンプルのようにキーの名前と対応する関数を引数とすることで、該当するキーが叩かれたら、対応する関数が呼ばれます。
```:
import tkinter as tk
root = tk.Tk()
root.bind("<キーの名前>", キーに対応する関数)
```

#### 補足)「キーの名前」の指定方法
***Controlを使う場合***
例）キー操作：「Control+s」に反応する場合
```
"<Control-s>"
```
キー操作：「Control+f」に反応する場合
```
"<Control-f>"
```

***Shiftを使う場合***
例）キー操作：「Shift+n」に反応する場合
```
"<Shift-N>"
```

# 4.終わりに
本記事ではtkinterを使用してキーバインドに対応する方法について紹介しました。
キーと関数を結び付けたいと思った際に、参考にしていただけたら幸いです。

## 参考文献
本記事は以下情報を参考にして執筆しました。
・Python 3.12 ドキュメント

https://docs.python.org/ja/3/library/tkinter.html

・PythonのTkinterを使ってみる

https://qiita.com/nnahito/items/ad1428a30738b3d93762
LM Studio をプロキシ環境下で実行する方法

# 結論

ブラウザや `wget` コマンドでモデルをダウンロードして `lms import` コマンドでインポートする。

# LM Studio の導入

LM Studio の公式サイトからインストーラーを使用してインストール。
ここまではプロキシ環境でも問題なく実行可能。
https://lmstudio.ai/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/d2bad0e2-624a-1b0b-b634-5d10fdb03339.png)

GUI上からモデルのダウンロードを実行すると以下のようにダウンロードに失敗する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/8ee3aa45-2583-3cf5-cb90-c678d5de1d8a.png)

プロキシ対応は望まれているが未対応の模様。

https://github.com/lmstudio-ai/configs/issues/1

# モデルのダウンロード

先ほどのログに出力されているモデルのURLを使用しLM Studio以外の方法でモデルを取得する。

`https://huggingface.co/lmstudio-community/Meta-Llama-3-8B-Instruct-GGUF/resolve/main/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf` の部分。
ブラウザのURLにコピペしてダウンロードするのが簡単。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/fbbc8fdf-9458-866b-4ed5-04e188bd6511.png)

# モデルのインポート

LM Studio は `lms` コマンドでも操作可能だが、インストール時にはパスが通っていないため Bootstrap を実行してパスを通す。

https://lmstudio.ai/blog/lms

```shell:Bootstrapの実行
# Mac / Linux:
~/.cache/lm-studio/bin/lms bootstrap

# Windows:
cmd /c %USERPROFILE%/.cache/lm-studio/bin/lms.exe bootstrap
```

`lms` コマンドの実行には LM Studio が起動している必要がある。（未起動の場合はコマンド実行時に起動しウィンドウが開く）


ダウンロードしたモデルのインポートには以下のコマンドを実行する。

```shell:モデルのインポート
lms import Downloads/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf
```

カテゴライズを聞かれるが一番上の Hugging Face で検索にするとまた通信エラーになってしまうため、二番目の Interactive import を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/854fc6fc-ef46-d880-4f4b-523140912dad.png)

作成者やモデル名を聞かれるがローカルで使用するだけなので空欄（デフォルト）のまま進める。`File moved to ~` と表示されていれば成功している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/6b7f7bb8-4c39-25c0-f2db-df528c3f6ea4.png)

# モデルの実行

GUIの「AI Chat」タブを開き「Select a model to load」をクリック。
先ほどインポートしたモデルが表示されていれば成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/cfe1bbc2-f8db-c559-b727-69b171a6850d.png)

無事ローカルLLMの実行に成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997186/ecfc93da-17ca-aeb1-d876-89e6efbe4d86.png)

# 終わりに

簡単に導入できるようにされているツールでもプロキシがあるだけで苦戦しました。。。
プロキシ環境下でローカルLLMの実行に挑戦している企業戦士の皆様のお役に立てれば幸いです。
iPhone / iPad で日本語入力の確定キー押下を keydown / up イベントで検知できなかった話

ちょっとハマったのでメモしておきます。

## バージョン

- iPad 17.4.1
- iPhone 15.8.2 

## やりたいこと

やりたいことは以下の２つです。
1. iPhone / iPad で、日本語入力時（ローマ字入力モード）の確定キー押下を検知したい
1. iPhone / iPad で、日本語入力時（ローマ字入力モード）の変換候補の中から何か１つが選択されたことを検知したい

以下、 iPhone のスクリーンショットになります。

ちょっと分かりづらいと思いますが、日本語ローマ字入力モードで「くま」の２文字を入力した直後の、まだ未確定のときのスクリーンショットになります。

このまま「くま」で入力を確定させたい場合は赤枠内の**確定**ボタンを押下すると思いますが、これがやりたいことの 1 になります。
「熊本」で確定させたい場合は黄色枠内の**変換候補**の中から「熊本」を選択すると思いますが、これがやりたいことの 2 になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/f4138ac2-28a6-3e3b-a66a-184b143db467.png)

```html
<input type="text" id="hoge">
```

```javascript
const inputElement = document.getElementById('hoge');
inputElement.addEventListener('keydown', (event) => {
  // 発火しない
});
```

単純に、上記のコードのように **keydown** イベントで検知できるだろうと思っていたのですが検知できませんでした。**keyup** イベントも検知できませんでした。

Safari 以外だとどうなるかが気になり、iPhone + Chrome でも試してみましたが、Safari の時と同様に検知できませんでした。※ iPad + Chrome は未検証です。

## 解決方法

**compositionend** イベントで検知できます。

入力可能な input 要素などは、IME を使って文字入力を行うと、変換開始時に **compositionstart** イベントが、変換終了（確定）時に **compositionend** イベントが発生するため、これを利用します。

**CompositionEvent** オブジェクトの `data` プロパティに **確定した文字列** が入っています。

```javascript
const inputElement = document.getElementById('hoge');
inputElement.addEventListener('compositionend', (event) => {
  // 発火する
  // event.data に「確定した文字列」が入っている
});
```

ちなみに、日本語入力時でないときは確定キーではなく**改行キー**に変わると思いますが、この改行キーの押下については keydown / up イベントで検知できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/ab014ef7-acb4-c0e8-ef15-26bfb8f766c3.png)
Pythonのリスコフの置換原則

# 概要

背景として、[後述のDjangoのModel定義でリスコフの置換原則満たさない書き方](#djangoのabstractbasemodel)をみんなしているのではないかという疑問が出てきたので、軽くまとめました。

# 関数の場合

以下の継承は、**reverse** の型が変わっているので、リスコフの置換原則を満たしません。

```python
class Parent:
    def reverse(self, x: int) -> int:
        return -x
class Child(Parent):
    def reverse(self, x: str) -> str:
        return x[::-1]
```

同じく、一見大丈夫そうに見えますが、`@proparty`を用いた場合もリスコフの置換原則を満たしません。
Parentではnameメソッドですが、Childではnameフィールドになっています。

```python
class Parent:
    @property
    def name(self) -> str:
        return "parent"

class Child(Parent):
    name = "child"
```

以下のように修正しなければなりません。

```python
class Parent:
    @property
    def name(self) -> str:
        return "parent"

class Child(Parent):
    @property
    def name(self) -> str:
        return "child"
```

# インナークラスの場合

以下はインナークラスを使用したリスコフの置換原則を満たさない例です。

```python
class Car:
    class Engine:
        gas = True


class EVCar(Car):
    class Engine:
        battery = True


car = Car()
engine = car.Engine()
print(engine.gas)  # True

ev = EVCar()
engine = ev.Engine()
print(engine.gas)  # AttributeError
print(engine.battery)  # True
```

上記は継承しているのにも関わらず、Engineをオーバーライドしてしまっています。EVCarのgas属性がないので、EVCar is Carの関係が成り立ちません。これはリスコフの置換原則を満たしません。

以下のようにすると、EVCarでCarのEngineも継承できております。

```python
class Car:
    class Engine:
        gas = True


class EVCar(Car):
    class Engine(Car.Engine):
        battery = True


car = Car()
engine = car.Engine()
print(engine.gas)  # True

ev = EVCar()
engine = ev.Engine()
print(engine.gas)  # True
print(engine.battery)  # True
```

しかし、上記だと、EVCar の engineの gas が*True*になってしまいます。そこで、EVCar のEngineで明示的に gas を *False* にします。

```python
class Car:
    class Engine:
        gas = True


class EVCar(Car):
    class Engine(Car.Engine):
        battery = True
        gas = False


car = Car()
engine = car.Engine()
print(engine.gas)  # True

ev = EVCar()
engine = ev.Engine()
print(engine.gas)  # False
print(engine.battery)  # True
```

# DjangoのAbstractBaseModel

Djangoでは抽象モデルとして、共通フィールドを `AbstractBaseClass`で定義することがあります。
例えば以下のようにcreate_atを共通化します。`AbstractModel`のメタデータに`abstract = True`があるので、AbstractModelはデータベースにマッピングされません。

```python
from django.db import models

class AbstractModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True


class Foo(ModelTemplate):

    class Meta:
        ordering = ["id"]
```

よく見かけるこの書き方、継承しているのにも関わらず、オーバライドしています。
そこで以下のように修正します。

```python
from django.db import models

class AbstractModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True


class Foo(ModelTemplate):
    class Meta(ModelTemplate.Meta):
        ordering = ["id"]
```

実行してみます。

```python
from public_service.models.a import ModelTemplate,Foo
a = Foo()
a.Meta().abstract # False
```

`abstract=True`が継承されているので、`a.Meta().abstract`は *True* になると思ったのですが、 *False* になりました。`models.Model` の実装を見ると、`_meta`でabstractがなければ自動的に *false*が設定されるようになっています。(実装の説明は割愛)

# 最後に

Pylanceでは `reportAssignmentType` として、継承時にオーバーライドしてしまっているものを検知することができます。
Unity×Snapdragon Spacesでハンドトラッキングを実装

# 環境構築
###  Unityでプロジェクトを作成
Unityでプロジェクトを作成
###  Snapdragon SpacesのSDKをダウンロード

公式サイトからSDKをダウンロードする。ARの方が新しかったのでそちらをダウンロード。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/25dd36f8-3dbb-e52a-2ac9-80cd4ca1812f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/7c9b3ecb-6bc9-2d01-7501-2f90d4db2d5f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/4e4c2054-0348-9a72-f782-60d0586d825c.png)

どちらのtgzもダウンロードする

### プロジェクト設定
Androidに切り替えたり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/8aae9d0b-96ab-0836-66e1-6732a41f2bc0.png)

OpenXRにチェックを入れたり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/8424d99e-7f43-23d3-92d3-cf8857f39a02.png)

CameraやHand Trackingにチェックを入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/d291a338-fb83-42c2-dc6e-46e932b5328d.png)

# サンプルをインポート
Package ManagerからQHCTやSnapdragon Spacesのサンプルをインポートする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/8d031bbd-f9ee-5da2-6685-1828f8aa3182.png)

QHCTのサンプルの「QHCT Rig Setup(XR Rig)」をコピペして使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/8773b725-9ba2-5f59-5934-6958155c7cbb.png)

# 使いたいシーンへ

例えばAR Foundationで既に「AR Session」や「XR Origin」が合ってもそこにQHCT Rig Setup(XR Rig)を追加してよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/c72216d1-cfbf-6f37-aed3-06d90d84ad43.png)

「Tracking Mode」はDeviceでoffsetは0にしておく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/de7cf7c7-6888-df55-e783-ba5493c29d55.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574599/4e343442-75ec-6eb5-9da1-b67b331c54e9.png)

# ビルド
あとはSnapdragon Spacesに対応したスマホにビルドしグラスをつなげればハンドトラッキングされる
Nim で Welcome to AtCoder を解いてみた

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)
において、約1ヶ月で38記事という大量の記事の投稿を要求されることがわかった。
そこで、あまりコストをかけずに記事数を稼ぐ方法を考えた結果、「Welcome to AtCoder を様々な言語で解く」ことを思いついた。
単に解くだけでなく、使用する言語仕様の解説を入れれば、記事として一応成立するだろう。

# Welcome to AtCoder

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

Welcome to AtCoder では、以下の形式で整数 $a$, $b$, $c$ および文字列 $s$ が入力として与えられる。

```text
a
b c
s
```

この入力をもとに、与えられた整数の和 $sum = a + b + c$ および文字列 $s$ を、以下の形式で出力することが求められる。

```text
sum s
```

# 今回用いる Nim の機能

[Documentation - Nim Programming Language](https://nim-lang.org/documentation.html)

## 変数

[Naming values](https://narimiran.github.io/nim-basics/#_naming_values)

```
let 変数名 = 値
```

と書くことで、**実行時に値が決まり、その後再代入をしない**変数を定義できる。

また、

```
var 変数名 = 値
```

と書くことで、**再代入ができる**変数を定義できる。

:::note info
今回は用いないが、`const` を用いることで**コンパイル時に値が決まる**変数 (定数) を定義できる。
:::

```
変数名 = 値
```

と書くことで、定義済みの変数に対する代入ができる。

## 文字列

[Strings](https://narimiran.github.io/nim-basics/#_strings)

文字列は、`""` で囲んで表現する。

## 数値の加算

[Integers](https://narimiran.github.io/nim-basics/#_integers)

`+` 演算子を用いることで、数値の加算ができる。

## 出力

```
echo 値
```

と書くことで、「値」を標準出力に出力し、さらに改行を出力できる。

```
echo 値1, 値2
```

のように値を `,` で区切って複数指定することで、1行に複数の値を連結して出力できる。
このとき、指定した値以外の区切り文字などは自動で出力されない。(最後の改行は出力される)

## 入力

[Reading user input](https://narimiran.github.io/nim-basics/#_reading_user_input)

`readLine(stdin)` を用いることで、標準入力から1行読み込むことができる。
読み込んだ行が文字列として返される。返される文字列には最後の改行文字は含まれない。

## 列の走査

[For loop](https://narimiran.github.io/nim-basics/#_for_loop)

```
for 変数 in 列:
  処理内容
```

と書くことで、「列」(イテレータ) に含まれる要素を1個ずつ順に「変数」に格納し、「処理内容」を実行できる。

## 文字列の加工

[Dealing with numbers](https://narimiran.github.io/nim-basics/#_dealing_with_numbers)
[splitWhitespace](https://nim-lang.org/docs/strutils.html#splitWhitespace.i%2Cstring%2Cint)

```nim
import strutils
```

と書くことで、文字列を処理するライブラリを読み込むことができる。

`文字列.parseInt()` により、「文字列」をそれが表す整数に変換できる。

`文字列.splitWhitespace()` により、「文字列」を空白文字で区切った列 (イテレータ) を得ることができる。

# 提出コード

```nim
import strutils

var sum = readLine(stdin).parseInt()

for item in readLine(stdin).splitWhitespace():
  sum = sum + item.parseInt()

echo sum, " ", readLine(stdin)
```

[提出 #54654041 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/54654041)
【CakePHP5】PHPStanをGitHubActionsで使う

# はじめに

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

前回PHPStanをローカルでコマンドを打って実行したので、今回はPushした時にGitHub上で実行するようにしようと思います。

https://qiita.com/keitaMax/items/77df412e05a537571549


# GitHubActionsの設定ファイル

`.github/workflows`ディレクトリを作成し、`phpstan.yml`ファイルを作成します。

```yml:phpstan.yml
name: LaraStan
on: [pull_request]

jobs:
  phpstan:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./src
    steps:
      - uses: actions/checkout@v2
      - name: dokcer-compose up
        run: |
          docker-compose up -d

      - name: Composer install
        run: docker compose exec app composer install

      - name: Run PHPStan
        run: docker compose exec app composer stan

```

これは以前の記事で作成したLaravelのymlファイルを参考にしています。

https://qiita.com/keitaMax/items/63d64590e53def393f4c

# 実際にPushする

実際にGitHubにPushしてみます。

すると以下のようにGitHubActionsが動いているのがわかります。

![スクリーンショット 2024-06-09 14.46.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/98e598f0-6c24-82aa-21a4-0eee2c5936a0.png)

実行が終わると、以下のようになります。

![スクリーンショット 2024-06-09 14.53.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/b0736bf4-9339-6e10-f097-5c7834abf1e9.png)

これでGitHub上でPHPStanを実行することができました。


# 失敗させてみる

正しく動いているか確かめるために失敗させてみます。

Controllerの`}`をわざと削除してPHPStanでエラーが出るようにしてPushしてみます。

すると以下のようにエラーになるのがわかります。

![スクリーンショット 2024-06-09 14.56.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/4ba02f5c-279b-3043-c4e5-c68152c2055e.png)


ただしくPHPStanがGitHub上で動作していることが確認できました。


# おわりに

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

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

# 参考

https://qiita.com/keitaMax/items/63d64590e53def393f4c
FormEventHandlerとFormEventの差

## FormEvent
React.FormEventHandler<HTMLFormElement>とReact.FormEvent<HTMLFormElement>は、Reactでフォームイベントを扱うための2つの型です。これら2つの型の主な違いは以下の通りです


## React.FormEventHandler<HTMLFormElement>
React.FormEventHandler<HTMLFormElement>は、フォームイベントを処理する関数の型です。この関数はフォームイベントオブジェクトを引数として受け取ります。例えば、フォームの送信イベントハンドラはこの型を使用します

## React.FormEvent<HTMLFormElement>
React.FormEvent<HTMLFormElement>は、フォームイベントオブジェクトの型です。このオブジェクトはフォームイベントが発生すると生成され、イベントに関する情報を持っています。例えば、イベントオブジェクトを使用してデフォルトのフォーム送信動作を防ぐことができます：


## まとめに
したがって、React.FormEventHandler<HTMLFormElement>はイベントを処理する関数の型を表し、React.FormEvent<HTMLFormElement>はイベントオブジェクトの型を表します。これら2つの型はそれぞれ異なる目的で使用されます。
LeetCode挑戦日記：Day10

# はじめに

最近、業務で実装する時間よりも資料作成やレビューをする時間が多くなってきました。
このままでは自身のコーディング能力が落ちそうで怖いので、LeetCodeを始めてみました。

自身の学習の記録 & LeetCodeに興味のある人が挑戦しやすいように、記事に残していきます。
このような競技プログラミングをした経験がないので、ひよってEasyからやっていきます...

# [Easy] 283. Move Zeroes

整数の配列`nums`が与えられたとき、0以外の要素の相対的な順序を維持しながら、すべての0を配列の末尾に移動させる。

配列のコピーを作成せずに、インプレースで実施すること。

## 素直に解いてみる

### 考え方

1. `nums`配列を前から確認し、0があったら削除し、配列の最後に追加する

### コーディング

```typescript
function moveZeroes(nums: number[]): void {
    let length = nums.length;
    for (let i = 0; i < length; i++) {
        if (nums[i] === 0) {
            nums.splice(i, 1);
            nums.push(0);
            i--;
            length--;
        }
    }
};
```

### 結果

Runtime：88ms
Beats 30.28%

Memory：55.14MB
Beats 55.76%

## 改善：配列操作を減らす

### 考え方

1. 配列の`splice`tと`push`に時間がかかっていると仮定
1. `nums`配列を前から確認していき、0の分だけずらす
1. 最後に末尾から0の数だけ0を入れる

### コーディング

```typescript
function moveZeroes(nums: number[]): void {
    let zeroCounter = 0;
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] === 0) {
            zeroCounter++;
        } else if (zeroCounter !== 0) {
            nums[i - zeroCounter] = nums[i];
        }
    }
    for (let i = 0; i < zeroCounter; i++) {
        nums[nums.length - 1 - i] = 0;
    }
};
```

### 結果

Runtime：69ms
Beats 92.33%

Memory：54.96MB
Beats 70.77%
【Progate】Reactコースを終えての所感

## 自己紹介
29歳。文系卒。新卒入社でWebディレクターを２年半経験。
その後は番組の字幕制作の仕事に従事。
現在はエンジニア転職を目指して勉強中。

## Reactの印象
「JavaScriptのライブラリ」「便利」くらいしか知りませんでした。本コースではstateやpropsのあたりから理解が難しくなり、２周３周と学習を進めましたが、身についたとはとても言えない状態です。

コードを丁寧に追って処理の流れを読むことはできても、何も参考せずに実装しろとなればかなり厳しい…。

しかし、エンジニアを目指すのであればこのくらいの処理は完璧に理解したいところ。なので、いまいちピンとこない部分の解像度を上げるため、自分なりに整理することにしました。

## わからないこと一覧
* state
* props
* map

並べてみると少ないものですね。
使用例と一緒に整理していきます

## state
__ユーザーの挙動(クリックや入力)によって変わる値のこと。
stateの値で判定し、それに応じてJSXを表示させる。__
（例：モーダルウィンドウの表示、入力エラー文の表示）

~~~javascript
// 子コンポーネント

// stateの定義
constructor(props) {
    super(props);
    this.state = {state名:デフォルトの値};
}

// stateの取得
this.state.state名

// stateの変更
this.setState({state名:変更後の値})
~~~

__使用例__

~~~javascript
// 子コンポーネント

// stateを用意
constructor(props) {
    super(props);
    this.state = {state名:デフォルトの値};
}

// stateを変更するメソッドを用意
メソッド名(){
    this.setState({state名:変更後の値});
}

// JSX用の変数を用意
render(){
    let 変数名;
    ┇

    // 条件式を用意
    if(stateを利用した条件式){
        変数名 = (代入したいJSX)
    }else{
        変数名 = (代入したいJSX)
    }
    ┇
    
 
    return(
        ┇
        // メソッドを呼び出すイベントを設定
        <button onClick = {()=>{this.メソッド名()}}>
        
        // 表示させたい位置に変数(JSX)を挿入
        <div>{変数名}</div>
        ┇
        }
~~~

## props
__プロパティのこと。
コンポーネントごとに中身(テキストや画像)を変更したいときに設定する。
親コンポーネントから子コンポーネントに渡す。__
(例：〇〇の一覧画面、コンテンツ)

~~~javascript
// 親コンポーネント

// propsを渡す
<子コンポーネント名
    props名 = 値
    props名 = 値...
    />
~~~
~~~javascript
// 子コンポーネント

// propsの取得
// (これを文言やURLに挿入する)
this.props.props名
~~~

## map
__配列の各要素に対して順に処理を行う。
要素の異なる同コンポーネントが並ぶ場合に使用する。__

~~~javascript
// 親コンポーネント

// 配列オブジェクトと、その中身を定義
const 配列名 = [
    {プロパティ名:値,プロパティ名:値...}
]

// 「コンポーネントを呼び出してpropsを渡す」を
//  配列オブジェクトのすべてに対して行う。
{配列名.map((引数名)=>{
    return (
        <子コンポーネント名
            props名 = {引数名.プロパティ名}
            props名 = {引数名.プロパティ名}...
        />
    )}
~~~

## まとめ
自分は今、なんとなく理解している気になっている状態だと思います。
しかし、こうして整理する前の理解度と比べると、深まっていることは確かです。
こういったアウトプット(?)を繰り返して、きっと自らの土壌になっていくのでしょう。

今後も継続して学習を続けていきたいと思います。

間違いなどあればご指摘いただけますと幸いです。
Javaで「多次元配列の長さを取得する(length)」の動作を確認してみた

# 概要

Javaで「多次元配列の長さを取得する(length)」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/array/index9.html

# 実装

以下のファイルを作成しました。
```JSample9_1.java
class JSample9_1{
  public static void main(String[] args){
    int[][] num = {{87,54}, {76,92,48,58,84}};
    
    for (int i = 0; i < num.length; i++){
      for (int j = 0; j < num[i].length; j++){
        System.out.println("num[" + i + "][" + j + "] = " + num[i][j]);
      }
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample9_1.java 
$ java JSample9_1 
num[0][0] = 87
num[0][1] = 54
num[1][0] = 76
num[1][1] = 92
num[1][2] = 48
num[1][3] = 58
num[1][4] = 84
```

# まとめ

何かの役に立てばと。
GNU gforth マニュアル翻訳

# はじめに
謎の会社のジーフォースじゃ無い方の gforth です。

Gforth 0.7.9_20240418

2024/05/06 〜
2024/12/09 翻訳終了。未校正。
2024/12/22 HTML 1ページ表示版(texinfo --html --no-headers)
2025/01/25 第一次校正終了。

## status

`````
status by sentence: 11092+0f+0u
progress by sentence:11092/11092(100.00%)
progress by files: 2/2
2024年 12月  9日 月曜日 08:22:18 JST
`````


# 成果物
https://kuma35.github.io/gforth-docs-ja/

手元の環境では info (Emacs内のinfoビュワー)で確認していて、htmlはあんまりチェックしてないです。 

## info
info はリポジトリから持っていって下さい。 doc-ja ディレクトリにサンプルの dir を入れてあります。 gforth.info 内で gforth.info-1 〜 gforth.info-5 をインクルードしてるので注意。

## $tring words 
`$` を含んだセクション名は info では問題ないのですが。 html ではコケるので、 `$tring words` を `＄tring words` と ＄だけ全角に変更してあります(セクション名、ノード名、xprefのみです。本文中は `$tring words` のまま)。

# リポジトリ

https://github.com/kuma35/gforth-docs-ja
の docs-ja-0 ブランチをご覧ください。

# 試しに使ってみる
Docker バージョンがあります(詳しくは INSTALL.md 参照)

````
docker pull forthy42/gforth
docker run -ti --rm forthy42/gforth
````

# po4a-updatepo や po4a-translate から po4a + po4a.cfg に移行

翻訳に使っているツール po4a は、 Ubuntu 22.04LTS から 24.04LTS にアップグレードしたら po4a 0.69 になって、  po4a-updatepo や po4a-translate が非推奨(0.68から)になったので対応した。

非推奨ながらもまだ使えるので当面現行どうりでも構わないが、今後改良されていくのは po4a だけにするとあるので、改良された果実を得たいならば将来検討するいいかもしれません。私はウッカリ対応してしまったので下記に置いときます。

## 結論
翻訳ファイルごとにそれぞれ po4a.cfg を用意してください。 doc/foo.texi → doc-ja/foo.texi, doc/bar.texi → doc-ja/bar.texi ならば、 doc-po/po4a-cfg/foo.texi.cfg, doc-po/po4a-cfg/bar.texi.cfg を用意します。

詳しくは以下参照

https://kuma35-memo.readthedocs.io/ja/latest/po4a-cfg.html

gforth翻訳は上記のようにしましたが、 その後 git翻訳では Makefile で扱いやすいよう以下のようにしました

https://kuma35-memo.readthedocs.io/ja/latest/po4a-cfg-2.html

# その他

使っている Ubuntu 22.04 LTS に入っている gforth は

````
Gforth 0.7.3, Copyright (C) 1995-2008 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
````

help 入ってないです。


で、今回翻訳中のは
````
Gforth 0.7.9_20240418
Authors: Anton Ertl, Bernd Paysan, Jens Wilke et al., for more type `authors'
Copyright © 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `help' for basic help
````
## gforth.el
ファイル名(ベース名)は "gforth" で、 "gforth.el" 内では ````(provde 'forth-mode)```` なので、そのままでは Emacs が見つけられません。 対策として、例えば ````(require 'forth-mode "gforth")```` とします。
文字列Sを回転させて文字列T に一致させる方法

# atcoder問題文
https://atcoder.jp/contests/abc103/tasks/abc103_b

B - String Rotation  / 
実行時間制限: 2 sec / メモリ制限: 1024 MB

配点 : 
200 点

問題文
英小文字からなる文字列 S, T が与えられます。
S を回転させて T に一致させられるか判定してください。

すなわち、以下の操作を任意の回数繰り返して S を T に一致させられるか判定してください。

制約
2≤∣S∣≤100
∣S∣=∣T∣
S, 
T は英小文字からなる
入力
入力は以下の形式で標準入力から与えられる。
S T

出力
S を回転させて T に一致させられる場合は Yes、一致させられない場合は No を出力せよ。

# 回答
``` python.py
def strings_rotation(s: str, t: str) -> bool:
    if s == t:
        return True
    
    t2 = t + t
    rotation_find_index = t[1:].find(s[0]) + 1
    if rotation_find_index == -1:
        return False
    
    for i in range(1, len(s)):
        if s[i] != t2[i + rotation_find_index]:
            return False
    
    return True

s = input()
t = input()

if strings_rotation(s, t) or strings_rotation(t, s):
    print("Yes")
else:
    print("No")
```

回転させて一致するということはすべての回転させる文字の移動距離が同一になることになるのでその性質を利用して説くことができる。t2 = t + tのように文字列を結合しているのは末尾から先頭への移動する文字の比較を楽にするため。