OmniAICreator/Qiita-1.07M huggingface dataset:
[Prisma][TypeScript]Includeしたテーブルの型を使用したい

# はじめに
表題の通りです。
Prismaの関数をラップした時、関数の戻り値の型にIncludeしたテーブルの型を含めたいです。



元々は以下の記事を参考にした「GetPayLoad」を使用して実現していました。
https://zenn.dev/yuyuyu_6/articles/9d3a2b5a7becad

しかし、Prisma4.11から5.11に更新してから型エラーで使えなくなってしまいました。
以下サンプルコードです。
```TS
  async fetchUser<T extends Prisma.UserInclude>(
    input: Prisma.UserFindManyArgs,
    include?: T,
  ): Promise<Prisma.UserGetPayload<{ include: T }>[]> {
    // 戻り値の型と不一致になる
    return await this.prisma.User.findMany({
      ...input,
      include: include,
    });
  }
```

上記が使えないと、Service層とUsecase層で処理の共通化が滞り、イケテナイコードを量産する羽目になりそうです。
本記事では上記の代替手段ついて記載します。

# 結論
代替を検討中にエラーを解消できてしまいました。。。
理由はわかりませんが、スプレット構文が原因でした。
以下のように修正すると動きます。
```TS
  async fetchUser<T extends Prisma.UserInclude>(
    input: Prisma.UserFindManyArgs,
    include?: T,
  ): Promise<Prisma.UserGetPayload<{ include: T }>[]> {
    // 戻り値の型と不一致になる
    return await this.prisma.User.findMany({
      where: input.where,
      orderBy: input.orderBy,
      skip: input.skip,
      take: input.take,
      cursor: input.cursor,
      distinct: input.distinct,
      include: include,
    });
  }
```
原因の予想ですが、PrismaではSelectとIncludeを同時におこなうとエラーになります。
元々UserFindManyArgsを展開すると、上記に反してエラーになるはずだったが、
バグか何かでそうならなかった。
それが修正されたのかなぁと。

でもスプレット構文の後にNullとかundefinedにしてもエラー発生するので、
わっかんねぇなぁって感じです。

# 代替案
## 前もって型を作成する
あんまりイケテナイとは思いますが最初に思いつく方法です。
シンプルゆえに一番確実です。
```TS

export type UserAndPost = User & {
  Post: Post;

};
```

## ジェネリクスを使わない
ジェネリクスを使わなくてもUserIncludeを使用すればリレーション先を含めた型を使用できます。

```TS
  async fetchUser(
    input: Prisma.UserFindManyArgs,
    include?: Prisma.UserInclude,
  ): Promise<Prisma.UserGetPayload<{ include: Prisma.UserInclude }>[]> {
    return await this.prisma.User.findMany({
      ...input,
      include: include,
    });
  }
```

こうするともっとスマートかなと思います。
```TS
  async fetchUser(
    input: Prisma.UserFindManyArgs,
  ): Promise<Prisma.UserGetPayload<{ include: typeof input.include }>[]> {
    return await this.prisma.User.findMany({
      ...input,
    });
  }
```

しかし、これで使用できるのはリレーション先のテーブルまでです。
リレーション先のリレーション先多重構造のテーブルの型は使用できません。


## PromiseReturnType（没案）
公式でPrisma関数が返すオブジェクトの型を取得する時は「PromiseReturnType」を使えとあります。
https://www.prisma.io/docs/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types#problem-getting-access-to-the-return-type-of-a-function

これは今回のようにIncludeによって戻り値の型が変わる関数では意味がありませんでした。
そもそも型が合わないので呼び出せないです。

PrismaでNativeSQLを実行する場合とかはいいかもしれません。


# 終わり
スプレット構文でハマることが多く、こまったなぁって感じです。
【ChatGPT＋DALL-E3】企画の裏で……


　どうも、カーブミラーです。

　今回は、X-Twitter上で企画をしているその裏で、私がやっていることを書きます。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はありません。あしからず。
:::

　酔っ払った勢いで
　　記事を書こうと思ってて
　　　途中で寝てしまいました。

　起きたら、すっかり忘れてて
　　それよりも二日酔い。

　とりあえず、
　　X-Twitterをチェックして
　　　腹にちょっと入れて。

　なんてことをしてたら、
　　記事が書けていないことに
　　　気付いて、あたふた。

　アップが
　　こんな時間になりました(汗)
***
　X-Twitterですが、
　　“春のバン祭り”（BANね）で
　　　またフォロワー数が減りました。
　　　　しかもゴッソリ😂

　まぁ、
　　フォロワー数を
　　　気にする段階は
　　　　過ぎましたので、
　　　　　楽しむことを目的に
　　　　　　活動していくつもりです。
***
　さて、
　　本題です。

　実は、今回の企画の裏で、
　　前回の企画で
　　　集まったファッションを
　　　　自分のモデルに着せて
　　　　　ポストしています。

　ここまでが
　　大変でした。

　今回は、
　　その舞台裏を
　　　書きました。
***
　作業は、
　　ポストされるごとに
　　　ファッションの解析を
　　　　させていましたので、
　　　　　基本はその延長です。

　その服装をした女性を
　　描画するだけですから、
　　　さして苦労はしないはずでした。

　ところが
　　服装は再現できず、
　　　アスペクト比もダメ。

　そのうちに
　　DALL-E3での描画制限が来て……。

　とりあえず、
　　それまで生成できた
　　　画像のPromptを出させて
　　　　コピーして。

　それを持って、
　　CopilotDesignerで
　　　描画していました。
　　　　まぁ、それは置いとくか。
***
　どこに時間が
　　取られたかといいますと
　　　アスペクト比です。

　1:1と指定していました。
　　正方形ですね。

　X-Twitterを
　　スマホで見ていると、
　　　基本の比率が正方形です。

　横長も縦長も
　　ありますが、多くはありません。

　別に
　　そういう仕来たりが
　　　あるわけではありません。

　とにかく、
　　私は、基本を
　　　正方形にしています。

　ところが、
　　どんな指示を出しても
　　　なかなかモデルの全身を
　　　　正方形の中に描画してくれず。

　全身の描画を指定すると
　　縦長画像で、横倒し状態が
　　　頻発します。

　これで
　　多くの時間とリソースが、
　　　流れていきました。
***
　もう、諦めの境地での
　　作業をしていると、
　　　縦長指定ならば、
　　　　うまく全身が
　　　　　描画されことに
　　　　　　気付きました。

　そこからは
　　バンバンと
　　　サクサクでの
　　　　作業になりました。

　ええ、
　　もう縦長画像で
　　　ポストします。
***
　こんなことが
　　みなさんの参考になるとは
　　　思えませんが、
　　　　作品制作を頑張ってください。

　今回は、ここまで。
論文メモ：Representation Learning on Graphs with Jumping Knowledge Networks



# この論文を読んだ理由
- この論文の手法を取り入れた論文を数多く見かけたため．


# 読んだところ
- 全体


# 解いている課題
- GNNにおける集約において，近傍ノードがグラフ構造に強く依存してしまっている問題．具体的には，中心のノードは近傍が多く，端のノードは近傍が少ない．
- ノードごとに適当的に近傍の範囲を定めたい．


# 提案手法のアプローチ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583007/ef6f0f4e-05b3-723e-5151-08c06c834e6a.png)

**各層の出力を集めてきた後，Concat/Max-pooling/LSTM-attention 演算を行う．**

- <INS>Concat</INS>...この場合は適応的ではない．Concatのあと線形層に通すことで全てのホップ数を考慮することが出来る．

- <INS>Max-pooling</INS>...各層の出力のうち，一番情報が多い要素（値が大きい要素）を取ることで，適応的に集約するノードを選択できる．

- <INS>LSTM-attention</INS>...双方向のLSTMで各層の重要度を計算し，重み付き和で集約を行う．重要なホップ数を定め，適応的に集約するノードを選択できる．


# 実装例

2層のGCNにJumping Knowledgeを取り入れたモデルです．
参考：https://github.com/pyg-team/pytorch_geometric/blob/master/benchmark/kernel/gcn.py

```python
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv, JumpingKnowledge

class GCNWithJK(torch.nn.Module):
    def __init__(self, in_channels, hidden_channels, out_channels, mode='cat'):
        super().__init__()

        self.conv1 = GCNConv(in_channels, hidden_channels)
        self.conv2 = GCNConv(hidden_channels, hidden_channels)

        self.jump = JumpingKnowledge(mode)

        if mode == 'cat':
            # concatするので次元がhidden_channelsの2倍になる．
            self.lin = Linear(hidden_channels * 2, out_channels) 
        else:
            self.lin = Linear(hidden_channels, out_channels)

    def reset_parameters(self):
        self.conv1.reset_parameters()
        self.conv2.reset_parameters()
        self.jump.reset_parameters()
        self.lin.reset_parameters()

    def forward(self, x, edge_index):

        xs = [] # 各層の出力を格納する

        # 一層目
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        
        xs += [x]

        # 二層目
        x = self.conv2(x, edge_index)
        x = F.relu(x)

        xs += [x]

        # 各層からの出力を集約
        x = self.jump(xs) 

        # 最終層の次元へ変換
        x = self.lin(x) 
        
        return F.log_softmax(x, dim=-1)
```
qiita error


# エラー集

qiita で起きたエラーやミスをまとめていきます（随時更新）
主に Qiita-CLI

# command error

### その1

```
> npx qiita preview
[Error: ENOENT: no such file or directory, open '/Users/user/.config/qiita-cli/credentials.json'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/Users/user/.config/qiita-cli/credentials.json'
}
エラーが発生しました (ENOENT: no such file or directory, open '/Users/user/.config/qiita-cli/credentials.json')
  バグの可能性がある場合は，Qiita Discussionsよりご報告いただけると幸いです
  https://github.com/increments/qiita-discussions
```

:::note info

### 解決策

ログインができていない
`npx qiita login`で[トークン発行ページ](https://qiita.com/settings/applications)で発行したトークンを貼り付け
:::



# npx qiita publish --all

### その1

```
> npx qiita publish -all
エラーが発生しました (unknown or unexpected option: -a)
  バグの可能性がある場合は，Qiita Discussionsよりご報告いただけると幸いです
  https://github.com/increments/qiita-discussions
```

::: note info

### 解決策

オプションの指定が間違っている

`npx qiita publish -**-**all`
:::

### その２

```
> npx qiita publish -all
QiitaForbiddenError: {"message":"Forbidden","type":"forbidden"}
    at QiitaApi.request
    ...
Qiita APIへのリクエストに失敗しました
  Qiitaのアクセストークンが正しいかご確認ください
```

:::note info

### 解決策

タグにスペースが含まれている
:::

### その３

```
> npx qiita publish --all
qiita_error: 内容がQiita上の記事より古い可能性があります
```

:::note info

### 解決策

古いと思われる記事の`updated_at`を空白('')にする
:::
robots.txt


# What is robots.txt
robots.txt is a text file webmasters create to instruct web robots (typically search engine robots) how to crawl pages on their website. The robots.txt file is part of the the robots exclusion protocol (REP), a group of web standards that regulate how robots crawl the web, access and index content, and serve that content up to users. The REP also includes directives like meta robots, as well as page-, subdirectory-, or site-wide instructions for how search engines should treat links (such as "follow" or "nofollow").

# How to use robots.txt
The robots.txt file is a simple text file placed on your web server which tells webcrawlers like Googlebot if they should access a file or not. The robots.txt file is part of the the robots exclusion protocol (REP), a group of web standards that regulate how robots crawl the web, access and index content, and serve that content up to users. The REP also includes directives like meta robots, as well as page-, subdirectory-, or site-wide instructions for how search engines should treat links (such as "follow" or "nofollow").

# Example
```
User-agent: *
Disallow: /cgi-bin/
Disallow: /tmp/
Disallow: /~joe/
```

# Reference
- [Google robots.txt](https://www.google.co.jp/robots.txt)
- [robots.txt](https://developers.google.com/search/docs/advanced/robots/intro?hl=en)
知識皆無の雑魚がDiscordBotを作ってみる 

## はじめに
皆さんも色々な用途でDiscordを使っていると思います。私も普段仕事で使うこともありますし、オンラインゲーム等で使用してたりします。そんなある日、ふと思いついてしまいました。

「DiscordBot作れたら面白そうじゃね？」

本当にそれだけでした。そのため、筆者が書くコードはマジやべぇレベルで汚いし、効率的でもありません。
実装するまでの備忘録がてらの記事を作成していきたいと思います。
これから始める人は、「あ、こんな雑魚でも作れるもんがあるのか」と思ってください。
ある程度慣れてる人や知識がちゃんとある人は「なんだこの雑魚。もっとまともなもん書けよ」と生暖かい目で見てやってください。
参考になるかはさっぱり微妙ですが、筆者と同じく「とりあえず何か作ってみよう」と思った人の参考になれば幸いです。
そして壁にぶちあたった様子が見られたら助けてやってください。

閑話休題。

## 最初にやったこと
コードの作り方を調べる！　と言えれば恰好よかったのですが、そこまでするのは面倒くさい。なので、ChatGPTとWindows標準のCopilotを利用して少しずつ作ることにしました。
人生は諦めが肝心です。多分言葉としてこれから何度も出てきます。結果として「ほしい機能に近いものが作れたらヨシッ」という感覚で妥協することに決めました。近いもの、というのが大事です。

## というわけで作ってみたいもの（機能）を決めました。
主な目的はプレイしているオンラインゲームの鯖での使用。Botを公開配布等は考えておらず、あくまで自分が管理権限を持つ場合に限っての使用です。
 
### 1.スケジュールのリマインド機能
> 「指定した時間」に「指定した内容」を「指定したチャンネル」に送信する機能
### 2.メッセージリンクの埋め込み表示機能
> Discordで発言したメッセージリンクを埋め込みリンクで送信する機能
### 3.外部SNS等のURLの埋め込み表示機能
> 具体的にはTwitter（現X）のリンクを貼った時に、画像を全て埋め込みで表示する機能
### 4.WebサイトのURL登録機能
> 事前に登録したWebサイトのURLを返してくれる機能
### 5.メッセージ一括削除機能
> 指定したユーザーのメッセージの一括削除機能

といったものをつっこんでみたいと思います。他にも随時増えていったら試していこうと思います。

 ## というわけで準備
VSCodeを用意して、Discor.pyとかpycordをインストールしてBotTOKENを用意して…とぶっちゃけ最初に開始する際の準備などはありふれているので割愛します。本来はちゃんと学ぶべきスタートラインだと思います。
筆者は結果だけ得られればいいという最低な動機のもと始めています。真似してはいけません。

 ## まず適当にCodeを突っ込んでみる。
とは言っても、何もないんじゃつっこんでみようもない。hogehogeとかHello,Wolrdとかまず打ってみるべきだとは思いますが、せっかちな筆者には苦痛でした。
しかしこのままだと「とりあえず作ってみよう」という人に向かない記事になってしまうので、頑張ってみます。
とりあえず簡単なコードを教えて、Copilot！
Q.「HELLOWEEN」と返すシンプルなコードを教えて。
A.「HELLOWEEN」というメッセージに反応して同じメッセージを返すシンプルなDiscordボットのPythonコードを以下に示します。

…いや、なんかキミ、ちょっと違わない？　まぁ、いっかぁ！　よろしくなぁ！　ちなみにHELLOWEENというのは誤字ではなくドイツのバンドです。

```
import discord
from discord.ext import commands

# ボットのコマンドプレフィックスを設定
bot = commands.Bot(command_prefix='!')

# 'HELLOWEEN'というメッセージに反応するコマンド
@bot.command()
async def helloween(ctx):
    await ctx.send('HELLOWEEN')

# ここにあなたのDiscordボットのトークンを入れてください
bot.run('YOUR_BOT_TOKEN')
```
とりあえず何となく文章から読み取れるものとして一つずつ把握していこうと思います。
```
import discord
from discord.ext import commands
```
discord機能を入力して、discord.extからcommandsという機能を入力しますよ、という意味と勝手に把握。初心者にかく恥などないのである。
```
# ボットのコマンドプレフィックスを設定
bot = commands.Bot(command_prefix='!')
```
「コマンドプレフィックスってなぁに？( ᐛ )」と思って調べたら、どうやらBotが認識するためのトリガーみたいなものらしい。「OK、Go〇gle」みたいな掛け声と思っておきます。正しい認識かはわかりません。
```
# 'HELLOWEEN'というメッセージに反応するコマンド
@bot.command()
async def helloween(ctx):
    await ctx.send('HELLOWEEN')
```
はい、ここからもうさっぱりわかりません！　筆者の脳みそは0.5mgぐらいしかないんですよ！？
syncは同期って意味だったはずだから、asyncだと非同期？　はいいとして、defって何、何なのさ！？
と思って調べてみたら、定義するためにつける拡張子みたいなもんらしい。ctxはコンテキスト情報で、コマンドを呼び出した時の複数の情報（端折った）を含むとか。
つまりasync def helloween(ctx)で「helloweenで呼び出すコンテキスト情報を非同期で定義する」的な意味なんですかね？　謎は深まるばかりである。~~謎の水深は多分0.01mmぐらい。~~
とりあえずお決まりの構文的なものとして出てくるものだと把握しとくに留めます。人生はやはり諦めが肝心です。
```
# ここにあなたのDiscordボットのトークンを入れてください
bot.run('YOUR_BOT_TOKEN')
```
これは流石にわかる。DiscordBotのTOKENを入れればいいだけですね。
でもこれって、Githubとかにそのままあげたら結構あぶねーのでは？　と疑問だけメモしておく。
多分何かしらマスクする方法があるでしょう！　でも今は後回し！

とりあえず試しでコードを打ち込んでみただけなので、今回は以上で終わります。
次の記事あたりから、作ってみたい機能であげた5つの機能を入れてみたいと思います。
多分途中でハゲちらかしながら進めることと思いますが、お付き合いいただければ幸いです。
DNSのnameserverを変更する

# 経緯
DNSサーバーの構築設定中、/etc/resolv.confの設定変更に詰まりました。

https://linuc.org/textbooks/server/

具体的には、こちらの手順(5.18)に従って構築していたのですが、テスト用に作成したドメイン（example1.jp）が、DNSの/etc/resolv.confファイルに追加されていないという問題が発生しました。


# 環境
VMware WorkStation 17
CentOS7


# 解決
Chat-GPT先生に聞いてみました。

まず、/etc/resolv.confファイルや/etc/sysconfig/network-scripts/ifcfg-XXXXを直接viなどで編集するのは非推奨らしい[^1]ので、nmcliコマンドを使って編集します。

①インターフェースの現状を表示する
```
# nmcli d
```

②DNSの追加とsearchを変更する
```
# nmcli c m "インターフェース名" ipv4.dns "ipv4アドレス" ipv4.dns-search example1.jp
```

③DHCPからDNSの自動取得を無効化
```
# nmcli c m "インターフェース名" ipv4.ignore-auto-dns yes
```

④設定の変更を反映させる
```
# sudo systemctl restart NetworkManager
```

⑤変更を確認する
```
 # cat /etc/resolv.conf
 ```


 # 参考

・/etc/resolv.conf内のsearchとdomainの違い

https://diesirae.fc2.net/blog-entry-204.html

・大まかな手順の流れ

https://yoshikawam.hatenablog.com/entry/2016/01/08/104736

https://blog.apar.jp/linux/3147/



[^1]:https://ngv.jp/blog/2023/03/20/181
ミスやタイポのリスク、他のツールとの競合、適応性の欠如、セキュリティ上の懸念などの問題を引き起こす可能性があるため。
nmcliコマンドが推奨とされるのは、ネットワーク設定が一貫性を持ち、エラーや不正な設定となることを防ぐためみたいです。
Sakana AIの新手法：既存LLMの組み合わせで高性能LLMを自動構築

最近、Transformerの著者の一人が立ち上げた日本のAIスタートアップ「Sakana AI」が、新しいLLMの作成手法”進化的モデルマージ（Evolutionary Model Merge）”を発表しました。SNSで非常に話題になりましたので、共有したいと思います。

# 1.レイヤーとパラメーターの組み合わせ

この手法は、既存のモデルのレイヤーとパラメーターの組み合わせを最適化することで、高性能なモデルを自動的に構築する手法です。

レイヤー間のマージでは、進化的アルゴリズムを用いて、複数の既存モデルから最適なレイヤーを選び出し、それらを並び替えます。下の図のようなイメージです⇩

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/c59055eb-7838-5e79-4eaa-b12fed57e63d.png)

一方、パラメータのマージは、異なるモデル間の最適な重みを探して、それらを組み合わせることを指します。⇩

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/30b7423d-8494-748b-05df-4e12c8706c14.png)

そして最後に、これら2つのマージ方法を再度組み合わせ、自動化することで、モデルを自動的に生成することができます。⇩

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/740328c3-5373-53a8-69cb-7426e20e4c85.png)

# 2.モデルの精度

⇩はマージ後のモデルの精度です。日本語モデル「Shisa Gamma 7B v1」と英語の数学モデル「WizardMath 7B v1.1」、「Abel 7B 002」を組み合わせたところ、「Llama 2 70B」や「GPT-3.5」といった既存の高性能モデル並みのスコアを達成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/ead6584a-daa1-1d85-b8d9-302bf0946055.png)


# 3.マルチモーダル間のマージ

さらに、マルチモーダル間のマージも可能です。英語のマルチモーダルモデル”LLaVA”と日本語LLM”Shisa Gamma 7B v1”をマージすることで、日本語データで学習した”Japanese Stable VLM”よりも高い精度のモデルを生成できました。画像生成モデルにも同様の結果が得られました。（もちろん一切勾配ベースのトレーニングせず、単純にマージしただけです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/cdaa9f3a-965d-f055-5971-54d80460083d.png)


これら3つのモデルは、現在Hugging Faceでそのまま試すこともできます。
興味ある方試してみてください：

https://huggingface.co/spaces/SakanaAI/EvoVLM-JP


https://sakana.ai/evolutionary-model-merge-jp/

https://arxiv.org/abs/2403.13187
ベイズ学習2

# 共役事前分布
事前分布$p(\omega)$と事後分布$p(\omega|\mathcal{D})$とが同じ関数系になるような事前分布のこと

### 等方的ガウス分布モデル

```math
p(\mathcal{D}|\omega)=\frac{1}{(2\pi\sigma^2)^{\frac{NM}{2}}}exp(-\frac{1}{2\sigma^2}\sum_n\lVert x^{(n)}-\mu \lVert^2)
```

$N$はデータ数、$M$はデータの次元である($x^{(n)} \in \mathbb{R}^M$)。
ここで、平均$\mu$のみをベイズ学習する場合を考える。

```math
\displaylines{
p(\mathcal{D}|\mu)\propto exp(-\frac{1}{2\sigma^2}\sum_n\lVert x^{(n)}-\mu \lVert^2)\\
=exp(-\frac{1}{2\sigma^2}\sum_n\lVert (x^{(n)}-\bar{x})+(\bar{x}-\mu) \lVert^2)\\
=exp(-\frac{1}{2\sigma^2}(\sum_n\lVert x^{(n)}-\bar{x}\lVert^2+N\Vert \bar{x}-\mu\Vert^2 )\\
\propto exp(-\frac{N}{2\sigma^2}\lVert \bar{x}-\mu \lVert^2)\\
\propto \mathcal{N}_M(\mu;\bar{x},\frac{\sigma^2}{N}I_{M})
}
```

$I_{M}$は$M$次元単位行列、$\bar{x}$は標本平均である。$\bar{x}$や各$x^{(n)}$は既知であるため、ベイズ学習をする上では定数扱いである。
ここで、共役事前分布について考える。等方的ガウス分布モデルは、積について閉じているため、事前分布として以下を用いることができる。

```math
p(\mu|\mu_0,\sigma_0^2)=\mathcal{N}_M(\mu;\mu_0,\sigma_0^2I_M)\propto exp(-\frac{1}{2\sigma_0^2}\Vert \mu-\mu_0 \Vert^2)
```

この共役事前分布を用いて計算を進めると、事後分布は以下のように書ける。

```math
p(\mu|\mathcal{D},\mu_0,\sigma_0^2)=\mathcal{N}_M(\mu;\frac{N\sigma^{-2}\bar{x}+\sigma_0^{-2}\mu_0}{N\sigma^{-2}+\sigma_0^{-2}},\frac{1}{N\sigma^{-2}+\sigma_0^{-2}})
```

# 周辺尤度
周辺尤度の計算は、以下によって与えられる。
```math
p(\mathcal{D}|\kappa)=\int_\mathcal{W}{p(\mathcal{D|\omega})p(\omega|\kappa)}d\omega
```

等方的ガウス分布では、計算を進めると以下のように書ける。

```math
p(\mathcal{D}|\mu_0,\sigma_0^2)=\frac{1}{(2\pi\sigma^{2})^{MN/2}}
\bigg( \frac{\sigma^2}{N\sigma_0^2+\sigma^2} \bigg)^{M/2}exp\bigg( \frac{(N\sigma^{-2}\bar{x}+\sigma_0^{-2}\mu_0)^2}{2(N\sigma^{-2}+\sigma_0^{-2})}-\frac{N\sigma^{-2}\bar{x^2}+\sigma_0^{-2}\mu_0^2}{2} \bigg)
```

# 経験ベイズ学習
経験ベイズ学習では、周辺尤度の最大化を行う。
これは、ベイズ自由エネルギーの最小化として扱うことができる。
```math
\hat{\kappa}=argmin_\kappa\big(-log(p(\mathcal{D}|\kappa))\big)
```

等方的ガウス分布に関して、$\mu_0$のみの学習を行うと$\mu_0=\bar{x}$が得られる。
これは、最尤推定の結果と一致する。
OpemCVでimshowしたときとimwriteしたときで色が違うときの原因と対策

# 事件
アルファ付きpng画像を重ねて表示したいときに事件は起きた。imreadで背景画像を読み込んだ時には大丈夫なのに、真っ白なキャンバスを生成するためにnp.zerosを使ったときに問題発生。cv2.cvshowで表示したときに色がおかしくなる。**cv2.imwriteで書き出すと思っていた通りの色が出る**

https://qiita.com/smatsumt/items/923aefb052f217f2f3c5

この記事を参考に(ほぼコピペ)、背景画像を読み込むところを、真っ白い画像を生成することによって代替した。
真っ白い画像を生成する(4,5行目)のは**適当にググった** ←伏線
```py:問題のソースコード（間違ったソースコード）
import cv2
import numpy as np

frame = np.zeros((720, 1280, 3)) #真っ黒画像(ゼロ埋め)
frame += 255 #真っ白画像を生成

#frame = cv2.imread("bg.jpg") #特定の画像を読み込むわけではない
png_image = cv2.imread("alpha.png", cv2.IMREAD_UNCHANGED)  # アルファチャンネル込みで読み込む

# 貼り付け先座標の設定。とりあえず左上に
x1, y1, x2, y2 = 0, 0, png_image.shape[1], png_image.shape[0]

# 合成!
frame[y1:y2, x1:x2] = frame[y1:y2, x1:x2] * (1 - png_image[:, :, 3:] / 255) + \
                      png_image[:, :, :3] * (png_image[:, :, 3:] / 255)

cv2.imwrite("out.png",frame)
cv2.imshow("window",frame)
cv2.waitKey(0)
```
↓alpha.png
![alpha.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719521/a39fc228-aa35-8874-eb5e-b9c895f6bbba.png)

# 結果
↓cv2.imshowで出したウィンドウ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719521/5aa3430f-44d3-c3a7-39a0-d6e9d315219e.png)
↓out.png
![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719521/87497b1e-4d8a-a48b-4b93-3267cdbaff0b.png)

imshowで出したウィンドウは、明らかにおかしい。なんというか、アルファチャンネルが読み込めていないようにも見える(アルファ値255のみが見えているように感じる)。しかし、よく見るとカラフルな線が黒い枠線に重なったところが白抜きされてるなど様子が変だ。(黒い枠線はどう考えてもアルファ値255である)
# 対策
**4行目**で`frame=np.zeros()`としてnp配列を作成して画像としている。どうやらnp.zerosのdtype引数はデフォルトでfloatとなっているらしい。しかしopenCVで使用するのは**np.uint8**らしく、どうやらこれが原因だったらしい。
と、後になって調べてみると、np.zerosで生成するときにほとんどの記事で**dtype=np.uint8**を指定しているではないか。適当にググったのが仇となってしまった。 ←伏線回収
ちなみにunit(ユニット)と見間違えやすいがこれはunsigned intのことである。
```py:対策したソースコード
import cv2
import numpy as np

frame = np.zeros((720, 1280, 3),dtype=np.uint8) #真っ黒画像(ゼロ埋め)
frame += 255 #真っ白画像を生成

#frame = cv2.imread("bg.jpg") #特定の画像を読み込むわけではない
png_image = cv2.imread("alpha.png", -1)  # アルファチャンネル込みで読み込む

# 貼り付け先座標の設定。とりあえず左上に
x1, y1, x2, y2 = 0, 0, png_image.shape[1], png_image.shape[0]

# 合成!
frame[y1:y2, x1:x2] = frame[y1:y2, x1:x2] * (1 - png_image[:, :, 3:] / 255) + \
                      png_image[:, :, :3] * (png_image[:, :, 3:] / 255)

cv2.imwrite("out.png",frame)
cv2.imshow("window",frame)
cv2.waitKey(0)
```
余談だがimreadでアルファチャンネルを読み込むならfilenameの次に-1で良い。こっそり直してみた

# 修正後
↓想像通りの画像をimshowすることができた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719521/99853d85-db5e-335d-28a6-b6037dcc150d.png)
【vue/Nuxt.js】composition APIを使用した子から親へのデータ受け渡しの書き方

**composition API**を使用して子コンポーネントのデータ（イベント）を親コンポーネントに渡す方法についてメモ:writing_hand: 

## defineEmitsで定義する
composition APIでは$emitの役割を持つ変数を作って**defineEmits**でカスタムイベントを定義します。
### 子コンポーネント側
```diff_vue
<script setup>
const emit = defineEmits(['hogeEvent']); //emit以外でもok
const hoge = () =>{
    emit('hogeEvent');
}
</script>
<template>
    <button type="button" @click="hoge">emitテスト</button>
</template>
```
### 親コンポーネント側
親コンポーネント側は定義したカスタムイベント名に処理を書くだけでok。
```diff_vue
<script setup>
const customEvent = () =>{
  console.log('test')
}
</script>
<template>
  <ChiledComponents @hogeEvent="customEvent"></ChiledComponents>
</template>
```

## 参考
[【Vue3 props/emit】コンポーネント間通信](https://reisuta.com/props-emit/)
[defineProps() & defineEmits()](https://ja.vuejs.org/api/sfc-script-setup#defineprops-defineemits)
【問題提起】Qiitaに楽にアウトプットし就活のネタにしてドヤる方法

## 結論

ChatGPTに書いてもらう。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/2107b4c3-d544-1f65-c6d4-d15cf9d6cf78.png">

## これによっておこる問題

AIによる記事が乱立し、Qiitaの信頼性が下がる。

## 解決方法

AIによる自動生成なのかを判定するツールを導入し、記事が公開可能かチェックする。

## 関連

https://www.techno-edge.net/article/2022/12/07/585.html

## チラ裏

最も、今まで

・外部リンクを貼っただけの記事
・ただのメモ書き
・本や別サイトの内容を書き写しただけの記事
・無断翻訳（自動翻訳してコピペ）
・技術とは何の関係もない日記（自分の体重の記録など）

のような記事が何のお咎めもなく放置されていることから運営が動くとは思えない。
（通報しても放置される。）

まあ、私もしょうもないポエムなどを書いているので善人面はできないが…

## チラ裏2

そういや就活で思い出したが、GitHubでコミットログを改竄して草を生やすハック（毎日プログラミングしますよアピールができる）があったなぁ。
本当に馬鹿らしい。

プライベートリポジトリを改竄すればコミットが無意味なものなのか判別できないから、仕事が雑な採用担当者は騙せるかもね。
音声認識中のAndroidの通知音をミュートする方法

# はじめに

AndroidのSpeech Recognizerを利用して音声認識機能を実装する際、音声認識の開始を示すための"ピロン"や"ポロン"といった通知音が自動的に鳴ることがある。これらの音はシステムによって生成されるため、通知音を無効にしてSpeech Recognizerを実行する直接的な方法は存在しない。

しかし、この通知音が頻繁に鳴り、場合によっては邪魔になることもあります。実装したい機能によっては、音を一時的にミュートしたい状況が生じるかもしれない。最近のAndroidバージョンでは、`adjustStreamVolume`メソッドを用いて通知音をミュートするのが良いようだ。 今回の内容はAndroid 9で動作確認した。

## adjustStreamVolumeを使用して音声認識の通知音をミュートする

`adjustStreamVolume`を使用する場合、特に問題なく通知音をミュートすることができる。

```kotlin
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
// 通知音をミュート
audioManager.adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_MUTE, 0)
// ミュートを解除
audioManager.adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0)
```

**参考資料**

https://qiita.com/YusukeIwaki/items/4d9f877ccc5ad835b5cb

## getStreamVolumeを使用して通知音をミュートしようとすると失敗する

`getStreamVolume`を使用して`AudioManager.STREAM_NOTIFICATION`のボリュームを0に設定しようとすると、`java.lang.SecurityException: Not allowed to change Do Not Disturb state`という例外エラーが発生し、操作が失敗する。

```kotlin
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION)
// ボリュームをゼロに設定
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 0, 0)
// ボリュームを元に戻す
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, currentVolume, 0)
```

**参考資料**

https://qiita.com/KAKKA/items/d15cb9187fd1bcca8770
AWS Organizationsの委任管理者の登録で詰まった箇所

## この記事について

- AWS Control Tower の検証中に、管理者の委任作業で詰まった点があったので、その紹介記事です

## 詰まった箇所

- 具体的には、Control Tower の Account Factory Customization (AFC) の検証中に、Service Catalog の管理者を委任する場面です

### Service Catalog 管理者委任のコマンド実行

- [DevelopersIOのAFCの記事](https://dev.classmethod.jp/articles/control-tower-account-factory-customization/)を参考に以下コマンドを CloudShell で実行しました
- AWS公式ドキュメントの[register-delegated-administrator](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/organizations/register-delegated-administrator.html)に詳細の記載があります

```bash
aws organizations register-delegated-administrator \
    --account-id 委任先アカウントID \
    --service-principal servicecatalog.amazonaws.com
```

:::note info
Organizations の管理アカウントからメンバーアカウントに、ポリシー管理の委任が可能です
:::

- 実行した所、以下のエラーが発生しました

```bash
[cloudshell-user@ip-10-130-48-71 ~]$ aws organizations register-delegated-administrator --account-id XXXXXXXXXXX --service-principal servicecatalog.amazonaws.com

An error occurred (ConstraintViolationException) when calling the RegisterDelegatedAdministrator operation: You must enable service access before you delegate an administrator for this service. Call the AWS API EnableAWSServiceAccess first.
```

- エラー内にも記載がありますが、先に「サービスへのアクセスを有効化する」必要がありました

## コマンド再実行

- `register-delegated-administrator`の前に[enable-aws-service-access](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/organizations/enable-aws-service-access.html)を実行します

```bash
[cloudshell-user@ip-10-134-22-228 ~]$ aws organizations enable-aws-service-access --service-principal servicecatalog.amazonaws.com
[cloudshell-user@ip-10-134-22-228 ~]$ aws organizations register-delegated-administrator --account-id XXXXXXXXXXX --service-principal servicecatalog.amazonaws.com
```

### 結果確認

- [list-delegated-administrators](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/organizations/list-delegated-administrators.html)で詳細を確認します
- コマンド実行前は以下の形で表示

```bash
[cloudshell-user@ip-10-134-22-228 ~]$ aws organizations list-delegated-administrators
{
    "DelegatedAdministrators": [
    ]
}
```

- コマンド実行後は以下の形で表示

```bash
[cloudshell-user@ip-10-134-22-228 ~]$ aws organizations list-delegated-administrators
{
    "DelegatedAdministrators": [
        {
            "Id": "XXXXXXXXXXX",
            "Arn": "arn:aws:organizations::XXXXXXXXXXX:account/o-r1dheg1ess/XXXXXXXXXXX",
            "Email": "sample@example.com",
            "Name": "ServiceCatalogAdmin",
            "Status": "ACTIVE",
            "JoinedMethod": "CREATED",
            "JoinedTimestamp": "2024-04-04T13:57:48.830000+00:00",
            "DelegationEnabledDate": "2024-04-06T03:01:39.347000+00:00"
        }
    ]
}
```

### AWSマネジメントコンソール上からの確認

- Organizations 管理者アカウントの`AWS Organizations` > `サービス`からも、Service Catalog へのアクセスが有効になっている事が確認できます

![enable-service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411902/a25d080c-0a2f-3a7a-3a4d-06beea3da57f.png)

### 補足

Organizations のサービスアクセスの許可や管理者委任のコマンドについては、[こちらの記事](https://dev.classmethod.jp/articles/manage-aws-organizations-service-integration-and-delegation-from-cli/)が参考になりました
[Google Calendar API(V3)] Javaでカレンダーのユーザー設定情報の変更を監視する

Google Calendar API V3(Java)を使用して、
Googleカレンダーのユーザー設定情報の変更を監視する方法
についてご紹介します。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Google Calendar API(V3)] JavaでCalendar APIを使う](https://qiita.com/doran/items/c735c7b05c0a2ed4bfdb)
を参照ください。
:::

|No||目次|
|---|---|---|
|1||[設定情報の変更を監視](#1-設定情報の変更を監視)|
||1|[スコープ](#11-スコープ)|
||2|[実行](#12-実行)|
||3|[レスポンスの内容](#13-レスポンスの内容)|
|2||[設定情報の監視を停止](#2-設定情報の監視を停止)|
|3||[変更通知を受信](#3-変更通知を受信)|

## 1. 設定情報の変更を監視
Googleカレンダーのユーザー設定情報の変更を監視します。

### 1.1. スコープ
このAPIを実行するには、以下のいずれかのスコープを指定してください。
```
CalendarScopes.CALENDAR_READONLY
CalendarScopes.CALENDAR
CalendarScopes.CALENDAR_SETTINGS_READONLY
```
[⧉[Google Calendar API(V3)] JavaでCalendar APIを使う(2.2 Driveインスタンスを取得)](https://qiita.com/doran/items/c735c7b05c0a2ed4bfdb#22-calendarインスタンスを取得)
でスコープを指定してください。

### 1.2. 実行

```java
public static void main(String[] args) throws Exception{
    Calendar calendar = getCalendar();
    Calendar.Settings settings = calendar.settings();
    
    Channel content = new Channel();
    content.setId("チャンネルを識別するUUID");
    content.setType("web_hook");
    content.setAddress("変更通知が配信されるURL");
    Calendar.Settings.Watch watch = settings.watch(content);
    
    Channel res = watch.execute();
    System.out.println(res);
}
```
#### 1.2.1. HTTPリクエスト
POST:　https:\//www.googleapis.com/calendar/v3/users/me/settings/watch
が実行されます。

#### 1.2.2. クエリパラメータ
クエリパラメータはありません。

#### 1.2.3. リクエストボディ
Channelのsetメソッドにより、クエリパラメータを追加できます。

|メソッド|引数|説明|
|---|---|---|
|setId|String|【必須】チャンネルを識別するUUID|	
|setAddress|String|【必須】変更通知が配信されるURL|
|setType|String|【必須】このチャンネルで使用される配信方法の種類<br>"web_hook"（または"webhook"）のみ|
|setToken|String|このチャンネル経由で通知と一緒に対象のアドレスに配布される任意の文字列|	
|setParams|Map\<String,String\>|配信チャンネルの操作を制御する追加のパラメータ|	
|setExpiration|Long|通知チャンネルの有効期間（秒）|

### 1.3. レスポンスの内容

#### Channel

|メソッド|戻り値|説明|
|---|---|---|
|getKind|String|リソースの種類<br>固定文字列："api#channel"|
|getId|String|このチャンネルを識別するUUID|	
|getResourceId|String|このチャンネルで監視するリソースを識別するID|
|getResourceUri|String|監視対象のリソースのバージョン固有のID|	
|getToken|String|このチャンネル経由で通知と一緒に対象のアドレスに配布される任意の文字列|
|getExpiration|long|通知チャンネルの有効期限|

## 2. 設定情報の監視を停止
Googleカレンダーのユーザー設定情報の監視を停止します。

変更通知の停止は、
[⧉[Google Calendar API(V3)] Javaで変更通知を停止する](https://qiita.com/doran/items/3c3ad1d6406d8fac634e)
の記事を参照ください。

## 3. 変更通知を受信
アクセス制御ルール(ACL)の変更があった場合、登録したURLへPOSTされます。
HTTPヘッダーの「x-goog」から始まるヘッダーの内容で確認できます。

|ヘッダ|内容|例|
|---|---|---|
|x-goog-channel-expiration|通知チャネルの有効期限|Tue, 02 Apr 2024 03:29:03 GMT|
|x-goog-channel-id|チャンネルを識別するUUID|test|
|x-goog-message-number|通知チャネルのこのメッセージを識別する整数|130992|
|x-goog-resource-id|チャンネルで監視するリソースを識別するID|sek_NpGJCK4wPi9TBOCvBF68lCo|
|x-goog-resource-state|通知をトリガーした新しいリソースの状態<br>sync,exists,not_exists|exists|
|x-goog-resource-uri|監視対象リソースの API バージョン固有の識別子|`https://www.googleapis.com/calendar/v3/users/me/settings?alt=json`|

<br>
<br>
おしまい。。
リートン で elixir を学ぶ （その3）text ファイルの read

こちらで行ったのと同じことを [wrtn](wrtn.jp) で行いました。
[ChatGPT で elixir を学ぶ　（その5）text ファイルの read](https://qiita.com/ekzemplaro/items/6cab9f3f96f1b31db52d)

## Python のプログラム

```py:text_read.py
#! /usr/bin/python
#
import	sys
#
# --------------------------------------------------------------------
def dict_display_proc(dict_aa):
	for key in sorted(dict_aa.keys()):
		unit = dict_aa[key]
		name = unit['name']
		str_out = str(key) +"\t"+ str(name)
		str_out += "\t" + str(unit['population'])
		str_out += "\t" + str(unit['date_mod'])
		print(str_out)
# --------------------------------------------------------------------
def text_read_proc(file_in):
#
	fp_in = open(file_in,encoding='utf-8')
	lines = fp_in.readlines()
	fp_in.close()
#
	dict_aa = {}
	for line in lines:
		if (5 < len(line)):
			cols= line[:-1].split('\t')
			if (3 < len(cols)):
				try:
					if (cols[0][0] == "t"):
						dict_unit = {'name': cols[1], \
			'population':int (cols[2]),'date_mod':cols[3]}
						dict_aa[cols[0]] = dict_unit
				except:
					sys.stderr.write \
				("*** error *** %s ***\n" % file_in)
					sys.stderr.write \
				("*** %s ***\n" % line)
#
	return	dict_aa
#
# --------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
file_in = sys.argv[1]
#
try:
	dict_aa = text_read_proc(file_in)
	dict_display_proc(dict_aa)
except Exception as ee:
	sys.stderr.write("*** error *** in text_read_proc ***\n")
	sys.stderr.write(str(ee) + '\n')
#
sys.stderr.write("*** 終了 ***\n")
# --------------------------------------------------------------------
```

## wrtn が作成したプログラム
wrtn では、メインプログラムが作成されませんでした。

次の部分は修正しました。

```elixir
#        date_mod: date_mod
        date_mod: String.trim_trailing(date_mod)
```

```elixir:text_read.exs
defmodule TextReader do
  def read_file(file_path) do
    file_path
    |> File.stream!()
    |> Enum.reduce(%{}, fn line, acc ->
      process_line(line, acc)
    end)
  end

  defp process_line(line, acc) do
    [key, name, population, date_mod | _] = String.split(line, "\t")
    if String.starts_with?(key, "t") do
      Map.put(acc, key, %{
        name: name,
        population: String.to_integer(population),
#        date_mod: date_mod
        date_mod: String.trim_trailing(date_mod)
      })
    else
      acc
    end
  end

  def display(dict_aa) do
    dict_aa
    |> Map.to_list()
    |> Enum.sort()
    |> Enum.each(fn {key, val} ->
      IO.puts("#{key}\t#{val.name}\t#{val.population}\t#{val.date_mod}")
    end)
  end
end
```

次のメインプログラムを加えました。

```exs
IO.puts :stderr,"*** 開始 ***"
[file_in | _] = System.argv()
IO.puts :stderr,file_in

dict_aa = TextReader.read_file(file_in)
TextReader.display(dict_aa)
IO.puts :stderr,"*** 終了 ***"
```

入力ファイル

```text:cities.txt
t2381	名古屋	93514	1910-5-17
t2382	豊橋	31296	1910-9-10
t2383	岡崎	17459	1910-2-14
t2384	一宮	62542	1910-7-9
```

実行結果

```text
$ ./text_read.exs cities.txt
*** 開始 ***
cities.txt
t2381	名古屋	93514	1910-5-17
t2382	豊橋	31296	1910-9-10
t2383	岡崎	17459	1910-2-14
t2384	一宮	62542	1910-7-9
*** 終了 ***
```
「頭のいい人が話す前に考えていること」・ 「超・箇条書き」を読んだ

## 今回読んだ本
「[頭のいい人が話す前に考えていること](https://www.amazon.co.jp/%E9%A0%AD%E3%81%AE%E3%81%84%E3%81%84%E4%BA%BA%E3%81%8C%E8%A9%B1%E3%81%99%E5%89%8D%E3%81%AB%E8%80%83%E3%81%88%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8-%E5%AE%89%E9%81%94-%E8%A3%95%E5%93%89/dp/4478116695)」  
「[超・箇条書き](https://www.amazon.co.jp/%E8%B6%85%E3%83%BB%E7%AE%87%E6%9D%A1%E6%9B%B8%E3%81%8D%E2%80%95%E2%80%95%E2%80%95%E3%80%8C10%E5%80%8D%E9%80%9F%E3%81%8F%E3%80%81%E9%AD%85%E5%8A%9B%E7%9A%84%E3%81%AB%E3%80%8D%E4%BC%9D%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-%E6%9D%89%E9%87%8E-%E5%B9%B9%E4%BA%BA/dp/4478068674)」


# お客様と円滑にコミュニケーションを取るための読書メモ

ビジネスにおける成功は、効果的なコミュニケーション技術にかかっています。最近読んだ上記の書籍から学んだコミュニケーションの技術や資料作成のヒントをまとめたので共有します。

### コミュニケーションを円滑に進めるためのポイント

- **相手に尽くす姿勢を見せることの重要性**  
相手に「この人は自分のために尽くしてくれている」と感じさせることで、信頼関係が築かれ、コミュニケーションがスムーズに進むようになります。これは、相手の話を丁寧に聞き、相手のニーズに対して真摯に応える姿勢から生まれます。
　前職で営業をしていた時も、初めて取引先の会社の社長とお話ししたおき、前の担当者がもらっていた会社パンフレットを読み込んだ上で話したら「よく調べてくれているね」とお言葉をいただき、会話がスムーズになったことがあります。

- **具体的な質問をすることの力**  
「御社の課題は何ですか？」というようなオープンな質問は、広すぎて答えづらいことがあり、「特にないかな〜」という回答につながってしまう恐れがあります。それよりも、事前の調査に基づいた具体的な仮説を提示し、「御社のHPを見て、レガシー商品の撤退に苦労されていると感じましたが、それについてどのようにお考えですか？」等と質問する方が、相手は具体的な反応を返しやすくなります。こうしたアプローチにより、お客様に自社の課題をより深く、具体的に考えるきっかけを提供し、有意義な情報交換へとつながります。

- **情報の根拠をしっかりと持つことの大切さ**  
ビジネスの場では、確かな根拠に基づく情報提供が求められます。根拠の薄い情報や他人の意見にすぐに流される姿勢は、プロフェッショナルとしての信頼性を損なう原因となります。情報には常にデータや事実を基にした裏付けを用意し、自信を持って提供しましょう。

### 資料作成の際に心がけるべきポイント

- **構成に関する考慮**  
資料は、大きな議題から具体的な議題へと順を追って説明することで、理解しやすくなります。起→承→転→結の流れだと、読み手としては話の方向性がどこに行くのかわからず不安を抱えたま資料を読まなければならなくなります。1番初めにしっかり「結」を示してあげるとその後の理解がスムーズになります。

- **時系列の整理**  
情報を時系列に沿って整理することで、過去の経緯、現在の状況、未来の展望が明確になり、聞き手にとって理解しやすくなります。これにより、プレゼンテーションや資料がより流動的で、論理的なストーリーを持つようになります。

- **副詞ではなく具体的な数字を使う**  
情報を提示する際に、「かなりの改善が見られる」といった曖昧な表現を避け、「改善後の生産性が前年比で３倍に増加した」や「参加者数が前回のイベントから400人増加した」といった具体的な数字を用いることの大切さを学びました。これは、受け手に明確なイメージを与え、説得力のあるコミュニケーションを実現します。数字を用いることで、提供する情報の具体性が増し、相手に対する信頼性も高まります。

- **AでなくB(否定) や AよりもB(比較)を使うことで理解しやすくする**
例えば、企業のビジネス目標を｢今年の目標は売上を伸ばすことに注力します｣と表現したとします。読み手は｢営利企業なんだし当たり前じゃないか?｣と捉える可能性が大いにあり、いまいち読み手に真意が伝わりません。ここで、**今年は利益を追求することではなく、売上を伸ばすことに注力します**と表現した場合、どうでしょうか。｢今は売上を伸ばして市場のシェアを拡大するフェーズで、利益の追求はその後に行うのかな｣と理解がしやすくなります。
文章が短ければいいわけではなくて、前提条件を知らずフラットな気持ちで読む読者の理解の仕方がぶれないようにする必要があるということですね。

### 結論

効果的なコミュニケーションは、相手への理解と敬意、情報の正確さと具体性に基づいています。ポイントを心がけることで、お客様との関係を深め、ビジネスの成功に繋がる土台を築くことができそうです。

### 感想
　コミュニケーションなんて生きていたら普段からやっているし、前職でお客様と接する機会もあったわけだし、社内通達文書なんて山ほど書いてきたし箇条書きも大事なことを「・」から始めて書けばそれっぽくなるし。特別できているとも思っていないが、出来ていないとか難しいとは思っていなかった・・・というか**難しく考えないことにして本質を避けてきたのかもしれないな**と思いました。こういう本をいくつか読んで、素直に実践してみて自分にあったスタイルを見つけたいものですね。
　英語の文章の組み立て方とかも好きなので、別の機会に紹介したいと思います。
20240406 日記 pipenvについて、githubのlockについて

### pipenvについて

Pipfileというのがあって、そこに環境ごとに使うpipモジュールを書いていく
そして、`pipenv install` (`--dev`とかつけるとその環境用の）とすると、Pipfileに書かれたモジュールが閉じられた仮想環境向けにインストールされる、という仕組みらしい

これだけ聞くとrubyのbundlerに似てる、と思った。けどbundlerはグローバルにgemをインストールしてくる（`--path vender/bundle`とかでグローバルに入れない方法もあるのは知ってるけど）
Rubyではグローバルに入れる使い方だけど、それで問題になったことはない
一方pythonはなんとなく仮想環境つかってグローバルを汚染しないようにする、という感覚だったけど、何が違うのだろう？

と不思議におもったのでまずBundlerで調べると、まさに自分が思った通りのことをまとめてくれている方がいた
参考：[bundle install時に--path vendor/bundleを付ける必要性は本当にあるのか、もう一度よく考えてみよう #Ruby - Qiita](https://qiita.com/jnchito/items/99b1dbea1767a5095d85)

Rubyの世界では仮想環境的なことは不要、という話
ではなぜPythonでは必要なのだろうか？
わからん

### githubのlockに関して
こないだ書いた日記の「[20240325 gitあれこれ、プロンプト、ブランチへのpush禁止、aliasに引数 #Git - Qiita](https://qiita.com/tontoroRR/items/e40484e97f4e96177dc1#main%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E7%9B%B4%E6%8E%A5push%E3%82%92%E7%A6%81%E6%AD%A2%E3%81%99%E3%82%8B)」、ブランチへの直接のpushはできなくなったが、他ブランチからのmergeも赤くなってすんなりできなくなった
無理やりマージみたいなチェックをするとできるが、そんなのは求めてない機能だ
ちょっと思ってたのと違った
なんかどこかで設定があるのかもだけど、とりあえずブランチのLockは外した
WordPressにおけるグローバル変数$postについて

WordPressにおけるグローバル変数 `$post` は、WordPressのループ中で現在処理している投稿（またはカスタムポストタイプ）のオブジェクトを指します。この変数はWordPressコアによって自動的に設定され、投稿の詳細な情報を含んでいます。例えば、投稿ID、タイトル、内容（コンテント）、投稿日時、スラッグなどが含まれます。

## グローバル変数 `$post` の役割

- 投稿データのアクセス：テンプレートファイルやプラグイン、テーマの関数内で、現在表示または処理中の投稿データにアクセスするために使用されます。
- テンプレートタグのコンテキスト： `the_title()`, `the_content()`, `the_permalink()` などのテンプレートタグは、 `$post` 変数からデータを取得し、現在の投稿に関連する情報を出力します。

## どのように機能するか

WordPressのページを表示する際、メインのクエリ（WordPressループ）を実行して投稿データを取得します。このとき、ループの各イテレーションで `$post` 変数は現在の投稿オブジェクトで更新されます。これにより、テンプレートタグが正しい投稿データに基づいて動作することが保証されます。

例えば、WordPressの標準ループでは次のように `$post` 変数が使われます。

```php
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        // ここで $post 変数は現在の投稿を指している
        the_title();  // 現在の投稿のタイトルを表示
        the_content(); // 現在の投稿の内容を表示
    endwhile;
endif;
```

`the_post()` 関数は内部でグローバル変数 `$post` を現在処理中の投稿データで更新します。この変数はループの現在のイテレーションのみ影響し、ループが次のイテレーションに進むと `$post` は新しい投稿データで更新されます。

## カスタムクエリとグローバル変数 `$post`

カスタムクエリを使用する場合（例えば `get_posts()` や `WP_Query` を使った場合）、 `setup_postdata($post)` 関数を呼び出して手動でグローバル変数 `$post` を更新することがあります。これにより、カスタムクエリの結果に基づいてテンプレートタグを適切に機能させることができます。

```php
$myposts = get_posts(array('numberposts' => 5));
foreach ($myposts as $post) : setup_postdata($post);
    // ここで $post は get_posts から取得した投稿を指す
    the_title();
    the_content();
endforeach;
wp_reset_postdata();
```

ここで、 `wp_reset_postdata()` の呼び出しは非常に重要です。これはカスタムクエリの後に `$post` を元のメインクエリの現在の投稿データに戻すために使用され、グローバル変数の状態を正常に保ちます。
配列関数・2回目

## はじめに

配列関数を整理する。2回目。

### array_search
特定の値を検索する

```php:array_search.php
$data = ['PHP', 'Javascript', 'PHP', 'Java', 'C#', '15'];
$data2 = ['X' => 10, 'Y' => 20, 'Z' => 30];
var_dump(array_search('Javascript', $data); //int(1)
var_dump(array_search('PHP', $data); //int(0)
var_dump(array_search('Java', $data); //bool(false)
var_dump(array_search(15, $data); //int(5)
var_dump(array_search(15, $data, true); //bool(false)
var_dump(array_search(10, $data2); //string(1) "X"
```

### in_array

要素の有無を判定する

```php:in_array.php
$data = ['PHP', 'Javascript', 'PHP', 'Java', 'C#', '15'];
var_dump(in_array('PHP', $data); //true
```

### sort

配列の内容を並べ替える

```php:sort.php
$data = ['Tennis', 'Swimming', 'Soccer', 'Baseball'];
sort($data, SORT_STRING);
print_r($data); // ['Baseball', 'Swimming', 'Soccer', 'Tennis']
rsort($data, SORT_STRING);
print_r($data); // ['Tennis', 'Soccer', 'Swimming', 'Baseball']

$data2 = ['Tennis' => 1, 'Swimming' => 1, 'Soccer' => 11, 'Baseball' => 9];
sort($data2, SORT_NUMERIC);
print_r($data2); // [1, 1, 9, 11]

$data3 = ['Tennis' => 1, 'Swimming' => 1, 'Soccer' => 11, 'Baseball' => 9];
asort($data3, SORT_NUMERIC);
print_r($data3); // [[Tennis] => 1 [Swimming] => 1 [Baseball] => 9 [Soccer] => 11]
ksort($data3, SORT_STRING);
print_r($data3); // [[Baseball] => 9 [Soccer] => 11 [Swimming] => 1 [Tennis] => 1]
```
cscの作法 その480

# 概要
cscの作法、調べてみた。
1秒ごとにマウスカーソル下のウィンドウのタイトルとクラス名を取得してテキストボックスに表示します。

# 参考にしたページ

https://qiita.com/nekotadon/items/f376d17de85dfb84fbd5

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8278272d-92c9-0e36-db2e-f78e6da81962.png)

# サンプルコード

```
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace App
{
	public partial class Form1: Form {
		internal static class NativeMethods {
			[DllImport("user32.dll", CharSet = CharSet.Unicode)]
			public static extern int GetWindowText(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder lpString, int nMaxCount);
			[DllImport("user32.dll", CharSet = CharSet.Unicode)]
			public static extern int GetClassName(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder lpClassName, int nMaxCount);
			[DllImport("user32.dll")]
			[return: MarshalAs(UnmanagedType.Bool)]
			public static extern bool GetCursorPos(out POINT lpPoint);
			[DllImport("user32.dll")]
			public static extern IntPtr WindowFromPoint(POINT Point);
		}
		[StructLayout(LayoutKind.Sequential)]
		public struct POINT {
			public int x;
			public int y;
		}
		TextBox textBox = new TextBox {
			Multiline = true,
			Dock = DockStyle.Fill,
			ScrollBars = ScrollBars.Both,
			WordWrap = false
		};
		Timer timer = new Timer();
		POINT point;
		public Form1() {
			TopMost = true;
			Controls.Add(textBox);
			timer.Enabled = true;
			timer.Interval = 1000;
			timer.Tick += new EventHandler(timer_Tick);
			//FormClosing += new EventHandler(Form1_Closing);
		}
		private void timer_Tick(Object sender, EventArgs e) {
			NativeMethods.GetCursorPos(out point);
			IntPtr hWnd;
			hWnd = NativeMethods.WindowFromPoint(point);
			if (hWnd != IntPtr.Zero)
			{
				StringBuilder windowTitle = new StringBuilder(256);
				NativeMethods.GetWindowText(hWnd, windowTitle, windowTitle.Capacity);
				StringBuilder className = new StringBuilder(256);
				NativeMethods.GetClassName(hWnd, className, className.Capacity);
				textBox.Text = windowTitle.ToString() + Environment.NewLine + className.ToString();
			}
		}
		private void Form1_Closing(object sender, FormClosingEventArgs e) {
			timer.Stop();
			timer.Dispose();
		}
		[STAThread]
		static void Main() {
			Application.Run(new Form1());
		}
	}
}





```


以上。
react-router-domのRouteのexactにエラー　型 '{ exact: true; path: string; element: Element; }' を型 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)' に割り当てることはできません。  

## はじめに
```
型 '{ exact: true; path: string; element: Element; }' を型 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)' に割り当てることはできません。
  プロパティ 'exact' は型 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)' に存在しません。ts(2322)
```

のエラー発生

![スクリーンショット 2022-04-25 22.42.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641679/43a208ec-ca90-1f9c-95b4-41713046b868.png)


## 結論
react-router-domのｖ６になり、exactを記述しなくても完全一致となったため、exactは不要になっていた。削除することで対応する。


## おわりに
Routeにはexactを記述する印象があったので、少しインパクトがあった。
それくらい当たり前にexactを書くようになっていたため、デフォルトで完全一致になったということだと思う。
AtCoder典型90を難易度順にまとめた（★５〜７）

# What's?
AtCoderの[競プロ典型90問](https://atcoder.jp/contests/typical90)を公式難易度★印順にまとめました。
もし間違っていた場合はお知らせ頂けると幸いです。

記事の重さの都合上★２〜４と★５〜７で記事を分けています。

https://qiita.com/Hiro_Gt/items/09fd33d13e4ccb5f59e4

## ★５

https://atcoder.jp/contests/typical90/tasks/typical90_f

https://atcoder.jp/contests/typical90/tasks/typical90_m

https://atcoder.jp/contests/typical90/tasks/typical90_u

https://atcoder.jp/contests/typical90/tasks/typical90_ac

https://atcoder.jp/contests/typical90/tasks/typical90_ad

https://atcoder.jp/contests/typical90/tasks/typical90_aj

https://atcoder.jp/contests/typical90/tasks/typical90_ak

https://atcoder.jp/contests/typical90/tasks/typical90_am

https://atcoder.jp/contests/typical90/tasks/typical90_ay

https://atcoder.jp/contests/typical90/tasks/typical90_bd

https://atcoder.jp/contests/typical90/tasks/typical90_bh

https://atcoder.jp/contests/typical90/tasks/typical90_bn

https://atcoder.jp/contests/typical90/tasks/typical90_bp

https://atcoder.jp/contests/typical90/tasks/typical90_bu

https://atcoder.jp/contests/typical90/tasks/typical90_cc

https://atcoder.jp/contests/typical90/tasks/typical90_ch

https://atcoder.jp/contests/typical90/tasks/typical90_ci



## ★６

https://atcoder.jp/contests/typical90/tasks/typical90_i

https://atcoder.jp/contests/typical90/tasks/typical90_k

https://atcoder.jp/contests/typical90/tasks/typical90_o

https://atcoder.jp/contests/typical90/tasks/typical90_s

https://atcoder.jp/contests/typical90/tasks/typical90_ae

https://atcoder.jp/contests/typical90/tasks/typical90_as

https://atcoder.jp/contests/typical90/tasks/typical90_aw

https://atcoder.jp/contests/typical90/tasks/typical90_bb

https://atcoder.jp/contests/typical90/tasks/typical90_be

https://atcoder.jp/contests/typical90/tasks/typical90_bj

https://atcoder.jp/contests/typical90/tasks/typical90_bv

https://atcoder.jp/contests/typical90/tasks/typical90_cb

https://atcoder.jp/contests/typical90/tasks/typical90_ce

https://atcoder.jp/contests/typical90/tasks/typical90_cj



## ★７

https://atcoder.jp/contests/typical90/tasks/typical90_e

https://atcoder.jp/contests/typical90/tasks/typical90_q

https://atcoder.jp/contests/typical90/tasks/typical90_w

https://atcoder.jp/contests/typical90/tasks/typical90_y

https://atcoder.jp/contests/typical90/tasks/typical90_ai

https://atcoder.jp/contests/typical90/tasks/typical90_an

https://atcoder.jp/contests/typical90/tasks/typical90_ao

https://atcoder.jp/contests/typical90/tasks/typical90_au

https://atcoder.jp/contests/typical90/tasks/typical90_ba

https://atcoder.jp/contests/typical90/tasks/typical90_bg

https://atcoder.jp/contests/typical90/tasks/typical90_bm

https://atcoder.jp/contests/typical90/tasks/typical90_bs

https://atcoder.jp/contests/typical90/tasks/typical90_by

https://atcoder.jp/contests/typical90/tasks/typical90_ck

https://atcoder.jp/contests/typical90/tasks/typical90_cl
AtCoder典型90を難易度順にまとめた（★２〜４）

# What's?
AtCoderの[競プロ典型90問](https://atcoder.jp/contests/typical90)を公式難易度★印順にまとめました。
もし間違っていた場合はお知らせ頂けると幸いです。

記事の重さの都合上★２〜４と★５〜７で記事を分けています。

https://qiita.com/Hiro_Gt/items/205ed7d492185bf15d38

# 難易度順まとめ

## ★２

https://atcoder.jp/contests/typical90/tasks/typical90_d

https://atcoder.jp/contests/typical90/tasks/typical90_j

https://atcoder.jp/contests/typical90/tasks/typical90_v

https://atcoder.jp/contests/typical90/tasks/typical90_x

https://atcoder.jp/contests/typical90/tasks/typical90_aa

https://atcoder.jp/contests/typical90/tasks/typical90_ag

https://atcoder.jp/contests/typical90/tasks/typical90_bc

https://atcoder.jp/contests/typical90/tasks/typical90_bi

https://atcoder.jp/contests/typical90/tasks/typical90_bo

https://atcoder.jp/contests/typical90/tasks/typical90_bz



## ★３

https://atcoder.jp/contests/typical90/tasks/typical90_b

https://atcoder.jp/contests/typical90/tasks/typical90_g

https://atcoder.jp/contests/typical90/tasks/typical90_n

https://atcoder.jp/contests/typical90/tasks/typical90_p

https://atcoder.jp/contests/typical90/tasks/typical90_r

https://atcoder.jp/contests/typical90/tasks/typical90_t

https://atcoder.jp/contests/typical90/tasks/typical90_af

https://atcoder.jp/contests/typical90/tasks/typical90_al

https://atcoder.jp/contests/typical90/tasks/typical90_ar

https://atcoder.jp/contests/typical90/tasks/typical90_at

https://atcoder.jp/contests/typical90/tasks/typical90_av

https://atcoder.jp/contests/typical90/tasks/typical90_ax

https://atcoder.jp/contests/typical90/tasks/typical90_az

https://atcoder.jp/contests/typical90/tasks/typical90_bl

https://atcoder.jp/contests/typical90/tasks/typical90_bq

https://atcoder.jp/contests/typical90/tasks/typical90_bw

https://atcoder.jp/contests/typical90/tasks/typical90_bx

https://atcoder.jp/contests/typical90/tasks/typical90_ca

https://atcoder.jp/contests/typical90/tasks/typical90_cd

https://atcoder.jp/contests/typical90/tasks/typical90_cf



## ★４

https://atcoder.jp/contests/typical90/tasks/typical90_a

https://atcoder.jp/contests/typical90/tasks/typical90_c

https://atcoder.jp/contests/typical90/tasks/typical90_h

https://atcoder.jp/contests/typical90/tasks/typical90_l

https://atcoder.jp/contests/typical90/tasks/typical90_z

https://atcoder.jp/contests/typical90/tasks/typical90_ab

https://atcoder.jp/contests/typical90/tasks/typical90_ah

https://atcoder.jp/contests/typical90/tasks/typical90_ap

https://atcoder.jp/contests/typical90/tasks/typical90_aq

https://atcoder.jp/contests/typical90/tasks/typical90_bf

https://atcoder.jp/contests/typical90/tasks/typical90_bk

https://atcoder.jp/contests/typical90/tasks/typical90_br

https://atcoder.jp/contests/typical90/tasks/typical90_bt

https://atcoder.jp/contests/typical90/tasks/typical90_cg
Git LFSは無制限のクラウドか？

# はじめに

gitを用いて開発を行うときに、画像、動画、音声、巨大なバイナリファイル等をgithubに上げたくなる場合があります。

しかし実は、githubに上げられるデータには制限が設けられています

https://docs.github.com/ja/repositories/working-with-files/managing-large-files/about-large-files-on-github

具体的には、

・100MBを超えるfileはpush出来ない
・レポジトリあたり5GBまでのデータしかpush出来ない

という制約があります。

しかし、画像、動画、音声、バイナリファイルで100MBを超えるデータは多く、このようなデータをgithubに上げられないのはとても不便です。

そこで、Git LFSという拡張機能を利用することによってこのような問題を解決することができます。


# Git LFSとは

Git LFSとはGit Large File Storage (LFS)のことで、巨大なファイルをGitのポインターファイルに変更する機能です。

https://git-lfs.com/

つまり、巨大なファイルをGitに上げて、Gitのファイルが保存されている場所のポインターを巨大なファイルと入れ替える機能です。

![graphic.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557107/c2043ab6-0434-107e-fbe8-0b172b61dd37.gif)

Git LFSを使うことによって本来はgitに上げることができないファイルをgitで管理することができるようになります。

git lfsを使用するためには、

```shell:PowerShell
git lfs install
```

をPowerShellに打ち込んでください。

Git LFSでファイルを管理したい場合は、

```shell:PowerShell
git lfs track "<管理したいファイル>"
```

をPowerShellに打ち込んでください。管理したいファイルはワイルドカードで指定することができます。

コマンドを打ち込むと.gitattributesというファイルが追加されます。

このファイルにはGit LFSで管理されるファイルが書かれており、このファイルを削除するとGit LFSでのファイル管理が解除されます。

Git LFSで管理してるファイルの管理をやめたい場合は、

```shell:PowerShell
git lfs untrack "<管理をやめたいファイル>"
```

をPowerShellに打ち込んでください。

# Git LFSに制限があるのか

では、Git LFSを使用すれば無料で巨大なファイルを無制限にGitに上げることができるのでしょうか？

残念ながら、Git LFSには制限がつけられています。

まずGit LFSでも5GiBを超えるファイルは保存することが出来ません。5GiBを超えるファイルを保存しようとするとサイレントに拒否されるそうです。

・無料のストレージは1 GiB
・無料帯域は1 GiB/月

https://docs.github.com/ja/repositories/working-with-files/managing-large-files/about-storage-and-bandwidth-usage

これらは、レポジトリ単位でなく、アカウント毎にカウントされます。

順に説明していきます。

# ストレージについて

全てのユーザーは無料のストレージを1 GiBを持っています。

これは簡単に言うと、合計1 GiBのファイルをGit LFSにアップロードすることができるということです。

しかし、これには注意が必要で他の人が自分のリポジトリにプッシュしたときもリポジトリの所有者である自分のストレージが消費されます。

また、注意すべきこととして、同じファイルでも変更を加えてもう一度プッシュすると、ファイルのサイズ分もう一度ストレージから消費されます。


# 帯域について

全てのユーザーは無料の帯域を1 GiBを持っています。

これは簡単に言うと、合計1 GiBのファイルをGit LFSからダウンロードができるということです。

しかし、これには注意が必要で他の人が自分のリポジトリをプルしたときもリポジトリの所有者である自分の帯域が消費されます。

また、注意すべきこととして、所有者がファイルに変更を加えた後、もう一度プルするとファイルのサイズ分もう一度帯域から消費されます。

# ストレージと帯域の回復

帯域は毎月無料使用枠が回復します(繰り越しはしません)。しかし、ストレージは課金をしないといつまでも回復しません。

Githubに巨大ファイルを共有する前提で開発するとなるとそれ相応のお金がかかる事になります。


# おわりに

Git LFSを使い始めた当初は、いくらでもGitに巨大なファイルを上げることができると思っていましたが、githubも営利企業である限り、そんなことはありませんでした。

世の中そんな甘くないですね...