OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】メンション付きコメントがあった際にメールで通知をする方法

## はじめに
Webアプリでよくある、@username　でメンション通知をできる機能を実装したので、やり方を残しておきます。

### 学べたこと
- `after_create`などのコールバックを使う際のデータの扱い方
- メールを送りたいときのメソッドの作り方
- 絶対リンクの作り方

## やりたいこと
ポストに対してのコメントで'@username'と記述した際にメンション通知を飛ばしたい。
メール送付は非同期処理で行いたい。

### 前提
- Redisとsidekiqを導入

## やり方
### 方向性
1. メンション通知用のメソッドをMailerを作って実装
1. viewの作成
1. `after_create`を使って、Commentモデル内にメール送付のメソッドを定義
    1. 保存したコメントの内容から'@'に反応してusernameを検知
    1. もしメンションされていたら、メールを送信

### Mailerの内容
```ruby
class CommentsMailer < ApplicationMailer
  def mention_notification(mentioned_user, comment)
    @comment = comment
    @mentioned_user = mentioned_user
    @post_url = post_url(@comment.post)
    mail to: @mentioned_user.email, subject: '【お知らせ】メンションされました'
  end
end
```
#### ポイント
##### 使われ方の想定
大前提からなのですが、このメソッドはモデルファイル（comment.rb）でafter_createの一部として、呼び出されることを想定しています。

##### 引数について
引数は、メールを送るため＋メール本文で使うために設定しています。
`mentioned_user`は`@username`でメンションされたユーザーを指しています。
送付先のメールアドレスを特定するために必要です。

`comment`は主にcommentの内容と、commentがついたポストへのリンクを生成するため引数に指定しています

蛇足ですが、メソッドや関数を作るうえで引数に何を設定したら悩むことが多かったのですが、このようにどういったデータを扱う必要があるのか、というところから逆算して設定するものなのだとはじめて腑に落ちました。

##### post_urlメソッド
post_url(モデルのインスタンス)でインスタンスまでのurlを簡単に作成できるメソッドです。
めっちゃ便利。覚えておこう。

### viewの内容
```ruby
%p #{@mentioning_user.username}さんがあなたをメンションしました
= @comment.content

= link_to '該当のポストはこちらから確認できます', @post_url,  target: '_blank'
```

#### ポイント
##### 内容について
メールを簡単に見ただけで必要な情報が載るように記述しました。
ポイントと言うほどでもないのですが。

### Commentモデルの内容
```ruby
class Comment < ApplicationRecord
  after_create :check_for_mentions

  private
  def check_for_mentions
    mentioned_usernames = content.scan(/@([^\s@]+)/).flatten
    mentioned_users = User.where(username: mentioned_usernames)
    mentioned_users.each do |mentioned_user|
      send_mention_notification(mentioned_user)
    end
  end

  def send_mention_notification(mentioned_user)
    CommentsMailer.mention_notification(mentioned_user, self).deliver_later
  end
end

```

#### ポイント
##### コメントの内容をどうやって扱うか
`content.scan(/@([^\s@]+)/).flatten`　は省略形で本来は`self.content.scan(/@([^\s@]+)/).flatten`となります。

この文脈だとselfは作成されたcomment（インスタンス）を指しています。
なのでcontent以外のカラムも取ろうと思えば取れます。

##### @以下がusernamなのかどう判定するか？
まずは、@以下を適切な単位で取得するため、正規表現を使います。
`.scan(/@([^\s@]+)/)`
正規表現はAIに任せてしまったのですが以下の意味になるようです
- `＾`は否定
- `\s`は空白
- `@`はそのまま@

つまり空白や@ではないすべての文字をという意味になります。
なので、ユーザーが良心的で@usernameの後ろにスペースを入れてくれたら適切にメンションできますが、"@usernameいいね！"のように空白がないとうまく取得できなくなってしまいます。

これは今後の改善点です…

次に以下で取得した@以下の文字列がusernameなのかを確認しています。
`User.where(username: mentioned_usernames)`

whereを使っているのがポイントで、複数人へのメンションにも対応でき、@がメンションではない形で使われていた場合でもエラーが出ません。

##### どうやってメールを送るのか
取得したメンションされたユーザーの配列を以下で取り出して、一人ずつメールを送ります。
```ruby
    mentioned_users.each do |mentioned_user|
      send_mention_notification(mentioned_user)
    end
```
`send_mention_notification`は別途下記のように定義します。
```ruby
  def send_mention_notification(mentioned_user)
    CommentsMailer.mention_notification(mentioned_user, self).deliver_later
  end
```
Mailerで作った`mention_noteificationに引数を渡しています。
また`.deliver_later`とすることで非同期処理で送付しています。

これでコメントにメンションがあれば、自動でメールが送付されます！

## おわりに
とりあえず実装はできましたが、メール送付までやたら時間がかかるので、別途リファクタリングを行おうと思います。
この辺のパフォーマンス改善については知見が0なので勉強しよー
ビジネスフレームワークを学んだので自分のオリジナルアプリを分析してみた



## はじめに
今日は、ビジネスに役立つ「ビジネスフレームワーク」ってものを学びました。その中でも、事業を視覚的に整理できる「ビジネスモデルキャンバス」ってツールが面白くて、これを使って自分のアイデアをAIで分析してみました。  
この記事では、僕が考えているオリジナルのフリマアプリ「wants」を、このビジネスモデルキャンバスで分析してみた結果をシェアしてみます！

#### ビジネスモデルキャンバスって何？
ビジネスモデルキャンバスは、事業を9つの要素に分けて整理するツールです。これを使うと、ビジネスの全体像がスッキリ見えて、どこを強化すればいいのかが分かりやすくなるんです。  
基本的にはこんな感じで整理されます。

1. **顧客セグメント**: 誰に価値を提供するのか
2. **価値提案**: どんな価値を提供するのか
3. **チャネル**: どうやって価値を届けるのか
4. **顧客関係**: 顧客とどんな関係を築くのか
5. **収益の流れ**: どうやって収益を得るのか
6. **主要資源**: ビジネスを支えるリソースは何か
7. **主要活動**: どんな活動を行うか
8. **主要パートナー**: 誰とパートナーを組むか
9. **コスト構造**: どんなコストがかかるか

これらを一枚のキャンバスにまとめて、ビジネスの全体像を整理するってわけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/ba20459c-043f-6ab0-8a7a-9ba06f3856d2.png)


#### 僕のアプリ「wants」とは？
「wants」は、ちょっと普通のフリマアプリとは違うコンセプトで作ったアプリのアイデアです。一般的なフリマって出品者が商品を出して、それを購入者が探して買う形だけど、「wants」はその逆です。購入者が欲しいものをリクエストして、それに応じて出品者が出品する、っていう仕組みになります。  
いわば、オークションとフリマの中間みたいなアプリです。

- **購入者**は、売り切れの心配なく欲しいものをリクエストできる。
- **出品者**は、需要があることを確認してから商品を出品できる。
- **企業**は、リクエストデータから市場のニーズを分析して商品開発に役立てることができる。

#### wantsのビジネスモデルキャンバスをAIで作ってみた
それでは、wantsをビジネスモデルキャンバスを使って整理してみた結果を紹介します！

---
#### プロンプト

:::note info
メルカリの競合としてフリマアプリの「wants」を作ろうと思います。
wantsは商品を欲しいと思った人が出品依頼を投稿し、その投稿に応じて希望者が出品するというオークションとフリマの中間のようなアプリです。
これにより出品者は需要がある商品を出品できる利点、購入者は随時アプリを見なくても売り切れの心配がない、企業としてはどのような需要があるかを分析するのに利用できるという利点があると思います。

wantsのビジネスについて、ビジネスモデルキャンバスのフレームワークに沿って提案してください。
:::
---
### 出力結果

##### 1. **顧客セグメント**
- **購入者**：手に入らない商品や限定品を探してる人たち。特にレアなものを探してる層。
- **出品者**：需要がある商品を確実に売りたい個人やビジネス。
- **企業**：ユーザーのリクエストを分析して、商品開発やマーケティングに活かしたいメーカー。

##### 2. **価値提案**
- **購入者向け**：欲しい商品をリクエストできて、売り切れを心配しなくて済む。
- **出品者向け**：確実に売れる商品を出品できるので、在庫リスクが減る。
- **企業向け**：ユーザーのリクエストデータを基にニーズを分析できる。

##### 3. **チャネル**
- **アプリ**と**ウェブサイト**が主なプラットフォーム。ユーザーはここでリクエストを投稿したり、出品者は商品を出品できる。
- **SNS**でトレンド商品やリクエストをシェアして拡散、集客。

##### 4. **顧客関係**
- **評価システム**でお互いの信頼を高める。
- **個別通知**で、リクエストに対して出品があった時に購入者に知らせる。
- **カスタマーサポート**でトラブル対応。

##### 5. **収益の流れ**
- **取引手数料**：出品者が商品を売ったときに手数料をもらう。
- **有料オプション**：リクエストを目立たせるための有料プランを提供。
- **広告**：企業がリクエストデータを基に出稿する広告収入。
- **データ提供**：企業にリクエストデータを提供して収益化。

##### 6. **主要資源**
- **アプリ**と**ウェブプラットフォーム**。ここがビジネスの基盤。
- **リクエストデータ**と**分析システム**。これが企業向けの価値を生み出す。
- **ユーザーベース**が重要。多くのユーザーがリクエストと出品をすることが成功の鍵。

##### 7. **主要活動**
- **プラットフォームの開発と運営**。
- **マーケティング**での新規ユーザー獲得。
- **データ分析**を活用した企業向けサービスの展開。

##### 8. **主要パートナー**
- **配送業者**：スムーズな配送体制を確保するために提携。
- **決済サービス**：安全な支払いのために外部プロバイダーと提携。
- **企業**：リクエストデータを利用して商品開発やマーケティングに役立てる企業との連携。

##### 9. **コスト構造**
- **開発・運用コスト**：アプリやウェブサイトの維持費。
- **マーケティングコスト**：新しいユーザーを集めるための広告費。
- **カスタマーサポート費用**やデータ分析の運用費。


![Colorful Modern and Friendly Rounded Business Model Canvas Brainstorm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/c8095d7c-23a6-be9e-0047-bfa3aa34c08a.png)
#### まとめ
「ビジネスモデルキャンバス」を使って、自分のアプリを分析してみると、ビジネスのどこに強みがあって、どこを改善すればいいのかが見えてきました！特に「価値提案」と「顧客セグメント」の整理が、自分のビジネスを明確に理解するのに役立ちました。  
まだまだ学びの途中ですが、こういったフレームワークを活用して自分のアイデアを成長させていくのが楽しくて仕方ありません。みなさんも、ぜひビジネスモデルキャンバスを使って、自分のプロジェクトを分析してみてください！
Node-RED Raspberry Pi

自社製品でNode-RED搭載のものを検討していると聞いたので
ラズパイにNode-REDを入れて動かすことにした。
ラズパイとWindowsに入れてNode-RED同士でも動くか試してみたいがとりあえずラズパイで試す。
最後はCODESYSと合わせて使ってみようと思う。
# 環境
Node-RED v4.0.3
Node.js v20.17.0
Linux 6.6.31+rpt-rpi-v8 arm LE


# Node-REDの追加
前は標準でインストールされていたけど今はインストールされていないようなので、
参考URLのRaspberry Pi OSへのNode-REDのインストールに記載されている短縮URLを使用させて頂きインストールを行った。
コンソールでnode-red-startを実行した所簡単に起動した。
感謝
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852763/1c86df8c-0fc0-3ad5-9a13-e471dd5275b1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852763/b2761dad-8f16-2dc6-cc3d-6b743e07868d.png)

# パレットの管理
パレットの管理でdashboardというのを追加した
（使うかわからないが）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852763/34e32eb6-2193-f31f-38d0-bb349f27b34b.png)

# 動作確認
タイムスタンプを定周期で繰り返して
テキストとゲージに表示するUIを設定してみた。
ローカル:1880/uiにアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852763/ef147aab-bc51-0e63-f941-60d9f7a8cf02.png)

ゲージは2024が表示されただけだけど、テキストは時間が進むと増えるのでヨシ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852763/1acc89c0-fdb4-804c-bd40-a9e823053886.png)




# 参考にした書籍・URL
https://qiita.com/utaani/items/7155c62d6c5e96822afb

https://gihyo.jp/book/2021/978-4-297-12052-8
JavaScriptのcallメソッドについて勉強してみた

タイトルの通り、JavaScriptのcallメソッドについて学んでみました。

以下、MDNからの引用です。

> call() はあるオブジェクトに所属する関数やメソッドを、別なオブジェクトに割り当てて呼び出すことができます。
参考:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call

これだけだとわかりづらいので、filterメソッドを例を挙げてみます。

filterメソッドは、対象の配列の各要素に対してコールバック関数を実行し、条件を満たす（コールバック関数がtrueを返す）要素だけを抽出した新しい配列を返します。

通常、このfilterメソッドは配列にしか使用できません。

例えば、querySelectorAll() メソッドで取得したNodeListに対して、filterメソッドやmapメソッドなどを使用することはできません。NodeListに対してforEachやlengthは使うことができますが、配列に使用できるメソッドをNodeListに使うことはできないのです。

しかし、callメソッドを利用することで、このNodeListに対しても(少々強引に)filterメソッドを使うことができます。

callメソッドの構文は以下のようなイメージです。

```JavaScript:callの構文
使いたいメソッドを持っているオブジェクト.使いたいメソッド.call(thisの参照先, 使いたいメソッドに渡す引数1, 引数2, 引数3, …)
```

わかりやすい解説をされている方がいたので、こちらもご紹介させていただきます。

>あっちのオブジェクト.あっちのメソッド.call(こっちのオブジェクト, あっちのメソッドに渡す引数);
参考:
https://qiita.com/Chrowa3/items/b3e2961c4930abc1369b

```JavaScript:例
const divs = document.querySelectorAll('div');

// NodeListに対してfilterを使えない場合
const hogeElements = divs.filter(element => element.classList.contains('hoge'));

// NodeListに対してfilterを使える場合
const hogeElements = Array.prototype.filter.call(divs, element => element.classList.contains('hoge'))
```

つまり、上記の例ではcallメソッドによって、

<b>Arrayオブジェクト内にあるprototypeのfilterメソッドを、NodeList(が代入された変数divs)のメソッドであるかのように扱う</b>

といったことを実現できています。

（prototypeはJavaScript独自の継承の仕組みのことです。こちらについても説明すると長くなるので省略します）

このように、callメソッドを使うことで、あるオブジェクトのメソッドを任意のオブジェクトのメソッドであるかのように利用することができるよ、ということを学びました。
Raspberry PiのUbuntu 22.04 LTSでホスト名を変更できない事象の解決方法

# 起きたこと

```
sudo hostnamectl set-hostname <新ホスト名>
```

でホスト名を変えてみたものの、再起動するとホスト名が変更前に戻ってしまう。

# 解決方法

`/boot/firmware/user-data`にある`hostname`の値を`<新ホスト名>`に変更して保存し、再起動する。


```:/boot/firmware/user-data
hostname: <新ホスト名>
...
...
```

この方法で新しいホスト名を使えます🎉

ちなみに、`/etc/hosts`も起動時に自動で変更してくれます。
「databinding」でエラーになる

Androidアプリ開発中にdatabindingでエラーになった。
ナレッジとして記述する。以下のようなimport文でエラーが起きたことを想定。

```ruby:MainActivity.kt

import com.tapps520.app.databinding.FragmentAboutBinding

```

Gradle Scripts内の

```ruby:build.gradle.kts (Module:app)

android {
    
    // 以下を追加する
    buildFeatures {
        viewBinding = true
        //noinspection DataBindingWithoutKapt
        dataBinding = true
    }

}

```
上記のようにして、Syncを実行して改善されたことを確認する。
【Git】git stash の使い方

## Git Stashとは

`git stash`は変更を一時的に退避するためのコマンドです。

https://git-scm.com/docs/git-stash

## 基本的な使い方

### 変更をスタッシュする

作業中の変更を一時退避するには、以下のコマンドを実行します。

```terminal
git stash
```

これにより、現在の変更が一時退避され、作業ディレクトリがクリーンな状態に戻ります。

### スタッシュの一覧を表示する

スタッシュした変更の一覧を表示するには、次のコマンドを使用します。

```terminal
git stash list
```

これにより、スタッシュされた変更のリストが表示されます。各スタッシュには、`stash@{0}`、`stash@{1}`のような識別子が付与されます。

### スタッシュを適用する

スタッシュした変更を再適用するには、以下のコマンドを使用します。

```bash
git stash apply
```

特定のスタッシュを適用したい場合は、識別子を指定します。

```bash
git stash apply stash@{0}
```

### スタッシュを削除する

スタッシュを削除するには、次のコマンドを使用します。

```bash
git stash drop stash@{0}
```

すべてのスタッシュを削除するには、以下のコマンドを使用します。

```bash
git stash clear
```
左手親指の手の平側を15針縫った場合に事務系会社員は仕事ができるか？

結論：
　出来る

この記事の想定読者：
　左手親指の手の平側の手術を控えていて業務に支障がないか怯えている事務系会社員(主に毎日キーボード叩いてる人)

詳細：
　左手親指の手の平側の付け根に鋭角な物(茶碗のふち等)が当たると、痛みがあり、日々ストレスを感じていた。検査の結果、異物除去の為の手術をするしか回復方法がなかったが、日々の業務や自己学習などでPCを触らない日はないので、術後の生活に支障が出ることを心配し、手術日を先延ばしにしていた。
　しかし、とある理由で急遽手術を行った為、その結果を共有したい。
 
　まず、しっかり縫われていて、包帯巻かれていればキーボードのタイピングは手術した指でも可能である。安心してほしい。もちろん当日は手の平の局所麻酔と腕自体の神経ブロック麻酔の為に肩から下はほとんど動かせないが、次の日からは通常業務可能だと思われる(車も運転できる)。痛みもタイピング程度では全くない(人によるとは思うが)。

 以上、安心して左手親指の手の平側の手術を行って頂きたい。

 ちなみに抜糸までは2週間であった。
【jQuery】 DataTablesでnullとrenderオプションを使って、複数のフィールドの値を組み合わせて表示する方法

# 概要
jQueryのDataTablesの`render`オプションを使用して、複数のフィールドを連携して表示するよう実装しました。使い方について説明します。

# サンプルコード
以下のように`render`関数を使用して、`condition1`、`condition2`、`condition3`の値を連結して表示することができます。
`data`にはバックエンド側からデータが連携される前提です（私はdjangoを利用しました）。

```js
$(document).ready(function () {
    var RenderTable = function (data) {
        var table = $('#sample_table').DataTable({
            "language": {
                "url": "//cdn.datatables.net/plug-ins/3cfcc339e89/i18n/Japanese.json"
            },
            //  略 
            data: data,
            columns: [
                {
                    "data": null,
                    "title": '連結名',
                    "render": function (data, type, row) {
                        return row.condition1 + ' ' +
                               row.condition2 + ' ' +
                               row.condition3;
                    }
                },
                //  略 
```

ポイントは、`"data": null:`を設定することによって、`render`関数内で`row`オブジェクト全体にアクセスできるようになり、また値を自由にカスタマイズできること。`null`になっているので、特定のキーに依存せず、この関数内で自由にデータを組み合わせて表示することができるようになるのです。

公式ドキュメントにも以下のように記載されています。

> Functions
Using columns.render is the most common method as it provides absolute control over the data that will be displayed to the end user (this is a regular Javascript function, so you can do virtually anything you wish with the data).
>
> The function is passed in three parameters:
>
> 1. The data that is pointed to by columns.data. If columns.data is null, null will be the value given here.
> 2. The data type being requested by DataTables - this allows the function to support orthogonal data.
> 3. The original and full data object or array for the row.

「`If columns.data is null, null will be the value given here.`」と記載されているように、`null`としておけば`render`の結果が入るようになっています。

https://datatables.net/manual/data/renderers

上記のようにすることで、複数のフィールドの値を組み合わせて1つのセルに表示することができました。
より柔軟に表記を変えることができて良いですね。
M5Stamp S3、Grove- I2C ADCで遊ぶ(ADC121C021)





参考

![o_coq422.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/636f3d52-2be7-1d05-e324-2568ba360d1f.jpeg)


https://qiita.com/caa45040/items/87439565c1b58fd0a6d3

結果

![o_coq438.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2edfffaa-7edf-7fb0-b10d-1608f909293c.jpeg)

![o_coq439.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4b0fb72a-f621-f318-ecc2-55463ad73677.jpeg)


![o_coq437.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/16347ce2-1fa9-a324-0eb8-4aad3b6104ce.jpeg)




プログラム


```c++


//Grove_ADC_test1_S3_1


//インクルド
#include <Arduino.h>
#include <Wire.h>


//I2Cのアドレス
#define Addr 0x50


//初期化
void setup() {

  //I2Cとシリアルポートの初期化
  Wire.begin();
  Serial.begin(9600);
  delay(1);

  //初期化(高速変換)
  //Wire.beginTransmission(Addr);
  //Wire.write(0x02);//CONFIG
  //Wire.write(0x20);
  //Wire.endTransmission();
  //delay(2);

}//setup


//メインループ
void loop() {

  //内部アドレスの設定
  Wire.beginTransmission(Addr);
  Wire.write(0x00);
  Wire.endTransmission();
  delay(2);

  //データの読み込み
  Wire.requestFrom(Addr, 2);
  delay(1);
  int h, l;
  if (Wire.available() == 2) {
    h = Wire.read();
    l = Wire.read();
  }//endif

  //値の表示
  int adc1 = ((h & 0x0F) << 8) + l;
  int vo = (adc1 * 6000) >> 12; // (adc1*(3/4096))*2
  Serial.print(adc1);
  Serial.print("count");
  Serial.print('\t');
  Serial.print(vo);
  Serial.print("mV");
  Serial.println();
  delay(50);

}//loop




```
git fast-forward、non-fast-forwardの違い

# 背景
mergeのfast-forwardとnon-fast-forwardをなんとなく行ってきたので、
明確に覚えたいため調査した。

# 目的
どのような時がfast-forwardになり、どのような時がnon-fast-forwardになるか理解する。

# 結論
マージ元のブランチに修正が
ないとき　→　fast-forward
あるとき　→ 　non-fast-forward

※ 実際の業務の例だと、マージ元のブランチ(masterなど)からfeatureブランチを切ったときに、origin/masterに他の人から修正がない場合、ある場合ということ。

#  検索して調べた内容

### fast-forward:早送りマージ
- git mergeするとデフォルトでfast-forwardになる。
```git 
git merge --ff feature
```
- fast-forward-mergeが可能なのは、現在のブランチが他のブランチの履歴の延長線上にある場合のみ。この場合、現在のブランチのポインタを他のブランチの最新コミットに移動するだけでマージが完了する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644072/74fcf0e2-59ef-1c5b-dfcc-6dbdff33ee23.png)

### non-fast-forward
- commitオブジェクトを作成する
- マージ元のブランチ(master、developなど)に変更があるときに実行される

```git 
git merge --no-ff feature
```

# gitで実践
featureブランチをdevelopブランチにマージしたい、という前提で確認。

## fast-forward
fast-fowardはマージ元のブランチに変更がない時に使用する。

gitgraph　fast-forward-merge前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644072/7c9da0c7-7b43-e2c2-be53-57b52acb405f.png)
gitgraph　fast-forward-merge後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644072/b61cdbe1-dc74-efef-9cbb-4675d339f7bb.png)

画像の通り、developのbranchリファレンスが移動するだけとなっている。

## non-fast-forward マージ元のブランチに変更があり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644072/7a130055-8527-385c-90a3-a8277b9a2c21.png)
↓ deveop に feature-1 を non-fast-forward merge
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644072/5a14bfdd-b90d-2a53-fb1a-d0c0cce99002.png)

画像の通り、新しいコミットオブジェクトを作成し、developリファレンスが移動することで、mergeされている。feature側のブランチがそのまま残るため、featureを確認しやすい。

## non-fast-forward マージ元のブランチに変更がなし(実際はほぼない)
通常fast-forward mergeできるところで、non-fast-forward mergeを行ってみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644072/0e9b2465-c7be-57e3-5fdd-c6fee1c4969e.png)

画像の通り、新しいコミットオブジェクトを作成している。
最後のmergeコミットは、feature-1ブランチで加えられた hello_world add 2,3,4の内容を、
developに取り込む内容となっている。

## 学び
- fast-foward merge : 新しくcommitオブジェクトを作成せず、リファレンスを移動させるだけのため、早送りマージと呼ばれる。developはfeatureと同じ履歴を辿る。
- non-fast-forward merge : 新しくcommitオブジェクトを作成する。featureの内容を最後にまとめてdevelopに加えている。

## 次のアクション
git revert も同様に調べる。
コンフリクト時のgitの動きも知りたい。
Photon FusionのIsSharedModeMasterClientは受け渡せない

# 結論
IsSharedModeMasterClientを意図的に他のプレイヤーに受け渡すことができません。今後に期待です。

https://x.com/PhotonCloudJP/status/1805150107454833122

# やりかったこと
IsSharedModeMasterClientの権限が無いと、ルームのCloseができません。ルームに入室している特定のグループだけがCloseするようにしたかったので、該当グループでないユーザがIsSharedModeMasterClientの権限を持ってしまった場合（例えば該当グループでないユーザ以外が全員退室した場合）、その後どこかのタイミングで受け渡したかった。

# プログラム的には
NetworkRunnerにはSetMasterClientというメソッドがあるので一見できそうなのですが、このメソッドを呼んでも設定変更されません。

```csharp
networkRunner.SetMasterClient(playerRef);
```

# その他
```csharp
/// 確認用に出したログ、NetworkBehaviourを継承しているクラスで出力できます。
/// よくわからなくなった時に見てみると権限周りで足りないものがわかるかもしれません。
private void CheckPropertyValues()
{
    Debug.Log($"HasInputAuthority = {HasInputAuthority}");
    Debug.Log($"HasStateAuthority = {HasStateAuthority}");

    Debug.Log($"Runner.IsClient = {Runner.IsClient}");
    Debug.Log($"Runner.IsPlayer = {Runner.IsPlayer}");
    Debug.Log($"Runner.IsServer = {Runner.IsServer}");
    Debug.Log($"Runner.IsSharedModeMasterClient = {Runner.IsSharedModeMasterClient}");

    Debug.Log($"Runner.IsResimulation = {Runner.IsResimulation}");
}
```
Azure AI Studioを使ってみた感想

何年ぶりかにAzure触りました。少し気になっていたAzure AI Studioを使った感想です。数時間試した程度で約32円かかりました。駄菓子１つくらい分ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/9854e1e0-7b56-bdfc-f432-1e30820414be.png)


# やったこと
以下のクイックスタート/チュートリアルで気になった点を動かしています。

https://learn.microsoft.com/ja-jp/azure/ai-studio/quickstarts/get-started-playground

https://learn.microsoft.com/ja-jp/azure/ai-studio/tutorials/deploy-chat-web-app

ローカルのターミナルでLLMへプロンプトを投げてみたり、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/2369adb2-b138-d739-fd21-aa5bda49c2c7.png)

プレイグランドでRAGを実行したり、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/1b23532d-09b3-2f02-5534-528ad64eaec8.png)

Web上にアプリをデプロしたりしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134273/e1ea26e7-e181-2a62-c6b7-614457d92fca.png)

# 感想
## 良かった点
### UX
"Studio"と名前がついている通り、1箇所でAI/ML系の作業ができるようにしてあり、操作性が良いと感じました。

### モデルの豊富さ
OpenAIのGPT系はもちろん、Hugging Faceからもモデルが使えるのが嬉しいです。

### RAGが比較的簡単
Naive RAG であれば非常に簡単に実装できます。コーディングできる人はLangChainなど使って実装すればいいと思いますが、非技術者でもやりやすいのでは。一方で、当然ですが複雑なRAGはやはりプログラムで組まないと駄目ですね。

## 改善点
### API-Versionがわかりにくい
AI Studioというより、ドキュメントについてですが、API-Versionに何を入れたらいいのかわからず、30分ほどつまづきました。gpt-35-turboだったら`2023-03-15-preview`が正解でした(どうやって見たか忘れました)。

https://learn.microsoft.com/ja-jp/azure/ai-studio/quickstarts/get-started-code?tabs=macos#configure-your-environment-variables

### Web Deployで失敗
Web Deployで失敗して1時間くらい？状態でした。Freeを使ったのが悪いかも、と思いStandardにしたら成功。Freeが原因だったか細かく見る時間とっていません。
ManjaroLinux(ArchLinux) paruとyayの自動インストール

ManjaroLinuxの仮想環境を全自動で作る、というのにはまってます。しかしyayとparuのインストールでは`makepkg -si`のあとであれこれユーザー入力が必要なのでこのままでは自動化できない！と嘆いていました。

けれど、世の中には同じことをすでに実現してくれている先輩がいて、ばっちり自動化できました。

```bash
    # install AUR packager
    pacman -S --noconfirm fakeroot binutils make gcc
    
    ##  Set up passwordless-sudo for the aur helper account
    printf "aur   ALL = (root) NOPASSWD: /usr/bin/makepkg, /usr/bin/pacman" > /etc/sudoers.d/02_aur
    useradd -m aur || true
    
    ## Install package-query
    su - aur -c bash -c 'rm -rf /tmp/package-query ; mkdir -p /tmp/package-query ; cd /tmp/package-query ; wget https://aur.archlinux.org/cgit/aur.git/snapshot/package-query.tar.gz ; tar zxvf package-query.tar.gz ; cd package-query ; makepkg --syncdeps --rmdeps --install --noconfirm'
    rm -rf /tmp/package-query

    ## Install yay and paru
    su - aur -c bash -c 'rm -rf /tmp/yay ; mkdir -p /tmp/yay ; cd /tmp/yay ; wget https://aur.archlinux.org/cgit/aur.git/snapshot/yay.tar.gz ; tar zxvf yay.tar.gz ; cd yay ; makepkg --syncdeps --rmdeps --install --noconfirm'
    rm -rf /tmp/yay
    su - aur -c bash -c 'rm -rf /tmp/paru ; mkdir -p /tmp/paru ; cd /tmp/paru ; wget https://aur.archlinux.org/cgit/aur.git/snapshot/paru.tar.gz ; tar zxvf paru.tar.gz ; cd paru ; makepkg --syncdeps --rmdeps --install --noconfirm'
    rm -rf /tmp/paru

    userdel -rf aur
```

参考：[Arch Linux yay scripted installation - Will Haley](https://www.willhaley.com/blog/2023-04-08-arch-linux-yay/)

Ansibleにはyayパッケージがあるからこんなことしなくてもよいのかもしれないです。けど、ManjaroLinuxはよくわからないのでまずはshellで動くのを確認中です。

ArchLinuxは公式ドキュメントが情報過多でつらいので諦めました、、、
VSCodeで開いているWSL2からPowerShellを開きたい

## きっかけ
TauriっていういろんなOSに対応した、デスクトップアプリケーションフレームワークを使ってWSL2上でお遊びのツールを作っていたときに、Windowsでも動作確認したいときがあって、PowerShellを別のウインドウで開くのは邪魔だなぁと感じていました。
あと、モニター1枚にしたことでアプリウインドウ間の移動をAlt + Tabとかでやっていてウインドウは少ないほうがいいので、なにかいい方法ないかなぁと探していました。
普段このレベルのことは記事にしないけれど、ChatGPTでもちょっと手こずったのと、記録用で。

## やり方
以下の設定をVSCodeの設定ファイルに追記。
```
"terminal.integrated.profiles.linux": {
    "PowerShell": {
      "path": "powershell.exe",
      "args": ["-NoExit", "-Command", "cd $HOME"]
    }
  }
```

"terminal.integrated.profiles.linux"の部分は、linuxをwindowsに置き換えたらWindowsでVSCodeを開いたときの構成を変えられる。

"PowerShell"は多分、名称。

"path"はファイルパス。WSL2からだとpowershell.exeって書くだけで開ける。ちなみにターミナルでこれを打つとPowerShellを開ける。

"args"は詳細を確認してないけど、これを書くことでPowerShellを通常Windowsで開くときのホームディレクトリに移動してくれる。これがないとWSL2の作業ディレクトリで開かれてしまう。

## ちなみに
他のLinuxで使う予定が今のところないので、VSCode本体の設定ファイルに追記したけど、WSL2上でだけ設定を使いたい場合はWSL2上の設定ファイルに書いたほうが良いと思う。

[公式ドキュメント](https://code.visualstudio.com/docs/terminal/profiles)
投稿81 pythonについて 2024/09/19

本日の勉強時間　5H

Python（パイソン）は、オープンソースのプログラミング言語で、次のような特徴があります。﻿
シンプルで読みやすい構文﻿
効率的なデータ構造とオブジェクト指向プログラミング機構を備えている﻿
豊富なライブラリやフレームワークが利用できる﻿
大規模な開発者コミュニティが存在する﻿
Pythonは、数値計算、Webアプリ開発、AI開発など幅広い用途で利用されており、次のようなことが可能です。
機械学習
画像認識
自然言語処理
時系列解析
データ収集
データ処理・分析
ブロックチェーン開発﻿
Pythonは、科学技術分野向けのライブラリが多く提供されているため、難解な計算処理を簡単に実行できます。また、データ分析では自由度が高く、大規模なデータでもスムーズに処理できるというメリットがあります。﻿
Pythonは、ネット環境とPCさえあれば誰でも無料で使用できます。﻿
マネージドIDでAzureFunctionsのキュートリガーを動かしたメモ

#  概要

[前前回](https://qiita.com/hibohiboo/items/e3050de912c9e608cba0)はマネージドIDを使ったblobコンテナおよびキューへのアクセスを行った。[前回](https://qiita.com/hibohiboo/items/95bb4782c5f04d449ef0)は接続文字列でキュートリガーを行った。

今回はマネージドIDでキュートリガーを動かす。

[ソースコード](https://github.com/hibohiboo/async-ttrpg/tree/d9f62208a51f3a06a1578857251dab6324075f8a)

# 環境変数の設定
[公式](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-storage-queue-trigger?tabs=python-v2%2Cisolated-process%2Cnodejs-v4%2Cextensionv5&pivots=programming-language-typescript#identity-based-connections)のID ベースの接続を参照に設定する。

```diff:infra/biceps/core/host/functions.bicep
param queueAndContainerStorageAccountName string
var environments = [
  {
    name: 'DATABASE_URL'
    value: databaseUrl
  }
  {
    name:'CONNECTION_STRING'
    value: connectionString
  }
-   {
-     name: 'BLOB_QUEUE_STORAGE_ACCOUNT_CONNECTION_STRING'
-     value: 'hoge'
-    }
     
+  {
+    name: 'BLOB_QUEUE_STORAGE_ACCOUNT__accountName'
+    value: queueAndContainerStorageAccountName
+  }
+  {
+    name: 'BLOB_QUEUE_STORAGE_ACCOUNT__queueServiceUri'
+    value: 'https://${queueAndContainerStorageAccountName}.queue.core.windows.net'
+  }
  ...functionEnvironments
]
```

```diff:apps/api/src/functions/queueTrigger.ts
import { app, InvocationContext } from '@azure/functions';

export async function storageQueueTrigger1(
  queueItem: unknown,
  context: InvocationContext,
): Promise<void> {
  context.log('Storage queue function processed work item:', queueItem);
  context.log('expirationTime =', context.triggerMetadata?.expirationTime);
}

app.storageQueue('storageQueueTrigger1', {
  queueName: 'character-queue',
-  connection: 'BLOB_QUEUE_STORAGE_ACCOUNT_CONNECTION_STRING',
+  connection: 'BLOB_QUEUE_STORAGE_ACCOUNT',
  handler: storageQueueTrigger1,
});
```
【自己学習用】AWSについて

## きっかけ
社長へ現在の業務から「インフラエンジニア」をチャレンジしたいとコミットしたところ
「できそうな業務探してくる」と返事をもらえました。

でも、ただ待つよりは何かスキルアップした状態で、インフラエンジニアの世界に飛び込みたいと思い、
AWSクラウドプラクティショナー等、資格取得を目指したのがきっかけです。

１か月後を目標に資格試験を受けたいと思います。

## 期間
2024/10/19付近で資格試験を受けようと思います。

## AWSとは

Amazonが提供するクラウドコンピューティングサービスの総称
企業や個人がインターネットを通じてコンピュータリソース（サーバー、ストレージ、データベース、ネットワーキング、AI、機械学習など）を利用できるように提供している｡

### 主な特徴
■ クラウドベースのサービス
1. オンプレミス（理的なサーバーを所有・運用する）ではなく、インターネット経由でAWSのクラウドインフラを利用できる｡
2. 世界中に分散されたデータセンターで稼働しているため、ユーザーは必要に応じてリソースを柔軟に追加・削減できる｡

■ スケーラビリティと弾力性
1. 使用したいリソースを簡単にスケールアップ・ダウンできる｡
需要に応じて自動的にリソースを調整することも可能。

■ コスト効率
1. 従来のオンプレミス環境に比べて、AWSは初期投資が不要で、**従量課金制（使った分だけ支払う）**を採用しているため、コスト管理がしやすい｡

■ セキュリティと信頼性
1. AWSは強力なセキュリティ機能を備えており、データの暗号化、アクセス制御、監査機能などが用意されています。また、高可用性を保証するために複数のリージョンやゾーンでサービスが冗長化されています｡
[読書メモ]　入社1年目の教科書

内定先企業から課題図書をいただいたので、この機会に技術書(広義)に関する読書メモはQiitaで一括管理してみようと思います。
# 入社1年目の教科書

- **著者**: 岩瀬大輔
- **出版社**: ダイヤモンド社
- **出版年**: 2011年05月
- **読書期間**: 2024/09/19 ~ 

---

## 1. 概要
新社会人あるいは転職一年目の人間が持つべきマインドセット、およびそれを具体的なやり方に落とし込んだ処世術のようなものが箇条書きで書かれている

---

## 2. 目次

- 第1章: 仕事においての3つの原則
- 第2章: 仕事のやり方1~15
- 第3章: 仕事のやり方16~29
- 第4章: 仕事のやり方30~43
- 第5章: 仕事のやり方44~50

---

## 3. 重要そうなポイント

### 第1章
- 頼まれたことは必ずやり切る
- 50点でいいから早く出す
- つまらない仕事はない

### 第2章
- 仕事がつまらなく感じるのはなんのためにやっているのか、そもそも何をやっているのかがわかっていないからの場合が多い
- わかった上でもつまらないなら次のその作業のために仕組み化することでつまらなさを逓減する
- 最後の五分で合意した内容を確認し、書き出す
- 完成度が低くてもいいから機会があれば積極的に取り組み、そこでのフィードバックを経験としてストックする
- 仕事を通じて私個人の物語を作りながら働くことで納得感を持ちながら働くことができる

### 第3章
- 仕事はまねること、盗むことで身につく
- 情報収集は参考文献を辿って原典にあたること
- 全社的な目標に自分の仕事が貢献できるかを意識
- 新聞は2紙以上紙で読め


### 第4章
- 仕事に関係のない人とランチせよ
- ミスをしたら再発防止の仕組みを考えよ

### 第5章
- どこに集中のピークをもっていくかというペース配分の重要性
- 貯蓄→ある程度まとまった資産→それをどう活用するかという視点が生まれる

---

## 4. 感想・考察

- 形式知と暗黙知の蓄積および暗黙知を形式知化する心持と具体的な施策について書かれている本だと読み取った。
- 一次情報や新聞から形式知を収集し、現場に出て上司とコミュニケーションを取る中で暗黙知を蓄積していく。それを円滑に進めるために、心身の健康管理、好かれる人になる努力、相手を尊敬することが重要。そして日々の復習と言語化によって暗黙知を形式知化する。これらによって、質の高い社会人経験が積めるのだろうなと思った。
- 終わりにで綴られているテレビ番組出演時のエピソードから本書の内容を総括するような著者の行動が読み取れてかっこよかった。
---

## 5. 引用・メモ


> 「宴会芸は仕事と一緒だ、手を抜かずにやれ」

言ってる内容には共感できるんですけど、改めて文字で見ると「ウッ」てなります

---
初めてのハッカソン体験とRevenueCat SDKの導入体験

はじめまして、モバイル開発者のヨウと申します。

先日、MeltingHackが主催するハッカソンに参加する機会がありました。とても貴重な体験ができたので、ここでその経験を共有させていただきます。

ハッカソンに参加するのは今回が初めてだったため、最初は非常に緊張していました。しかし、スタッフの皆さんがとても親切で、わかりやすい日本語と英語でサポートしてくださったおかげで、すぐに不安は消え、イベントを楽しむことができました。

チームメンバーだけでなく、他のチームの参加者とも交流することができ、良い刺激をたくさん受けました。
![1726488850786.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/736127/482c1bec-e094-41cc-9990-4a6ce9118a69.jpeg)


RevenueCat SDKをiOSアプリに導入してみた。
1. Swift Package Managerを使用してRevenueCat SDKを追加する
2. Apple ConnectコンソルでSubscription Productを作成する

    2.1 サブスク表示名の多言語対応を作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/736127/7a8f7c7e-adb9-363b-5feb-a708bed608de.png)

3. 作ったProductのKey を Revunue Cat プロジェクトのProductと連携する
4. Revunue Cat プロジェクトにOfferings（すべてのProducts）、entitlementを作る
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/736127/d9afa416-4dec-03b3-5713-51a917a88e47.png)


revuenue cat sdk の初期化
```
    init() {
        Purchases.logLevel = .debug
        Purchases.configure(withAPIKey: <revenuecat_project_apple_api_key>, appUserID: <app_user_id>)
    }
　
```

OfferingsのVMを作成する
```
class OfferingsViewModel: ObservableObject {
    @Published private(set) var availablePackages: [Package] = []
    @Published private(set) var isLoading = true
    @Published private(set) var errorMessage: String?
    @Published var alertItem: AlertItem?

    func fetchOfferings() {
        Purchases.shared.getOfferings { [weak self] (offerings, error) in
            DispatchQueue.main.async {
                self?.isLoading = false
                if let error = error {
                    self?.errorMessage = "Failed to fetch offerings: \(error.localizedDescription)"
                    return
                }
                self?.availablePackages = offerings?.current?.availablePackages ?? []
            }
        }
    }
　
```
　

　
　
　
Viewに表示してみる
```
struct OfferingsView: View {
    @StateObject private var viewModel = OfferingsViewModel()
    var body: some View {
        VStack {
            if viewModel.isLoading {
                ProgressView("Loading Packages...")
            } else if viewModel.errorMessage != nil {
                ErrorView(message: viewModel.errorMessage!)
            } else {
                PackageListView(packages: viewModel.availablePackages, onSelect: viewModel.purchase)
            }
        }
        .onAppear(perform: viewModel.fetchOfferings)
        .alert(item: $viewModel.alertItem) { alertItem in
            Alert(title: Text(alertItem.title),
                  message: Text(alertItem.message),
                  dismissButton: .default(Text("OK")))
        }
    }
}
```
 
 Apple Connect Subscriptionに作成したプロダクトが表示できました！
 ![Simulator Screenshot - iPhone 15 Pro - 2024-09-20 at 12.15.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/736127/09a6ddae-7f15-d2b3-3891-abf1f35a5c7c.png)



結論
RevenueCat SDKは、iOSアプリにおけるサブスクリプション管理において非常に優れたツールであることがわかりました。初めての導入もスムーズで直感的で、今回のプロジェクトにも使いたいと思います。
MVCモデルを覚える

Ruby on RailsのMVCモデルについての走り書きです。悪しからず…

# MVCモデル
Railsで登場するモデル/ビュー/コントローラーという役割の総称
RailsをはじめとするWebアプリケーションシステムの処理の構造を表している

特徴
・分離された役割により、コードの可読性や保守性が向上する﻿
↳ただし、分割されているので処理速度が低下、分割作業の発生がある
・コンポーネントの疎結合性により、再利用や保守が容易になる﻿
・各コンポーネントを独立してテストできるため、品質管理やバグの早期発見が可能です﻿
・役割で効率的にアプリケーション開発が行える﻿
・独立性が非常に高く、変更などの対応も柔軟に行なえる﻿

※※手作りMVCモデル※※
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864659/360fc842-2213-6a83-9ea6-83b1219a8110.png)


# M（モデル）
モデルとは、DBとデータをやり取りしたり、データの登録・更新・削除などの処理を行うもの
DBから取得したデータや処理の結果はControllerに送る

# V(ビュー)
ビューとは、表示や入出力などのユーザーインターフェースを担当する部分
リクエストデータをControllerに送ったり、Controllerからレスポンスデータを受け取って画面に表示したりする

					
# C(コントローラー）				
ModelとViewの制御を担当する部分
Modelにデータ処理の指示を出したり、Viewに画面表示の指示を出したりする
Invalid bound statement (not found) 【Mybatisのエラー・ディレクトリ構成の見直しで解決】

## MyBatisのBindingExceptionエラーに悩んでいる方へ  
### マッパーファイルのパス設定に要注意

MyBatisを使用していると、次のようなエラーに遭遇することがある。

```
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
```

このエラーにしばらく悩まされていたが、原因は非常にシンプルだった。
単純だからこそ気づくのに時間がかかってしまっている人も多いかもしれない。

また、手動でディレクトリを一つずつ作成しているパターンなどはこの手のエラーで躓きやすいのではないかと感じたため、画像を添付しながら解説記事として残しておく。

## エラーの原因  
プロジェクトのディレクトリ構成において、**Javaのパッケージ名に合わせて `resources` フォルダ下にも、同じようにディレクトリを配置する必要**があり、構成が異なるとマッパーが、マッパーファイルの場所が正しく指定されていなかったことが原因であった。

例えば、次のような構造の場合:
- `src/main/java/appName/mapper/YourMapper.java`

対応するマッパーファイルは、次の場所に配置しなければならない。
- `src/main/resources/appName/mapper/YourMapper.xml`

**Javaのパッケージと同様のディレクトリ構成を `resources` フォルダにも作成しなければならない。**

例えば、ディレクトリ構造が下記のようになっているとエラーが解消される可能性がある
※上記のファイルパスのappNameが、画像だとimportAppという名前になっている
![スクリーンショット 2024-09-19 212311.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233529/fcf7eb3e-5be8-bd22-f151-41b5605f0541.png)



このディレクトリ構造が正しくないと、MyBatisは対応するマッパーファイルを見つけることができず、エラーが発生する。

## 解決策  
このエラーが出た場合、まずは次の点を確認すべきであると思った。
- `resources` フォルダ内のディレクトリ構成が正しいか？
- マッパーファイルのパスがJavaパッケージと一致しているか？

自分もこの見落としに気づくまで時間を要したが、解決すればスムーズに動作するはずだ。
原因が他にある可能性も十分にあるが、まずディレクトリの構成を見直してみてもいいかもしれない。
少しでも参考になれば幸いである。
Salesforce「選択した商品を編集」項目編集方法

本橋孝昭です

商品追加時に表示される「選択した商品を編集」項目の表示を変更する方法をご紹介します


設定場所はこの画面です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/71e68812-7fa5-785c-336c-49052e0988ea.png)


では見ていきましょう

商談商品オブジェクトのページレイアウトをクリックしてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/488998ed-3589-73b1-af12-4317b71b3a1b.png)



次に右上にある「複数行レイアウトの編集」をクリックしてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/3f9bcad6-a969-6f54-c517-8a9a1cee6144.png)


こちらの「選択済み項目」の設定が反映されれば設定変更可能です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/9753e6d9-d0ee-be7b-482c-abd62e25f0b1.png)
Properties画面でタグに複数値を設定したのに$metaで参照できないとき

# 発生したトラブル
foobar2000のProperties画面でタグに複数値を入力したのに、TitleFormatingの$meta_num(タグ)で1が返ってくる……

# 原因
原因は2つ。
1. タグに入力した複数値が、**1種類の複数のタグに分割されてflacファイルに書き込まれておらず、分割されずに1つのタグにそのまま書き込まれていること**
2. タグの書き込まれ方によって、$metaの挙動が異なること

例えば、ARTISTタグにAとBの2人のアーティストを入力したとき、ARTISTタグへの書き込まれ方によって、以下のように$metaの挙動が異なる。

```:ARTISTタグへの書き込まれ方と$metaの挙動
ARTIST=A
ARITST=B
// $meta_num(ARTIST)=2

ARTIST=A,B
// $meta_num(ARTIST)=1

ARTIST=A;B
// $meta_num(ARTIST)=1
```

## Properties画面で入力した複数値が、なぜ分割されて書き込まれないのか
原因は以下のどちらか。
1. 複数値を入力する際、区切り文字がセミコロンではない
2. 既存タグではない自作タグに入力している

### 原因1：複数値を入力する際の区切り文字がセミコロンではない
Properties画面でタグに複数値を入力する時は、**セミコロン区切りでないと分割して書き込まれない。**
* 例えば、Properties画面でARTISTタグにA,Bと入力すると、flacファイルのARTISTタグにはそのままARTIST=A,Bと書き込まれる。
* ARTIST=A ARTIST=Bと書き込みたいのならば、Properties画面でARTISTタグにA;Bと入力しなければならない。

### 原因2：既存タグではない自作タグに入力している
自作タグの場合、**Properties画面上でセミコロン区切りで複数値を入力しても、分割してタグに書き込まれない。**
* 例えば、Properties画面で自作タグArrangerにA;Bとセミコロン区切りで入力すると、flacファイルにはそのままARRANGER=A;Bと書き込まれる。
* Properties画面での編集のみでは不可能かと思う。Masstaggerを用いることで可能。
[foobar2000 Compornent Repository - Masstagger](https://www.foobar2000.org/components/view/foo_masstag)
    * 一旦セミコロン区切りで自作タグに複数値を入力しておき、Masstagerの"Split by separator"（separatorにセミコロンを指定）で、入力済みの複数値を分割してflacファイルに書き込むことが出来る。

# 感想
* まさか「自作タグの場合、Properties画面でセミコロン区切りで入力しても分割されてflacファイルに書き込まれない」なんて・・・
* 試しにmetaflacでタグ情報を確認してみたところ原因が判明。公式がツール出してくれてるのありがたい。

# 参考
* Masstaggerダウンロード
[foobar2000 Compornent Repository - Masstagger](https://www.foobar2000.org/components/view/foo_masstag)
* Masstaggerを用いて、カンマ区切りで入力しているタグ値を全てセミコロン区切りに置換する。
[オタク特有の「複数アーティストの区切りバラバラ問題」に対応する](https://albno273.hatenablog.com/entry/2016/06/03/%E3%82%AA%E3%82%BF%E3%82%AF%E7%89%B9%E6%9C%89%E3%81%AE%E3%80%8C%E8%A4%87%E6%95%B0%E3%82%A2%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B9%E3%83%88%E3%81%AE%E5%8C%BA%E5%88%87%E3%82%8A%E3%83%90%E3%83%A9%E3%83%90)
* flacファイルのタグ情報をコマンドラインで確認する。
    * flac公式ツールのmetaflacを用いることで確認可能。
    [FLAC - Downloads](https://xiph.org/flac/download.html)
    * コマンドラインで"metaflac --list --block-type=VORBIS_COMMENT XXX.flac"でOK。
macOS Sequoia intel 向け bottle は提供されない（homebrew）

こんにちは。
homebrew の bottle では、macOS Sequoia intel 向けは提供されないようです（2024年9月）。

```console
$ brew cat node | grep "sha.*:" | awk '{print $2}'
arm64_sequoia:
arm64_sonoma:
arm64_ventura:
sonoma:
ventura:
x86_64_linux:
```

なお私の想定よりも提供停止は 1 年早く、私の Intel Mac も macOS Sequoia へは移行させないつもりです。2026年9月には、Sonoma 向けも提供停止となることでしょう。
Ubuntuをインストールしたdynabookのタッチパッドが反応しない問題の解消方法

# はじめに

**Ubuntu24.04.1**を**dynabook GZ83/ML**にインストールするとタッチパッドが反応しなくなりました。この記事はubuntu in dynabookのタッチパッド反応しない問題を解消したときのメモ書きです。

# 解消方法

以下のQAの回答の手順通りにすれば、タッチパッド問題を解消できました。GRUBブートローダ(OSの起動に必要なソフトウェア)の設定を変更することで、dynabookに搭載されたSynaptics社のタッチパッドを有効化する手順が必要になるようでした。

https://askubuntu.com/questions/1365332/synps-2-synaptics-touchpad-doesnt-work-on-ubuntu-20-04-on-dynabook

↓タッチパッド問題の解消手順です。


① GRUB設定用ファイル`/etc/default/grub`を好みのエディターで開く(管理者権限)

```
sudo nano /etc/default/grub
```

② GRUB設定用ファイルを部分的に以下のように編集する

```diff
~~~~~
- GRUB_CMDLINE_LINUX_DEFAULT='quiet splash'
+ GRUB_CMDLINE_LINUX_DEFAULT='quiet splash psmouse.synaptics_intertouch=1'
~~~~~
```

③ GRUBの設定変更を反映し、PCを再起動する

```
sudo update-grub
sudo reboot
```

この手順で自分の環境ではタッチパッドが正常に反応するようになりました。最初にタッチパッドが反応しないときは少し焦ったが、さくっと問題を解消できてよかった。
ソフトウェアファースト第2版（第3章）の読書メモ

# はじめに

前回に続き、ソフトウェアファーストの第2版を読んで思ったことを書き連ねていきます。

https://amzn.asia/d/2fxjKjS

第3章は「ソフトウェアファーストを実現する手段」です。

# 緻密な現状分析

技術者（開発チーム）が主導権を握るシステム開発案件の場合、ここが不十分になることが多い印象を受けます。
開発者たちの関心は、どのような技術スタック、アーキテクトで、システムを構成するかであり、そのために、どのプログラミング言語、フレームワークを採用するかに、意識が向かいがちです。

ものづくりって楽しいんですよね。

とにかくノリでどんどん作ってしまい、その結果、メンテナンスコストが発生し、後から本当に必要な機能がわかったとしても、実装するまでに時間がかかってしまうのが、よくあるパターンです。:sweat:

ビルドトラップとも関連しています。

https://product-managers-club.jp/blog/post/build-traps-fall

また、別の要因として、開発チームの外側にいる人間が勝手に締切を設定した結果、開発が急かされてしまって、現状分析が不十分になることがあります。


# プロダクトマネジメントの3要素

プロダクト全体を考える時は、技術・ユーザ体験（UX）・ビジネスの観点が不可欠と言われています。

確かにどれも重要です。そしてそれら全てを総合的に判断するためには、3分野もの知見が必要になります。

そのような人材の調達・育成にはコストがかかるため、組織側は普段からある程度プール（ツテを作っておく）しておく必要がありそうです。

# リビングドキュメント（生きている文書）

ドキュメントを、開発とともに育てていくという考え方です。

私は、既に普段から行なっているのですが、このような名称があることを初めて知りました。

官公庁系の案件だと、最初から文書の種類やページ数が定められていて、書かないといけないからドキュメントを書くという状態に陥りがちですが、本来は、必要な情報を、必要な時に、必要なだけ書くというアプローチが適切かなと思います。

ドキュメントを書くときは、一般的なWikiだと操作性が良くないので、NotionやConfluenceがおすすめです。

https://www.notion.so/

https://www.atlassian.com/software/confluence
JAG 夏合宿 2024 参加記

　JAG 夏合宿 2024 に参加したので参加記を置いておきます。

### きっかけ
　去年もICPCのチームメンバー(miscalc君)と一緒に参加したので、今年も出ようということになり、参加した。チームメンバーの入れ替わりが生じて、今年はserendipity君を加えて3人での参加となった。

### 1日目
　コンテストは韓国の地区予選のセット？で、3時間で12問だった。ABCD/EFGH/IJKLと分担して読み始めることに。
　自分が最初に担当したI問題を読んでみると、いかにも「1問目」って感じの問題(ABC-Bくらい？)だったので早速実装してAC。最初に見た問題が偶然簡単だったので、I問題はFAを取ることができた。
　解き終わったタイミングで、チームメンバーから「J問題が通されていて、チラっと見ただけだが見た目簡単そう」というような話を聞いたので読んでみると、確かにすんなりと解けそうな見た目だったので(ABC-Dくらい？)解いてAC。
　次にK問題を見ると、かなり[この記事](https://miscalc.hatenablog.com/entry/2022/11/11/213943)みたいな感じだったので、miscalc君に投げてL問題へ。この頃、miscalc君からもH問題のヘルプが来るが、悩んでいるうちに解決したので、KとHの2問の考察を任せてL問題へ。この辺りでseren君がE問題を通した。
　ここからは、自分がL、miscalc君がA、seren君がCのような感じで、他の問題の進捗も見つつ頑張っていた気がする。L問題は幾何っぽいので自分の担当だと考えて頑張ったものの、解法に余計なlogがかかっていたためかTLEしてしまった(発想自体は近かったっぽい)。A問題は定数倍高速化を本気でやるくらいしか思いつかず望み薄で、C問題は構築が詰め切れず。最後30分くらいでBが解けそうだと気付き、seren君が頑張ったものの時間が間に合わずに終了。
　5完13位。B問題に取り組めていたら良かったかもしれない。L問題みたいなのも通せるようになりたい。

 ### 1日目夜
 　ABC371に出た。ちょっと眠かったとはいえ、さすがにA問題に8分かけたのは意味不明すぎる。Fでバグを生やして結構時間を溶かしてGに取り組む時間がなかった。

### 2日目
　コンテストは有志提供の問題セットで、5時間で14問。昨日と同様に、ABCDE/FGHI/JKLMNとほぼ3分割して取り組んだ。
　昨日と同様、他の人が見ていない簡単枠をたまたま最初に見つけてFAを取れると嬉しいな～と考えていたが、JKLMNのいずれも難しそうだった。これらの中ではK問題が若干解きやすそうだったけど、それなりに考察は必要そうなので、いったん全問チームメンバーと共有することにした。その間にmiscalc君がAを通して、ほどなくしてseren君がGを通してくれた。
　問題概要を共有すると、seren君がK問題を解いてくれそうな流れになった。また、Jもなんか行けそうな気がしたので、miscalc君と考えているうちに、かなり方針が立ってきたので担当。二分探索木を眺めて丁寧に頑張り、AC。なんとこの時点でJ問題を通しているチームはなく、2日連続でFAをゲット！
　そうこうしているうちに、seren君がKを通してBに取り組み、miscalc君がFを通してNなどを考えていた。Bのヘルプが欲しそうだったので考察をすると、行ける気がしてきたので頑張って詰めてAC。そのうちに2人はMとNを考えてくれていた。miscalc君からNのヘルプが来ていて、こっちに集中。方針の誤っていた部分を約数包除で解決し、主に自分がNを取り組むようになった。同時進行で2人がMを考えてくれた。この分担ができたのはかなり良かったと思う。結果、MもNも終了10分前くらいにACが取れた。
　8完7位。現時点の実力を出し切れたと思う。

### 2日目夜
　みんな懇親会に行っちゃった……。「参加しても話せそうな人がいないんじゃないか」という消極的な理由で断ってしまった。もっと人と関わろう💪
　特にやることもなかったのでAHCに出場。ヒューリスティック初心者過ぎて、かなり厄介な手法を頑張って実装した割に、素朴な貪欲よりも微妙な結果になってしまって悲しい。ビジュアライザを見るのが楽しかった。

### 3日目
　コンテストは有志提供の問題セットで、5時間で11問。ABが簡単らしいので、Aをseren君が、Bを自分が担当し、miscalc君にはざっと問題を眺めてもらった。A,Bは早々にACを取った。
　Bが終わったので、読まれてなさそうだった後ろから読んでいく。Kはグラフに対するいろいろなクエリを捌く感じで、Union-Findなどをちゃんと使えばできなくもなさそうという感じ。Jは変な問題だなぁと思いながら眺めていると、Dが通っていたので、miscalc君にKの説明をして一緒に考察。マージテクなど解法の本質的な部分が出てきて解けそうだと思ったので自分が担当し、ACをゲット。なんと、この時点でまだ誰もK問題を通していなかったので、3日連続でFAをゲット！！
　ほどなくしてmiscalc君もIを通したので、3人でF,Gを考える状態に。Gはインタラクティブで、seren君が指数探索の方針で考察をしていて、その細部を詰めつつ、Fの考察を行う。どちらもそれなりに難航。Gはどうやら提案された方針だと回数がヤバそうなので、平方分割みたいなことをする変な解法を編み出した。ざっと計算すると、1100回まで許されている質問クエリを1100回くらい行う計算になり、さすがにギリギリすぎるだろと全員思いつつ、Gを自分が担当し、他の2人でFを考えることに。FはFで「辞書順何番目か」を計算するパートで頭がこんがらがったりしながらも、なんとかAC。残りの時間はGに取り組んだ。少しでも質問回数を減らす工夫をして実装し、チームメンバーにジャッジ側の挙動やランダムケースを書いてもらったりして、どうやら1100回は超えなさそうだということが分かり、提出してACを獲得することができた。
　ここまでで4問を残して残り時間が30分くらいだった。ここまでも十分難しかったのだが、残り4問はさらに崖になっていて全然解かれていなかった。一応Cを考察して実験を書いたりしたが分かるわけもなく、ふざけて全問提出して凍結順位表のカモフラージュをしたら時間が来た。
　7完8位。この日も自分のチームで出し切れる限界に近かったと思う。ちなみに、順位表のカモフラージュは、解けてないのに提出した4問のうち3問はCEだったのであまり成功していなかった。むしろ、順位表が凍結された瞬間に全問提出して結果8完していたtokusakurai氏(特別に1人で参加)の方が見事だった。

 ### まとめ
　3日連続でFAを取れたのは嬉しい。1日目は完全に偶然だが、2,3日目は解けそうな問題を解けると信じて取り組めたのが良かった。解けそうな問題を見抜く力はコンテストでも役に立つと思うので自信になった。
　2,3日目はチームで出せる力をかなり出し切った感があった。ここから先は順当に強くなること、つまり解ける問題を増やしていくことが必要になると思うので、練習を重ねていきたい。
　最後に、運営の皆様、夏合宿を開催してくださり本当にありがとうございました。
MySQL 8.4以降のMySQL 9.0で追加、非推奨、変更、削除された内容まとめ

# 概要
MySQL 8.4以降のMySQL 9.0で追加、非推奨、変更、削除された内容まとめです。

MySQL 9.0に追加された機能は以下の通りです。

## JavaScriptストアドプログラム

MySQL Enterprise Editionに、JavaScriptで書かれたストアドプログラムのサポートが追加されました。以下は`CREATE FUNCTION`文とJavaScriptコードを使用した簡単な例です。

```sql
CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$
let x = Math.abs(a)
let y = Math.abs(b)
while(y) {
  var t = y
  y = x % y
  x = t
}
return x
$mle$ ;
```

JavaScriptで書かれたストアドプロシージャとストアド関数の両方がサポートされており、多言語エンジンコンポーネント(MLE)によって提供されています。

MySQLのJavaScript言語サポートはECMAScript 2023仕様に準拠しており、デフォルトでStrictモードを使用します。この実装には、`Object`、`Function`、`Math`、`Date`、`String`などの標準ECMAScriptライブラリオブジェクトがすべて含まれています。

## VECTORタイプのサポート

MySQL 9.0は`VECTOR`カラムタイプをサポートしています。ベクトルは、バイナリ文字列値またはリスト形式の文字列として表現できる、エントリ（4バイト浮動小数点値）のリストで構成されるデータ構造です。

`VECTOR`カラムは以下のように`CREATE TABLE`を使用して作成できます。

```sql
mysql> CREATE TABLE v1 (c1 VECTOR(5000));
Query OK, 0 rows affected (0.03 sec)
```

ベクトルカラムにはいくつかの制限があります

- `VECTOR`カラムはどのタイプのキーとしても使用できません。
- 一部のMySQL関数と演算子はベクトルを引数として受け付けません。

## インラインおよび暗黙的な外部キー制約

MySQLは現在、以前はパーサーに受け入れられていたものの無視されていたインライン外部キー指定を強制します。MySQL 9.0は親テーブルの主キー列への暗黙的な参照も受け入れます。

## EXPLAIN ANALYZE INTO のJSON出力の保存

`EXPLAIN ANALYZE`のJSON出力をユーザー変数に保存するサポートが追加されました。

```sql
EXPLAIN ANALYZE FORMAT=JSON INTO @variable select_stmt
```

## イベントDDLのプリペアドステートメント

MySQL 9.0.0以降、以下のステートメントを準備できるようになりました。

- CREATE EVENT
- ALTER EVENT
- DROP EVENT

## パフォーマンススキーマのシステム変数テーブル

MySQL 9.0では、サーバーシステム変数に関する情報を提供する2つの新しいテーブルがパフォーマンススキーマに追加されました。

- `variables_metadata`テーブル
- `global_variable_attributes`テーブル

## EXPLAIN FORMAT=JSON の拡張

`EXPLAIN FORMAT=JSON`の出力に、結合列に関する情報が含まれるようになりました。

## LIMIT 1 を含む相関サブクエリ

以前は、派生テーブルを持つ外部左結合に変換される資格を得るために、サブクエリに`LIMIT`句を含めることはできませんでした。MySQL 9.0では、この制限が若干緩和され、`LIMIT 1`を含むサブクエリを変換できるようになりました。

以下の機能はMySQL 9.0で非推奨となり、将来のシリーズで削除される可能性があります。

- パフォーマンススキーマの`variables_info`テーブルの列
- トランザクショナルおよび非トランザクショナルテーブルを更新するトランザクション

以下の項目は廃止され、MySQL 9.0で削除されました。

- `mysql_native_password`プラグイン

この変更に伴い、以下のサーバーオプションと変数も削除されました。

- `--mysql-native-password` サーバーオプション

- `--mysql-native-password-proxy-users` サーバーオプション

- `default_authentication_plugin` サーバーシステム変数

下位互換性のため、`mysql_native_password` はクライアント側では引き続き利用可能です。これにより、MySQL 9.0のクライアントプログラムが以前のバージョンのMySQLサーバーに接続できるようになっています。MySQL 9.0では、以前のリリースのクライアントプログラムに組み込まれていたMySQLネイティブ認証プラグインが、実行時にロードする必要があるプラグインに変換されました。

## 参考
https://dev.mysql.com/doc/refman/9.0/en/mysql-nutshell.html
検索インデックスを構築して大容量データを検索する


大容量のデータを扱う検索インデックスの作成は、効率的なデータ構造や検索アルゴリズムが重要です。以下に、一般的なアプローチと技術を紹介します。

### 1. **インデックスの構造設計**
#### a. **倒立インデックス（Inverted Index）**
   - **概要**: 倒立インデックスは、検索エンジンのコア技術で、ドキュメントに含まれる単語（トークン）をキーにして、どのドキュメントにその単語が出現するかを記録します。これはフルテキスト検索で非常に有効です。
   - **実装例**: Apache LuceneやElasticsearchなどが倒立インデックスを採用しています。

#### b. **B+ツリー**
   - **概要**: データベース管理システム（DBMS）で使われるデータ構造で、ディスクベースのデータアクセスを効率化します。リレーショナルデータベース（RDBMS）のような検索エンジンでよく使われます。
   - **用途**: SQLのLIKE検索や範囲検索などで有効です。

#### c. **ハッシュインデックス**
   - **概要**: キーと値のペアを素早く検索するためにハッシュ関数を使用します。具体的な値を一意に検索する際に特に効率的です。ただし、範囲検索や部分一致検索には不向きです。

#### d. **トライ木（Trie）**
   - **概要**: 文字列検索に特化したデータ構造で、プレフィックス検索に非常に効果的です。例えば、サジェスト機能やオートコンプリートで使われます。

### 2. **データの分散・分割**
大容量のデータを扱う場合、インデックスを単一のノードに置くことは非現実的なことが多いです。分散処理を行うためのアプローチが必要です。

#### a. **シャーディング**
   - **概要**: データを複数のシャード（分割）に分けて、それぞれ別々のサーバーやノードに保存します。これにより、検索負荷を分散できます。

#### b. **レプリケーション**
   - **概要**: データを複数のノードに複製して、可用性と耐障害性を向上させます。検索クエリは複数のノードに対して並列に実行され、応答時間が短縮されます。

### 3. **インデックスの最適化**
インデックスは更新や挿入によって断片化することがあります。これを解消するための最適化が必要です。

#### a. **マージプロセス**
   - インデックスを定期的にマージして断片化を防ぎ、検索速度を向上させます。例えば、Elasticsearchでは背景で自動的に行われます。

#### b. **キャッシュの利用**
   - 頻繁に参照されるデータをキャッシュに保存して、検索パフォーマンスを向上させます。ElasticsearchやSolrなどはメモリベースのキャッシュを持っており、ホットデータの高速アクセスを可能にします。

### 4. **検索クエリの効率化**
インデックスの構造だけでなく、検索クエリ自体を効率的に設計することも重要です。

#### a. **クエリの正規化**
   - ユーザーの入力を正規化し、無駄な処理を避けることで、検索の効率を上げます。例えば、大文字・小文字の区別を無くしたり、無意味なトークンを除去します。

#### b. **分散クエリの実行**
   - シャーディングされたインデックスに対してクエリを分散して実行し、結果を統合します。

### 5. **利用するツール・ライブラリ**
大規模なデータセットを扱う際には、既存の分散検索エンジンやインデックス作成ライブラリを活用するのが効率的です。
   
#### a. **Elasticsearch**
   - フルテキスト検索と分散システムの両方に対応したオープンソース検索エンジン。大量のデータに対してリアルタイムにクエリを実行できます。
   
#### b. **Apache Solr**
   - Luceneベースの検索エンジンで、スケーラブルな分散検索や分析機能を提供します。REST API経由でのアクセスが可能です。

#### c. **Apache Lucene**
   - フルテキスト検索エンジンのコアライブラリで、SolrやElasticsearchのベースとなっています。独自の検索システムを構築する場合にも利用可能です。

### 6. **並列処理とバッチ処理**
大量データを一度に処理する場合、インデックス作成をバッチ処理や並列処理で実行することが推奨されます。

#### a. **バルクインデックス**
   - データをバッチでインデックスすることで、パフォーマンスを最適化します。ElasticsearchやSolrはこの機能を提供しています。

#### b. **並列処理フレームワーク**
   - Apache HadoopやApache Sparkのような分散処理フレームワークを活用して、大規模データセットのインデックス作成を並列化します。

### 7. **スケーリング**
データが増えるにつれて、システム全体をスケールアップまたはスケールアウトする必要があります。

#### a. **水平スケーリング**
   - ノード数を増やしてシステム全体の処理能力を向上させる方法です。Elasticsearchなどの分散検索エンジンは、この方法でスケールが可能です。

#### b. **垂直スケーリング**
   - 単一のサーバーのハードウェアスペックを上げて、処理能力を増やす方法ですが、コストと限界があります。

---

### 結論
大容量データを扱う検索インデックスの作成には、適切なインデックス構造、分散処理、キャッシュ、そして検索クエリの最適化が重要です。具体的なシステム設計や要件によって、使用する技術やアーキテクチャは異なりますが、ElasticsearchやSolrといった既存のツールを使うことが効果的です。
CSS: 属性selectorを無視

htmlの各要素には属性値があります。これらには規定値が設定されている場合があり、CSSの属性selectorと組み合わせるとどうなるのでしょうか…。結論から申し上げますと、CSSでは無視されるようです。

## input
type属性の規定値のtextです。cssで文字色を赤に設定。ド突くと規定値表示
```html
<style>input[type=text]{color:red}</style>
<input onfocus=value=type>
<input onfocus=value=type type=text>
```
`type=text`等のinput要素の`value`の規定値は空文字。しかしtagに記述しておかないとやはり適用されず、なんと動的に設定しても適用されません(最後のinput要素)
```html
<style>input[value]{color:red}</style>
<input>
<input value>
<input value="">
<input value=text>
<input onfocus=value=type type=text>
```
## button
type属性の規定値はsubmit。cssで文字色をaquaに設定。ド突くと規定値表示
```html
<style>button[type=submit]{color:aqua}</style>
<button onfocus=innerText=type>&nbsp;</button>
<button onfocus=innerText=type type=submit>&nbsp;</button>
```
## 他の要素
一般属性であるid、class、title等の規定値は空文字。だからと言って全要素に適用されてはたまったものではありません。さすがにtagに明示的に設定しておかないと適用されません
```css:css
[id]{color:red}
[class]{color:gold}
[title]{color:aqua}
```
以下はほぼ?同じ意味となる
```css:css
[id=""]{color:red}
[class=""]{color:gold}
[title=""]{color:aqua}
```
空文字で始まる場合も、属性持ちの全要素に適用される……**わけがありません**。なんと**該当要素皆無**。
```css:css
[id^=""]{color:red}
[class^=""]{color:gold}
[title^=""]{color:aqua}
```
続いてhtml
```html:html
<a id>適用</a> <a id="">適用</a> <a id=a>適用</a>
<a>不適用</a>
```
Dart言語の重要なトピック「Async & Await」について

![async.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771687/71c3cfa5-ff3d-7cc6-8ce9-63202a676a87.png)

このトピックを議論する前に、「同期的」と「非同期的」プログラム実行について理解しておく必要があります。

## 同期プログラミング:

同期プログラミングでは、プログラムが逐次的に行ごとに実行されます。
- 同じタイミングでプログラムが実行され、行ごとに進行します。
- 関数を呼び出すと、その関数が戻るまで、または関数の処理が完了するまで、次のステートメントは実行されません。

 例を見てみましょう：
  ```
  ステートメント1..... 実行
  関数(); // 1s 2s 3s 4s.... 実行
  ステートメント2 ..... 実行
  ステートメント3 ..... 実行
  ```

## 非同期プログラミング:

非同期プログラミングでは、プログラムが逐次的に実行されるわけではありません。
- 関数を呼び出しても、その関数の処理が完了するのを待たずに、次のステートメントが実行されます。

例を見てみましょう：
  ```
  ステートメント1...  // 実行
  関数() // 待機
  ステートメント2 ...  // 完了
  ステートメント3 ... // 完了
  ```
![synchronous-vs-asynchronous.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771687/658a78e4-6b41-ae75-92a4-e828ed308161.jpeg)

さて、本題に戻りましょう。`async`とは、関数が結果を取得するのに時間がかかる可能性があることを意味します。一方、`await`は、`async`関数が完了するまで通常のフローをブロックし、次の指示やステートメントの実行を停止します。そして、`async`メソッドの処理が完了すると、`await`が待機していたコードの実行を再開します。たとえば、APIサーバーからデータをリクエストする場合、そのリクエストがサーバーからのレスポンスを待つ間、プログラムは他のステートメントを実行し続けます。Dartでは、非同期操作を行うために`Future`クラスと`async`および`await`キーワードを使用します。


### では、なぜ`async`はそれほど重要なのか？

`async`は非常に重要な機能です。なぜなら、`async`は`Future`タイプのデータを処理しながら、他の作業を完了するのを助けてくれるからです。その結果、プログラムの実行時間が節約され、ソフトウェアのパフォーマンスが向上します。一般的な非同期操作の例としては以下のものがあります：

- ネットワーク経由でデータを取得する。
- データベースに書き込む。
- ファイルからデータを読み取る。

## フォローお願いします
https://github.com/jpmehedi
Exporting the operator 'aten::_upsample_bilinear2d_aa' to ONNX opset version 19 is not supported.

今回は自分自身へのいましめも含めて記事にしました。
ーーーーーーーーーーーーーーーーーーーーーーーーー
onnxへの変換の際に、torchvision.transformsのResize()で以下のエラーが出力された。

```
Exporting the operator 'aten::_upsample_bilinear2d_aa' to ONNX opset version 19 is not supported.
```

ならばtorchvision.transforms.functionalのInterpolate()ならばどうだろうと試してみたところ、無事解決したので、その理由も考えずにスルーしてマージ。

そのまま数週間後学習用コードはResize()で、onnx用コードはinterpolate()を利用していたところ、なぜか学習した重みを使ってonnxを作成すると精度がすごく悪い。
画像のアーキファクトなどのノイズを補正するantialiasがResize()だとデフォルトでTrue()になっており、interpolate()だとデフォルトでFalseになっているのが原因でした。

デフォルト引数に気をつけるのはもちろん、エラーが解決したときは理由も考えるようにしましょう。