OmniAICreator/Qiita-1.07M huggingface dataset:
Oracle:データベースバッファキャッシュを確認してみた

## データベースバッファキャッシュとは

アクセスされたデータファイル内にあるデータを保持しておくメモリ領域。
メモリ(SGA)にデータを保持することでデータを参照・更新する速度が速くなったり性能が上がったりする。

## データベースバッファキャッシュをSQLで参照

SQL*Plusを起動し、以下のコマンドを実行

```
 show parameter db_cache_size
```

結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533750/bcf995d2-b5c4-e308-519b-31089faddecc.png)

## データベースバッファキャッシュのサイズ変更

```
alter system set db_cache_size=6M;
```
ほんとはサイズは4の倍数にしなければいけないのですが、4の倍数でない場合強制的に4の倍数に変更されるそうなので、試してみました。

結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533750/422fd97c-373d-0054-045b-b52cbbd9cab5.png)

本当に16Mという4の倍数のサイズになってました。
TypeScriptのEnum型について




TypeScriptのenumは、特定の値の集合を表現するための方法の一つです。

1. 基本的なenum
最もシンプルな形のenumを以下に示します：

```Typescript
enum Colors {
    Red,
    Green,
    Blue
}
```
上記のColorsというenumを定義することで、Colors.RedやColors.Greenのようにしてその値にアクセスすることができます。また、enumの値はデフォルトで0から始まり、1ずつ増加していきます。したがって、Colors.Redの値は0、Colors.Greenの値は1、となります。

2. 初期値や値の変更
enumの要素には、任意の数値や文字列を割り当てることができます。

```Typescript
enum Colors {
    Red = 3,
    Green = 5,
    Blue = 7
}
```
この場合、Colors.Redの値は3になります。

文字列を使用することもできます：

```Typescript
enum Greetings {
    Hello = "こんにちは",
    Goodbye = "さようなら"
}
```
3. Computed value
enumの要素の値は、計算される値を持つことができます。しかし、計算される値を持つenumの要素の後ろに来るenumの要素には明示的な初期値を提供する必要があります。

```typescript
enum Values {
    A,
    B = A * 2,
    C  // この行はエラーとなる
}
```
4. 逆マッピング
TypeScriptのenumは逆マッピングの機能を持っています。数値のenumであれば、その値から名前を取得することができます。

```typescript
enum Colors {
    Red,
    Green,
    Blue
}


let colorName: string = Colors[0];  // "Red"
```
ただし、文字列のenumや計算される値を持つenumではこの機能は利用できません。

5. const enum
const enumは、enumの値がコンパイル時にインライン展開されるenumです。これにより、出力されるJavaScriptコードが短くなり、パフォーマンスが向上する場合があります。

```typescript
const enum Directions {
    Up,
    Down,
    Left,
    Right
}

let dir: Directions = Directions.Up;  // コンパイル時に "0" として展開される
```
以上がTypeScriptのenumの基本的な使い方や特性です。どんな状況でenumを使用するかは、具体的なケースやプロジェクトの要件によって異なりますが、限定的な値の集合を扱う場面で非常に役立つことが多いです。
単一テーブル継承について

:::note info
**単一テーブル継承（Single Table Inheritance）**
1つのテーブル内に継承関係にあるクラスのカラムを全て持つこと。
異なるモデル間でフィールドや振る舞いを共有したい場合などに採用する。
:::

### 具体例
親モデル：`Vehicle`モデル
継承するモデル：`Car`モデル、`Motorcycle`モデル、`Bicycle`モデル

上記のようなモデルが存在するときに、`color`、`price`などのフィールドや、関連メソッドなどを共有したい一方で、モデルごとに異なった振る舞いをする場合を考える。

#### 親モデルVehicleを生成
```bash
$ bin/rails generate model vehicle type:string color:string 
```
typeフィールドを追加することで、Railsはこのカラムに該当するモデル名を保存する。（`Car`モデル、`Motorcycle`モデル、`Bicycle`モデル）

この例での単一テーブル継承では、テーブルに`type`フィールドが必要。


次に継承するモデルを生成する。
```ruby
class Car < Vehicle
end

class Motorcycle < Vehicle
end

class Motorcycle < Vehicle
end
```
上記のように継承することで、親モデル`Vehicle`モデルに追加されたすべての振る舞いが、継承したモデルにも追加されるようになる。


#### 継承したモデルの挙動
##### Carモデルを新しく生成して保存すると、、、
```ruby
Car.create(color: 'Red', price: 10000)
```
```sql
INSERT INTO "vehicles" ("type", "color", "price") VALUES ('Car', 'Red', 10000)
```
:::note warn
typeフィールドに"Car"が代入されたデータがvehiclesテーブルに追加される
:::

---

https://railsguides.jp/association_basics.html#%E5%8D%98%E4%B8%80%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E7%B6%99%E6%89%BF-%EF%BC%88sti%EF%BC%89
DockerでPHP7.1環境を用意する

# 概要
PHP7.1で実行しているアプリケーション保守のため、検証環境を用意する必要があったのでメモ。

### 備考
dockerhubの　`php:7.1.33-apache`　を利用するのが楽なんだろうけど、、、2023年9月現在コンテナをビルドしようとすると、apt-getがコケるなど困った状況に陥った。（未解決）


そのため以下の参考記事を頼りにして、amazonlinux2 + php7.1 のコンテナを作成した。
* https://qiita.com/kazumeat/items/716dca6f084577ae9f85
* https://iret.media/39812


# 手順

### コンテナにコピーするためiniファイルを用意

```ini
[Core]
display_errors = On
error_reporting = E_ALL
error_log = /var/log/httpd/error.log
log_errors = On

[Date]
date.timezone = 'Asia/Tokyo'

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = auto
mbstring.http_input = auto
mbstring.http_output = auto
mbsting.encoding_translation = Off
mbstring.detect_order = auto
```

### Dockerfileを作成

```Dockerfile
FROM amazonlinux:2

COPY ./php.ini /usr/local/etc/php/

RUN yum install -y wget vi httpd libxml2-devel libxslt-devel zip unzip ncurses-compat-libs

RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
RUN rpm -ivh epel-release-latest-7.noarch.rpm
RUN yum install -y http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

RUN yum install -y --enablerepo=epel libedit
RUN yum install -y --disablerepo=amzn2-core --enablerepo=remi,remi-php71 php php-xml php-zip php-mbstring

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN composer global require phpstan/phpstan
RUN composer global require phpmd/phpmd

```

とりあえず、これでPHP7.1を実行できる環境を用意できた。
技育展2023に参加してきました。

先日行われた技育展2023に個人開発で参加してきました！
結果としては決勝進出はできたものの、入賞できずに終わってしまいました。。。
しかしつよつよ学生の様々なプロダクトを見てすごく刺激を受けたので、この刺激を忘れないように記事にまとめることにしました！

# 技育展とは
技育展とは学生のためのピッチコンテストで、今回200チームが参加し、上位60チームが決勝にいけるというもので、僕は予選を勝ち抜いてなんとか決勝まで進むことができました。

https://talent.supporterz.jp/geekten/2023/

# 作品
AI Typingという作品で出場しました。下に概要を載せておきます。

https://www.ai-typing.app/

https://qiita.com/y4asse/items/7873d7f2d341cc431060

# 感じたこと
## 1. すんごい学生がいる
ファイナリスト（上位12チーム）のプロダクトを見て「ほんとうに学生か？」と思いました。なかには海外の企業との繋がりをもった学生もいて、同じ学生とは思えないような人ばかりでした。その人たちと自分とで何がちがうのかを考えてみました。

### ○技術力
パフォーマンスについても考えて開発したり、自分が実装しようと思ってもなかなか想像がつかないような機能があったりと、知識の差が計り知れないなと感じました。どうやってその技術を身に付けてるんですか。

### ○環境
自分は独学で個人開発をしてきて、コミュニティなどには属していなかったのですが、やはりつよつよな人たちはいろんな繋がりを持ってたり、コミュニティ内で情報共有してたりするので、ともに高め合う仲間がいる環境っていうのはすごい成長できるんだなと感じました。

### ○思考
どれもすごいプロダクトだったけど、コンテストということでどうしても優劣が決まってしまうのですが、そのなかでファイナリストに残ったプロダクトに共通していたのは「だれかの役に立つサービス」だと感じました。多くの人に使われるような社会的に価値のあるサービスというのは「だれかの課題を解決」したり、「活動を後押し」したりするサービスなんだと再認識しました。誰かの役に立つサービスを作って、世の中に貢献していくということが、すごく素敵でかっこいいなと感じ、自分もそんなサービスを作って、技術で世の中を変えていきたいと思うきっかけになりました。

## 2. いろんな人と交流できてよかった
技育展では色々な人と交流できる時間がたくさん取られていたのですが、実際につよつよな人たちやスポンサー企業の方などとお話しすることができ色々な話を聞くことができました。また技育展を通して仲良くなった人とかもいるので、こういった場を提供してくれてとても感謝です。人数が多かったのでまだまだ話せてない人がいるのが残念です、、、

## 3. 楽しい
全国の学生のいろんなプロダクトを見て、自分の知らない技術や考え方に触れることができて、すごく刺激的で楽しかったです。発表の会場が東京大学で、緊張して途中日本語がしゃべれなくなっていたのですが、今後できないであろう良い経験ができました。

# 最後に
初めて技育展に参加したのですが、入賞することができず、**とっっても悔しい思いをしました**。それと同時に自分の中の考え方や価値観が変わる大きなきっかけとなりました。企業の方々のコメントで個人的に心にくるものがあったので、**その気持ちを忘れずこれからも開発を続けていきたい**と思いました！
より高みを目指している学生エンジニアの方にとってはこの技育展はすごく刺激的な経験になると思うので、ぜひ参加してみてください！
AnsPress（WordPress）の個別質問ページに「関連した質問」を表示できますか？

AnsPressを使い、はじめてWordPressでQAサイトを作成しています。



質問個別ページの
サイドバーや投稿文下に、
その質問に関連した質問を表示したいのですが、「外観＞ウィジェット」から該当するウィジェットが見つかりません。



例)
「動物」カテゴリーの質問個別ページの「関連した質問」枠に、
他の「動物」カテゴリーの質問個別ページを表示したい

最新の質問を表示する「（AnsPress）質問」というウィジェットはあるのですが、関連した質問を表示する機能はないのでしょうか？

ご教授よろしくお願いいたします。
vim/neovimで動くchatgptクライアントを作った

### 令和5年11月25日追記
かなりの破壊的な更新を行いましたので、記事を書きました。

https://qiita.com/uesseu/items/956dc3df90e6ff1a3192

下記は内容が古く、もう動かないものです。

# なにを作ったのか
vim/neovimで動くchatgptクライアントを書いてみました。多分もう100万回擦られた車輪の再発明。
Deno/Denopsで動きます。名前はninco.vimってつけました。
![out.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139153/5dc5f5d0-4b30-aba9-2e51-7559a7bb2aa9.gif)

https://github.com/uesseu/ninco.vim

# なにが出来るのか
- chatgptを叩く
- 別のウィンドウでchatgptを叩く
- 選択範囲に対してchatgptを叩く
- chatgptの履歴を圧縮する
- モデルを指定する



# 品質
まぁ、エンジニアじゃない僕が作ったわけですのでお察し…。

素の状態ではファインチューニングしていませんのでそのまま使えばプログラミングスキルは素のchatgptです。もちろん、ファインチューニングしたモデルを導入することは出来ますので、強力なものを使うことは出来ます。(そういう設定を入れる関数を用意しています)

# 値段
これ自体は無料として……openaiの素のchatgptを使っているので、運用にかかる費用がとんでもなく安いです。具体的には、使わないときにはお金掛からないし、使っても安い。

# 実装
これはvim/neovim環境下でDenopsを使っています。DenopsはDenoでvim/neovimのプラグインを書けるやつです。故になのか分かりませんが、サクサク動きます。最近のvim/neovimはかなり違うので、vim/neovim側はvimscriptで分岐しながら書いています。Denoには何故かopenaiのライブラリがないので、そこは素でAPIを叩きました。
なので、作るの意外と面倒でした。

# 感想
僕は使おうと思います。
【備忘録】jspにとんでもなく便利なタグがあるぞって話。

<h1>とんでもなく便利なjspのタグ

<p>発見してしまいました。色々な問題を解決してくれるやつを。それは…

```jsp
<% %>
```

これと

```jsp
<%= %>
```
これです！

何ができるかというと、これ、Javaを書けるんですよね。
詳しく説明すると、前者がロジックを書くとこで後者が変数をhtmlタグに入れ込む用の奴なんすよね。

```jsp
<% 
String java_sample = "sample";
%>

<html:text name="sample" property="property" value="<%=java_sample%>"/>

```

こうやって書くとJavaのStringで書いた変数の値を表示することができるんですよね。これが非常に便利なんですよね。
応用すると、
```jsp
<% if(entity.getId().equals("1")){ %>
<html:text name="name" property="property"/>
<% } %>

```
みたいに書くことでentityに指定したJavaのデータクラスのgetid()で取り出した値が1の時のみ、このhtmlタグをブラウザ上に表示させることができます。これが非常に有用性が高いんですよね。
あるWebアプリで新規登録のページと編集するページがあり、ほとんど表示するものが一緒。みたいなケース！
違うjspファイルを用意しないで済むのです。

<h1>ただしかし

<p>これだけ便利でもやっぱりデメリットがありました。
私が感じた不便な点を紹介します。
<ol>
<li>見づらい
<li>書き損じに気付きづらい
<li>デバッグがしづらい
<ol>

<h2>見づらい</h2>
<p>これが一番困る印象です。
<p>JSPはJavaScriptとCSS、htmlに当たる文を書いてることが多いんですが、これに加えてJavaまで書くととにかく視認性が悪くなります。

<h2>書き損じに気付きづらい</h2>
<p>Javaを直接Javaのファイルに書くのと違って、色が変わったり波線を引いたりしてくれません！よって気づけません！疲れてたら無理です！
<p>しかも書き損じを見つける方法も「じっくり探す」しかありません（私が知らないだけかも）。だからミスった時めっちゃ大変なんですよね。。

<h2>デバッグがしづらい</h2>
<p>上2つと似たようなもんなのですが、デバッグがしづらいです。
<p>ブレークポイントで止めて、変数の中を見る。みたいな手法がとれないので挙動の確認がやりにくいんですよね。

<br>
<br>
<h1>まとめ
<p>こんな感じですね。jspの便利なタグは。

めっちゃ便利なんですが、多用してると後々に苦労してしまうような気がするので使いどころには気を付けないとですね。
クリーンアーキテクチャ-全体メモ

# この記事の目的
クリーンアーキテクチャに関連するメモに散らばっている知識をまとめて見やすくする．


## SOLID原則について

**依存性逆転の原則**

https://qiita.com/cagorogoro994/items/db5d9b2c35d4f426bb3a

**単一責任の原則**

https://qiita.com/cagorogoro994/items/a023b07a2a3c2b7f07f3

**開放閉鎖の原則**

https://qiita.com/cagorogoro994/items/37e70487fbf560cbf79a

**リスコフの置換原則**

https://qiita.com/cagorogoro994/items/e100e1aa0f941cc0b258

**インターフェース分離の原則**

https://qiita.com/cagorogoro994/items/0410ddb66e4fabee18fe


## 今後について
今後も新しい情報を追加していく．
まとめて欲しい内容や，指摘があれば是非コメントをお願いします．
キーエンスPLCとプログラミング言語のデータ型の関係

# キーエンスPLCとプログラミング言語のデータ型の関係

Python等を使用して、PLCへ上位リンク通信をかけるためにはPLCのデータ型を理解する必要があります。
そのためにデータ型を比較した表をまとめました。

- PLCはキーエンスの場合としております。
- Pythonにはデフォルトで符号なしの型が存在しないため、ctypesのライブラリを使用する前提です。


| 型 | PLC Suffix | C# | Python |
| :---: | :---: | :---: | :---: |
| 16bit符号なし整数 | .U | ushort | ctypes.c_ushort |
| 16bit符号あり整数 | .S | short | ctypes.c_short |
| 32bit符号なし整数 | .D | uint | ctypes.c_uint |
| 32bit符号あり整数 | .L | int | ctypes.c_int |
| 単精度浮動小数点実数 | .F | float | ctypes.c_float |
| 倍精度浮動小数点実数 | .DF | double | ctypes.c_double |
GCP VMインスタンスの初期パスワード設定

GCP ComputeEngineのVMは初期状態ではパスワードが設定されていません。
しかし、この状態でsuコマンドなどを実行するとパスワードが求められます。

このようなときは、下記のコマンドでパスワードを設定することができます。
```
sudo passwd
```
トリビア: Mac版のPythonは「壊れている」ので、Poetryのインストールに失敗することがある

# Intro
Macでインストール可能なPython[^1]を使ってPoetryをインストールしようとすると、動的ライブラリを読み込めないとかいう以下のerror logを吐いて死ぬことがよくある。
[^1]: AppleがMacに同梱しているバイナリ、HomeBrewでインストール可能なバイナリ

```
dyld[6624]: Library not loaded: @loader_path/../../../../Python.framework/Versions/3.11/Python
  Referenced from: <16376C03-0DA9-3714-9207-5AF8D546EED4> /Users/$USER/Library/Application Support/pypoetry/venv/bin/python3.11
  Reason: tried: '/Users/$USER/Library/Application Support/pypoetry/venv/bin/../../../../Python.framework/Versions/3.11/Python' (no such file), '/Library/Frameworks/Python.framework/Versions/3.11/Python' (no such file), '/System/Library/Frameworks/Python.framework/Versions/3.11/Python' (no such file, not in dyld cache)
```
:::note
`$USER`は実際にはホームディレクトリ名
:::

特に、HomeBrewでPythonをアップデートした後はよくこの症状が出て、そのたびに調べ直していたので、備忘録としてまとめることにした。

# TL; DR
* PythonはApple版でもHomeBrew版でも良い。（自分はHomeBrew版を使っている）
* Poetryのインストールには、公式のワンライナーではなく[以下のワンライナー](https://github.com/python-poetry/install.python-poetry.org/issues/24#issuecomment-1692427804)を使う。

```zsh
curl -sSL https://install.python-poetry.org | sed 's/symlinks=False/symlinks=True/' | python3 -
```

# もっと詳しく
Poetryの[該当GitHub issue上でのコメント](https://github.com/python-poetry/install.python-poetry.org/issues/24#issuecomment-1226504499)にリンクされた[CPythonのGitHub issue](https://github.com/python/cpython/issues/82886#issuecomment-1093846287)のコメントによると、 仮想環境を作成するvenvの `--copies` や `--symlinks=False` オプションを使う（バイナリをコピーし、シンボリックリンクを使わない）ことで、壊れたPythonバイナリが生成されることが主な原因。この動作は、Poetryのインストールスクリプトでも行っているため、同じ問題が発生する。

「壊れたPythonバイナリ」というのは、「動的ライブラリを読み込めないバイナリ」のことだと思う。同じMac向けのPythonバイナリでも動的ライブラリへのパスの種類は異なっていて、状況は複雑っぽい。

* Apple版バイナリ: 相対パス
  - `symlinks=False` にすると常に壊れる。
* Homebrew版バイナリ: 絶対パス
  - Python 3.11.3までは、Pythonの新しいリリースにアップグレードすると壊れる。
  - Python 3.11.3以降は、HomeBrewで新規インストールしても壊れる。[^2]
* python.org版バイナリ: おそらく問題ない？

ということで、常に`symlink=True`にするのが解決策らしい。Macではvenvによる仮想環境の作成にシンボリックリンクを使うのがデフォルト動作になるだろうとの指摘がある。[^2]
[^2]: https://github.com/python-poetry/install.python-poetry.org/issues/24#issuecomment-1666601505

ちなみに未だに該当issueは1年以上closeしておらず、問題の複雑さを物語っているように思える。

# 参考文献

https://github.com/python-poetry/install.python-poetry.org/issues/24

https://docs.python.org/ja/3/library/venv.html
「可読性」に関する先行研究のリンク集とメモ

# はじめに
「可読性」って雰囲気で使ってるけど、可読性の構成要素とかいまいちよくわかんないので、調べてみた。
自分には結構定義が難しくて、簡単にサマリできなかったので、単なるリンク集になってしまった。
網羅的に調べたわけではないので、検索してヒットしたものを整理した、くらいのもの。


# 調査時のメモ
調べた箇所別に整理していく。

## wikipedia

https://ja.wikipedia.org/wiki/%E5%8F%AF%E8%AA%AD%E6%80%A7

> コンピュータ・プログラミングにおける可読性（readability）とは、プログラムのソースコードを人間が読んだときの、その目的や処理の流れの理解しやすさを指している。
ソースコードを保守するのは人間であるため、その可読性は重要である（ただし、未熟なプログラマが、よく使われるイディオムによる簡潔なコードを「可読性の低いコード」と見なしてしまうことがあり、読む人間のスキルもまた重要である）。
コメントも可読性に影響し、適切なコメントは可読性を向上するし、誤ったコメントが放置されていれば誤読のおそれが高くなる。可読性の低いコードは、バグを生みやすく、重複コードによる非効率を生みやすい。
> コーディングスタイルの規則の大部分はコードの意味には何ら関係なく、主に可読性に関するものである。例えば以下のようなものである。
>- 字下げスタイルの違い
>    - なお、インデントがコードの意味に直接関係する言語もある（例：Python）。
>- コメント
>- 問題の分割の仕方
>- 各種オブジェクトの命名規則（変数名、クラス名、手続き名など）

まぁよく言われる話以上の情報は得られなかった。


## いろんな先行研究

https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=94181&item_no=1&page_id=13&block_id=8

https://web.eecs.umich.edu/~weimerw/p/weimer-tse2010-readability-preprint.pdf

https://www.researchgate.net/publication/221657129_A_simpler_model_of_software_readability

https://www.ieice.org/publications/ken/summary.php?contribution_id=KJ00009191941

https://www.semanticscholar.org/paper/A-metric-for-software-readability-Buse-Weimer/d370c6d9d138bd30ee136def25a1a7269a95f5d0

https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=104434&item_no=1&page_id=13&block_id=8

https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=98513&item_no=1&page_id=13&block_id=8

面白い切り口は多いものの、言語が違うとか、分析のための準備が大変そうとか、自分の現場に適用できそうなのはちょっと見当たらなかった。。。
画像で２値化してとか評価するとかは、簡単で面白そうだった。ただ、その基準でスコア化した時に、現場がそのスコアを過剰に重視してしまって、そのスコアが良くなることを目指されるとつらいので、採用には至らなかった。

# 最後に
ちょっと「可読性」って基準は諦めようかなぁと思ってる。
自分が評価したいのは「コード品質」なんだろうなというのがわかってきたので、そっちのキーワードで調べ直そうと思った。

以上。
Kotlinで二次元累積和と二次元区間和を求める方法

二次元累積和と二次元区間和とは、行列の一部分の要素の和を高速に求めることができるアルゴリズムです。この記事では、Kotlinで二次元累積和と二次元区間和を求める方法について説明します。

## 二次元累積和とは

二次元累積和とは、行列の左上から任意の位置までの部分行列の和を事前に計算しておくことで、任意の区間の和を高速に求めることができるテクニックです。 

具体的には、以下のような手順で計算します。

- まず、s[0][0] を 0 とします。
- 次に、s[i][0] を i 行目の要素の和とします。つまり、s[i][0] = s[i - 1][0] + a[i - 1][0] となります。
- 同様に、s[0][j] を j 列目の要素の和とします。つまり、s[0][j] = s[0][j - 1] + a[0][j - 1] となります。
- そして、s[i][j] を左上から (i, j) の位置までの部分行列の和とします。つまり、s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i - 1][j - 1] となります。この式は、上の行と左の列の和を足して、重複した部分を引いて、現在の要素を足すことで求められます。

このようにして、s[i][j] をすべて計算することで、二次元累積和が完成します。 

## 二次元区間和とは

二次元区間和とは、行列の任意の区間 (l, r) の要素の和を求めることです。ここで、区間 (l, r) は左上の位置 l = (a, b) と右下の位置 r = (c, d) の組で表されます。

二次元累積和があれば、任意の区間 (l, r) の和は s[r][r] - s[l - 1][r] - s[r][l - 1] + s[l - 1][l - 1] で求めることができます。この式は、右下から左上に向かって四角形を切り取っていくイメージです。

## Kotlinでの実装例

以下にKotlinで二次元累積和と二次元区間和を求めるコード例を示します。

```kotlin
import java.util.*

fun main() {
    // 入力を受け取る
    val sc = Scanner(System.`in`)
    val h = sc.nextInt()
    val w = sc.nextInt()
    val n = sc.nextInt()
    val a = Array(h) { IntArray(w) }
    for (i in 0 until h) {
        for (j in 0 until w) {
            a[i][j] = sc.nextInt()
        }
    }
    val abcd = Array(n) { IntArray(4) }
    for (i in 0 until n) {
        for (j in 0..3) {
            abcd[i][j] = sc.nextInt() - 1 // 0-indexedにする
        }
    }

    // 二次元累積和を計算する
    val s = Array(h + 1) { IntArray(w + 1) }
    s[0][0] = 0
    for (i in 1..h) {
        for (j in 1..w) {
            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i - 1][j - 1]
        }
    }

    // 各ペアについての区間和を求める
    for (i in 0 until n) {
        val a = abcd[i][0]
        val b = abcd[i][1]
        val c = abcd[i][2]
        val d = abcd[i][3]
        val ans = s[c + 1][d + 1] - s[a][d + 1] - s[c + 1][b] + s[a][b] // S({a,b} , {c,d}) の値は s[c + 1][d + 1] - s[a][d + 1] - s[c + 1][b] + s[a][b] に等しい
        println(ans)
    }
}
```

### 参考
ソース: Bing との会話 2023/9/26
: [二次元累積和](https://qiita.com/drken/items/56a6b68edef8fc605821)
法務部門の先例集の機能を検討してみた！

![IMG_1609.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519421/d7202ac1-ed5d-94cd-98eb-f8ef71543eb7.jpeg)
法務部門の担当者として、完了した案件を通じて得られた知識、経験その他有益な情報を蓄積する先例集の作成を目論んでいます。
作成された案件ごとのWORDファイルを格納したフォルダから、特定のキーワードを含むファイルを抽出できれば便利だと考え、挑戦してみました。

 # 成果物のイメージ
テスト用にファイルを作ってみました。
![スクリーンショット 2023-09-26 212248.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519421/038c373f-7185-fd31-3db1-a2e8a4102d26.png)
![スクリーンショット 2023-09-26 212349.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519421/daa36599-394c-4605-8c3a-b3b4e2598dcf.png)
3つのファイルのうち「test2」にのみ「民事執行法」というキーワードが入っています。
このファイルをPADで抽出するツールを目指します。

 # 使用したツール
・**WORD**
・**Power Automate Desktop**
・**Chat-GPT**

今回は、一から考えてもよく分からないので、Chat-GPTにヒントをもらいながらやりました。

 # やってみる 
まず、Chat-GPTに次のような質問をしてみます。

:::note
「指定されたキーワードを含むWORDファイルをPowerAutomateDesktopを使って抽出する」
:::

すると、次のような答えが返ってきました。

:::note
Power Automate Desktop（以前はWinAutomationとして知られていました）を使用して、指定されたキーワードを含むWordファイルを抽出するには、次のステップを実行できます。以下は一般的な手順の一例ですが、具体的な設定によって異なる場合があります。詳細な手順はPower Automate Desktopのバージョンやインタフェースに依存します。

1. **新しいフローを作成**:
   - Power Automate Desktopを起動し、新しいフローを作成します。

2. **ファイルの検索**:
   - "ファイルを検索"アクションを使用して、指定されたフォルダー内でWordファイルを検索します。
   - アクションの設定で、検索条件としてキーワードを含むファイルを指定します。

3. **検索結果の反復処理**:
   - 検索結果を反復処理するためにループを設定します。これにより、検索結果に含まれる各ファイルに対して同じ操作を繰り返します。

4. **Wordファイルの内容を検索**:
   - Wordファイルを開いて、その内容を検索するアクションを追加します。
   - Wordファイルを開く方法は、Power Automate Desktopのバージョンによって異なる場合があるため、ドキュメンテーションを確認してください。
   - Wordファイル内のテキストを検索し、指定されたキーワードが含まれているか確認します。

5. **キーワードが見つかった場合のアクション**:
   - キーワードが見つかった場合、必要なアクションを実行します。これにはファイルのコピー、メールの送信、または他の操作が含まれるかもしれません。

6. **次のファイルへの反復処理**:
   - 反復処理を通じてすべてのファイルをチェックしたら、フローを終了します。

Power Automate Desktopは、ビジネスプロセスの自動化に非常に便利なツールですが、具体的な設定やアクションは使用するバージョンによって異なる場合があります。必要に応じてドキュメンテーションやオンラインリソースを参照して、正確な手順とアクションを確認してください。
:::

分かったようでよく分からないので、Googleでも調べてみて以下のサイトを見つけました。

https://www.teijitaisya.com/pad-filesearch-or/

このサイトの方法をほぼそのまま真似して（真似したつもり）出来上がったPADのフローがこちらです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519421/2ea281b2-9721-75b2-0aff-35de1da6dec0.png)
しかし、想像したように働いてくれません。
成功例としては、test2ファイルがポップアップされるはずなのですが・・・。

 # まとめ（まとめになっていないけど）
原因はよく分かりませんが、うまくいきませんでした・・・。
敢えて簡単な成果物にしたつもりだったのですが、それでもできんとは・・・凹みます。
どなたかアドバイスをお願いします！
Helix Editor でファイルツリーを表示する

## Helix Editor

https://helix-editor.com
最近使ってるCUIエディタです。

## ファイルツリー機能

https://github.com/helix-editor/helix/issues/200

https://github.com/helix-editor/helix/pull/5768

公式でIssue立ってますが、PRを見ると最終的にこの機能はプラグインとして開発するそうです。
また、プラグインは開発中とのことです。

ということで代替案を探しました。

## 代替案の参考

https://www.youtube.com/watch?v=wIyz7UQPL70

https://gist.github.com/lukepighetti/8e4a13db5bdcd68a7d83eee19051ab14

## 使った感じ

![ScreenShot 2023-09-26 21.57.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/42e15b98-c0e4-02dc-92d5-05dbc5ac78a8.png)

Helixエディタを起動した状態で `control` + `f` でファイルツリーが開きます。 開きたいファイルを選択して `l` または `→` でHelixエディタでファイルが開きます。

プラグインが開発されるまでは十分かなと思います。

## 導入方法

参考動画に手順や解説が載ってるので詳しくはそちらを参照ください。

### ファイルマネージャーをインストール

https://github.com/gokcehan/lf

```shell
$ brew install lf
```

### Helix 設定

```toml:~/.config/helix/config.toml
[keys.normal]
C-f = [":new", ":insert-output lf-pick", ":theme default", "select_all", "split_selection_on_newline", "goto_file", "goto_last_modified_file", ":buffer-close!", ":theme tokyonight_storm"]
```

### シェルスクリプト

```shell
$ mkdir -p ~/.local/bin
$ touch ~/.local/bin/lf-pick
$ chmod +x ~/.local/bin/lf-pick
```

```~/.local/bin/lf-pick
function lfp(){
  local TEMP=$(mktemp)
  lf -selection-path=$TEMP
  cat $TEMP
}

lfp
```

### パス追加

```~/.zshrc
PATH="$HOME/.local/bin:$PATH"
```

シェルを再起動してパス設定を反映

```shell
$ exec $SHELL -l
```

動作確認

```shell
$ lf-pick
```

起動すればok `q` で抜ける。

### 使い方

```shell
$ hx
```

Helix Editorを適当に起動する。
`control` + `f` でファイルツリーが表示されればOK。

![ScreenShot 2023-09-26 21.57.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/42e15b98-c0e4-02dc-92d5-05dbc5ac78a8.png)

ファイルを選択して `l` または `→` で開く。

## 補足

そもそも標準機能の `Space` + `f` でファイルのあいまい検索ができるので、不要な人は不要だと思います。

![ScreenShot 2023-09-27 1.12.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/246ab25f-9e8a-0887-4cf4-fd39561217e8.png)
【プラクティス紹介】1分でさらっと分かる「あんどん」

## プラクティス名（別名）
あんどん　（ソフトウェアあんどん）

## プラクティスの目的・狙い
* 「止めて、直す」を徹底することで、障害影響を極小化する 

## どんな時に使うか
* 人知れずビルドが壊れている、といったことがよく発生する
* さらにそれを復旧させるのに時間がかかる（原因調査、影響調査、etc...）

## 実施手順
1. 受け入れテストを自動化し、毎日定時にバッチ実行する
1. ビルドエラーが出たら「あんどん」を灯す
1. 「あんどん」が灯ったら、作業の手を止め、状況を共有し、全員で原因を究明する
1. 問題が解消するまではビルドに他のコードを追加してはならない
1. 問題が解消したら「あんどん」を消灯し、通常の仕事モードに戻る

:::note info
「あんどん」はパトランプや旗、アラーム、チャットの緊急通知など現場の全員がすぐ気づけるサインであれば何でもよい
:::

問題が起きるたびに製造ライン全体をストップさせるのは一見効率が悪いように思えるが、エラー発生後に別のコードが載ってきて問題が複雑化する事態を防げるため、結果的には少ない労力で問題を取り除ける。エラー状況もその場で全員に共有されるため二次障害も起こりにくい。
背後にある考え方として「欠陥のムダ ＝ 欠陥の大きさ × 欠陥の滞在時間」という計算式があり、滞在時間を短くすることで影響を最小限に抑える。

## アレンジ例
* 「あんどん」が灯ったら、全員モブプロエリアに集合する

## アンチパターン
* 「あんどん」が灯っているのに、問題解決に協力せず、自分が担当中の作業を黙々と続ける

## 参考情報

オブジェクト倶楽部（後にオブラブに改名） 「見える化によるプロジェクトファシリテーション」
http://objectclub.jp/download/files/pf/ProjectFacilitation20051124.pdf

## こぼれ話（私的コメント）
「あんどん」という名称の由来はTPS（トヨタ生産システム）から。製造ラインの誰でも異常を見つけたら、ボタンを押してラインを止めることができる。一旦「止めて、直す」ことで欠陥品が次工程に流れずに済むため影響が少ない。海外でも「Andon System」の名で知られている。その考え方をソフトウェア開発に応用したのが「ソフトウェアあんどん」となる。

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
【Swift】特定の要素の次の要素、前の要素を取得する

# はじめに
やりたいことはタイトルの通りです。
1番前にいる時に前の要素を取得しようとすると、1番後ろの要素を取得したいです
1番後ろにいる時に前の要素を取得しようとすると、1番前の要素を取得したいです

# 実装
```swift
struct XXX {
    let id: String
}

let array: [XXX] = [XXX(id: "000"), XXX(id: "001"), XXX(id: "002"), XXX(id: "003"), XXX(id: "004")]

let selectedItem = XXX(id: "003")

func currentItemIndex(selected: XXX, in array: [XXX]) -> Int? {
    if let index = array.firstIndex(where: { $0.id == selected.id }) {
        return index
    } else {
        return nil
    }
}

func previousItem(selected: XXX, in array: [XXX]) -> XXX? {
    if let currentIndex = currentItemIndex(selected: selected, in: array) {
        let nextIndex = (currentIndex + 1) % array.count
        return array[nextIndex]
    }
    return nil
}

func nextItem(selected: XXX, in array: [XXX]) -> XXX? {
    if let currentIndex = currentItemIndex(selected: selected, in: array) {
        let previousIndex = (currentIndex - 1 + array.count) % array.count
        return array[previousIndex]
    }
    return nil
}

print(nextItem(selected: selectedItem, in: array)) // XXX(id: "002")
print(previousItem(selected: selectedItem, in: array)) // XXX(id: "004")
```

### 前の要素を取得する
```swift
func previousItem(selected: XXX, in array: [XXX]) -> XXX? {
    if let currentIndex = currentItemIndex(selected: selected, in: array) {
        let nextIndex = (currentIndex + 1) % array.count
        return array[nextIndex]
    }
    return nil
}
```

### 次の要素を取得する
```swift
func nextItem(selected: XXX, in array: [XXX]) -> XXX? {
    if let currentIndex = currentItemIndex(selected: selected, in: array) {
        let previousIndex = (currentIndex - 1 + array.count) % array.count
        return array[previousIndex]
    }
    return nil
}
```

# おわり
実現できました
LeetCodeのMerge Two Sorted Lists解いてみた

# 始めに
少し空いてしまったけど今回もLeetCodeの有名問題をやったのでアウトプットしていく
最近はMedium問題ばかりでしたが久々のEasy問題。
もし間違えなどがあればご指摘お願いします！

では行ってみよう


# 問題
https://leetcode.com/problems/merge-two-sorted-lists/description/

2つのソート済み連結リストを結合して1つのソートされたノードを返す問題。
やり方を知らないとコーディングがピタリと止まる
当然私も止まった

# 考察
この問題を解く上で重要なのは2つのノードをどのようにして走査するのか？を考えること
最初に思いついたのが2回に分けてiteratorを使い値の配列を作り、それをマージした後に新たなノードを作成していく方法。
ただこれだと無駄な計算が多すぎる

なので2つのポインタ(curr, dummy)を使いlist1とlist2を同時に走査する方法を取る。
具体的には各ノードの値の小さい方の値のlistを先に進めながら走査していけば良い

# 解法
## ２つのポインタを用意
curr → 現在のポインタを示す
dummy → 最終的にマージしたノードのhead
```python
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
    curr = dummy = ListNode()
```

## イテレート処理
list1とlist2の値を比較し、小さい方のノードを次のノードに設定する
この際、値の大きさが同じ場合、次のポインタにlist2を設定する
```python
   while list1 and list2:
        if list1.val < list2.val:
            curr.next = list1
            list1 = list1.next
        else:
            curr.next =  list2
            list2 = list2.next
```

## ノードを先に進める
前項で次のポインタは設定したのでノードを先に進めます
```python
curr = curr.next
```

## 残りのノードを末尾に追加
残りのノードを追加したらdummy.nextでソートした連結リストの完成
```python
curr.next = list1 or list2

return dummy.next
```

以下に全文を載せます
```python
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
    curr = dummy = ListNode()
    while list1 and list2:
        if list1.val < list2.val:
            curr.next = list1
            list1 = list1.next
        else:
            curr.next =  list2
            list2 = list2.next

        curr = curr.next 

    curr.next = list1 or list2

    return dummy.next
```


# 感想
連結リストの問題はやり方をある程度暗記でも良いのでは？と思ってる。
即興で解ければ苦労はないが、やはりコーディング面接や試験では時間制限などもあり本来なら解けた問題も緊張で解けないなんてことになったら大変。
なのである程度問題を見た時にざっくりの解法が浮かぶぐらいにはしておきたい
先は長い...
boto3 で S3 オブジェクトを mv, rename

別にどうということはないのだけど、あとで使いまわしそうなのでメモしておくやつ。

AWS CLI には `aws s3 mv` というコマンドがあるが、Amazon S3 そのものにはオブジェクトの Key の変更 (≒ 移動やリネーム) に相当する API が存在しないので、実際には CopyObject してから古い方を DeleteObject することになる。

Python で同様のことをしたい場合、boto3 の S3 Client には `aws s3 mv` 相当のメソッドは無いので、

``` python
def s3_move_object(s3, *, BucketFrom: str, BucketTo: str | None = None, KeyFrom: str, KeyTo: str):
    if BucketTo is None:
        BucketTo = BucketFrom
    s3.copy_object(Bucket=BucketTo, Key=KeyTo, CopySource={"Bucket": BucketFrom, "Key": KeyFrom})
    s3.delete_object(Bucket=BucketFrom, Key=KeyFrom)
```

こういう関数を作っておくと、

``` python
import boto3

s3 = boto3.client("s3")

s3_move_object(s3, BucketFrom="mybucket", KeyFrom="mydir/foo.txt", KeyTo="mydir/bar.txt")
```

こんなふうに使えて便利。
SOLID原則-メモ5

## インターフェース分離の原則について
インターフェース分離の原則（Interface Segregation Principle, ISP）は、SOLID原則の一つであり、クラスが自身が利用しないインターフェースに依存すべきではないという原則です。

**クラスは、それが使用しないメソッドに依存すべきではない。**
この原則は、クラスが必要としないメソッドに依存することなく、それらが必要なクラスのみが特定のメソッドを実装するように設計すべきであると述べています。

## 具体的な適用方法

**小さなインターフェースの作成**
大きなインターフェースを小さなインターフェースに分割することで、クラスは必要なインターフェースのみを実装できます。

## インターフェース分離の原則を適用することで得られる利益

#### 1. 可読性の向上
不要なメソッドが排除されることで、コードの可読性が向上し、理解しやすくなります。

#### 2. 保守性の向上
必要なインターフェースのみに依存することで、変更の影響範囲が小さくなり、保守が容易になります。

#### 3. 疎結合の促進
インターフェースの分割により、クラス間の結合度が低減し、疎結合な設計が促進されます。

## C#の具体的なコード

#### 悪例: 大きなインターフェイスの実装
```cs
public interface IOperations
{
    void Operation1();
    void Operation2();
    void Operation3();
    void Operation4();
    void Operation5();
}

public class BadExampleClass : IOperations
{
    public void Operation1() { /*...*/ }
    public void Operation2() { /*...*/ }
    public void Operation3() { /*...*/ }
    // BadExampleClassではOperation4, Operation5は不要
    public void Operation4() { throw new NotImplementedException(); }
    public void Operation5() { throw new NotImplementedException(); }
}
```

上記のコードでは、`IOperations`インターフェースは多くの操作を持っており、`BadExampleClass`はそのうちの2つしか利用していません。しかし、`BadExampleClass`は`IOperations`インターフェイスを実装しているため、利用しないメソッドも実装しなければなりません。これはインターフェース分離の原則に違反しています。

#### 良例: 小さなインターフェイスの実装
```cs
public interface IOperation1
{
    void Operation1();
}

public interface IOperation2
{
    void Operation2();
}

public class GoodExampleClass : IOperation1, IOperation2
{
    public void Operation1() { /*...*/ }
    public void Operation2() { /*...*/ }
}
```

良い設計の例では、各操作に対して別々のインターフェースが定義されています。`GoodExampleClass`は必要なインターフェースのみを実装するため、不要なメソッドに依存することなく、また未実装のメソッドを持つことなくコードを書くことができます。これはインターフェース分離の原則に従っています。


## まとめ
インターフェース分離の原則は、クラスが不必要なインターフェースメソッドに依存することを避けるための重要な原則である。この原則の適用により、コードの可読性、保守性が向上し、疎結合な設計が促進される。従って、クラスが必要とするメソッドのみを持つ小さなインターフェースの作成が推奨される。
Djangoサーバー起動時にModuleNotFoundError: No module named 'pkg_resources'が出た件

## 背景
バックエンドの環境が更新され、git pullし反映後、それまでは問題なく起動していたDjangoサーバーが起動しなくなった。
また、投稿者自身はもっぱらフロントエンド開発ばかりの為、pythonの知見はほぼない。

## 経緯
`git pull`を行い反映後、`poetry instal`を行う。
`python manage.py runserver`を実行したところ、エラーが発生。
もちろん、gitブランチを切り替えても解決せず、フロントエンド開発が出来なくなってしまった。

## エラー内容
細かいところは大人の事情で省略・・・
一番最後のエラーログ
```
$ python manage.py runserver

... 省略 ...
ModuleNotFoundError: No module named 'pkg_resources'
```

## 環境
- windows10
- Python 3.8.10
- poetry 1.1.12
- pip 21.3.1

## 調査した内容
- `poetry install`を行っても、相変わらず上記エラーが発生
- `poetry show`の結果と`pyproject.toml`の内容に差分があることがわかった
    - どうやら`setuptools`が仮想環境にインストールされていないみたい

## 結論
恐らく正攻法ではない気がするが、以下の手順で一旦解決（？）
※一部マスキングしてます
```
# 依存関係を一旦installする
$ poetry install

# 仮想環境に入り pythonコマンドで検証(エラーが発生することを確認)
$ python
Python 3.8.10 (tags/v3.8.10:3d8993a, xxx  0 0000, 00:00:00) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import setuptools
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'setuptools'
>>> exit()

# setuptoolsをpipコマンドでinstallする
$ pip install setuptools
Collecting setuptools
  Using cached setuptools-68.2.2-py3-none-any.whl (807 kB)
Installing collected packages: setuptools
Successfully installed setuptools-68.2.2

# 仮想環境に入り pythonコマンドで検証(エラーが発生しないことを確認)
$ python
Python 3.8.10 (tags/v3.8.10:3d8993a, xxx  0 0000, 00:00:00) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import setuptools
>>> exit()
(.venv)

# サーバー起動コマンドを実行し正常に動作することを確認する
$ python manage.py runserver
```

ご参考になれば幸いです。
ご利用は自己責任で。。
BitWardenでJASSOの奨学生番号入力を自動化(カスタムフィールド)

独自形式のPW入力欄、1フェムト秒でも早く滅びてほしいですよね。
それはそうと、そういう糞に対応する方法があるようなので、自分がぱっと思い当たった糞で試してみました。

大本の記事
https://bitwarden.com/ja-JP/help/custom-fields/


JASSOの糞はこういう糞なんですが、これに対応しようというカスタムフィールドのチュートリアル的記事です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200360/881eab25-bc6a-2975-4b0f-77e591e75220.png)

まず、入力欄に対して右クリックします。すると図のがあるので、クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200360/a065f15d-ec90-e1c4-9f6d-5def9760b6ac.png)

するとクリップボードにその入力欄の`名前`がコピーされます。

`テキスト`なフィールドなので、`テキスト`を選択して十字マークをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200360/ef355c65-91b3-9d13-f721-58e56c7a0864.png)

すると`名前`と`値`を入力する欄になるので`名前`は`名前`、`値`はそのフィールドに書くべき値を書きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200360/148c4410-e196-b230-4625-c355c88ade40.png)
これを糞欄の数だけ繰り返すと…

幸せになれます。


糞欄の`名前`
| 位置 | 名前 |
|---|---|
| 左の欄 | syogkseibgKakunin_open_syogkseiBg1 |
| 中の欄 | kakuninInput_openToEntry_syogkseiBg2 |
| 左の欄 | syogkseibgKakunin_open_syogkseiBg3 |

さああなたの幸せなパスワード管理ライフを。
Bigqueryの holidays_and_events_for_forecasting には祝日ではない日も考慮される

# 結論
`bigquery-public-data.ml_datasets.holidays_and_events_for_forecasting` には祝日以外の日付も含まれるから気を付けよう

# 背景
BigQuery ML で時系列予測をする際に、Bigqueryが祝日を考慮してくれるようになった。
具体的には下記の記事などが詳しい。
https://cloud.google.com/blog/ja/products/data-analytics/customized-holiday-modeling-with-bigquery-ml-forecasting/

で、どのような祝日が考慮されるかというと、
` select * from bigquery-public-data.ml_datasets.holidays_and_events_for_forecasting where region = 'JP' `

クリスマスやバレンタインデーも祝日として考慮されてる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44801/d0c467ad-2b13-b16f-feba-7d85e1c1cc94.png)

B向けのアプリで時系列分析されてるかたなど、ご注意ください。
バレンタインの週などに普通に業務している場合でも、「今週は祝日が含まれるのに値が通常通りだ！いい意味で異常！」とかになるかもです。（未検証）

特に、このテーブルをつかって正確に祝日判定しようとしている方がいればお勧めしません。
NK細胞(自然殺手細胞)治療

がんを殺すことが出来る主な免疫細胞は、細胞傷害性Tリンパ球(CTL)とナチュラルキラー(NK)細胞と考えられています。そのうち、CTLは殺そうとする相手方のMHC-class I分子とその上に載った抗原ペプチドを同時に認識して、相手を殺しますが、NK細胞は逆にMHC分子を発現していない細胞を殺します。

NK細胞の表面には、NK細胞の活性化を阻害する受容体分子（KIR）が発現しています。KIRには、MHC分子が結合できます。MHC分子を発現している細胞はNK細胞に殺されないようにシグナルを送るのです。

正常細胞は自己であることを示すため、MHC分子を常時発現しています。NK細胞はMHC分子を発現している細胞は殺さず、MHCタンパクを発現しなくなった“ヘンな細胞”が現れれば、それを好んで殺すような仕掛けを持っているのです。

この性質をがん治療に応用しようというのが、NK細胞療法です。しかし、これまでの経験から、 NK細胞による固形がんの治療はかなり難しいことがわかっています。

[免疫細胞療法 - ナチュラルキラー細胞（NK細胞）](https://stemcellthailand.org/natural-killer-cells-nk-cell-cancer/)，その理由は、最初に免疫刺激の期間を経ずにがん細胞に対して非特異的攻撃を実行でき、細胞活性化のマーカーとして特殊なサイトカインを放出できるためです。 細胞が正常細胞かがん細胞かを識別するには、T細胞が体内の細胞の主要組織適合性複合体1型（MHC-I）を識別する必要があり、これによりT細胞の殺傷能力が活性化されます。 しかし、NK細胞の毒制御機構は自己認識欠損説に変わってきました。 キラー免疫グロブリン受容体 (KIR) は NK 細胞の表面に発現します。がん細胞の表面に同じ KIR 受容体 (リガンド) が欠如しているか発現していない場合、活性化メッセージが NK 活性化受容体を介して伝達され、NK の殺傷効果が強化されます。 KIR は MHC-I と相互作用することができ、正常細胞の表面に結合すると、NK 細胞の細胞傷害活性を阻害します。MHC-I 分子は主に細胞内抗原を提示する役割を担っているため、MHC-I によって引き起こされる T 細胞の細胞傷害反応を回避するために、 I、がん細胞はMHC-Iを多く発現しており、正常細胞に比べて発現量が低いため、NK細胞に認識されます NK細胞ががん細胞に近づくとパーフォリンを分泌し、標的細胞膜に穴をあけてチャネルを形成しますプロテアーゼ（グランザイム）を注入することにより、標的細胞の内部溶解が起こり、アポトーシス（Apoptosis）が起こり、標的細胞を破壊します。 したがって、一部のがん細胞がMHC-Iを隠すことで特殊な免疫系T細胞による認識を回避したとしても、NK細胞はMHC-Iを隠しているこれらのがん細胞を探し出して破壊する役割を果たすことができます。

しかし、NK細胞は主に人体の末梢血系に分布しているため、採血してNK細胞を分離し、特定のサイトカインを加えて約14日間培養することで、NK細胞が大量に増殖し活性化します。これらの活性化細胞である NK 細胞は、最終的には通常の点滴によって人体に注入することができます。この高品質の免疫細胞の軍隊は、がん細胞を殺し、腫瘍の増殖やがん細胞の広がりを阻害する役割を果たすことができます。縮小したり消えたりすることさえあります。
ひとの体の中では、がんの殺し屋と呼ばれる「ナチュラルキラー細胞（NK細胞）」が活動しています。

![Screenshot 2023-09-26 at 7.28.51 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920958/4480af72-3405-7a1f-8a69-e9f19d47d7b1.png)


これは自然免疫と呼ばれるもので、全身をくまなくパトロールし、がん細胞や悪性化しそうな異常細胞を見つけると、他の細胞の指示を受けることなく瞬時に攻撃を開始します。

NK細胞は血液の中のリンパ球のおよそ10~30%を占めますが、20歳位をピークにその活性が下がっていきます。がんと十分に闘えるだけの自然免疫力を増強させるために、患者さまの少量の血液からNK細胞を活性化し増殖させたものを投与する治療が、活性NK細胞療法です。

分子レベルでがん細胞を見極めて攻撃するため、外科的な除去が難しい浸潤性のがんや、発見されにくい微細ながんにも効果が期待できます。

当院ではがんの縮小や病状回復、がん再発抑制やがん予防を目的として、特許技術で製造する活性NK細胞療法（第三種再生医療等 提供計画番号：PC3180295）をご提案しています。
【GAS】グラフにデータラベルを付ける方法

## 前置き
生成したグラフにデータラベルを付ける方法を紹介している人がいなかった為、内容は少ないですが記事として残します。
## 方法
これ↓を「newChart()」にオプションとして設定します。これだけです。
``` 
// 前略
.setOption('series', {
    0: {
        dataLabel: 'value',
    }
});
```
SOLID原則-メモ4

## リスコフの置換原則について
リスコフの置換原則（Liskov Substitution Principle, LSP）は、SOLID原則の一つであり、ソフトウェア設計において、以下の主要なガイドラインを提供します。

**「派生型はその基本型と置換可能でなければならない」**
- ここでの「派生型」とは、あるクラスから派生（継承）したクラスを指します。
「基本型」とは、派生型の基となるクラスを指します。

- この原則は、派生型が基本型の振る舞いを変更せず、新しい振る舞いを追加することを保証します。これにより、基本型のオブジェクトを派生型のオブジェクトで置換しても、プログラムの正当性が保たれることを保証します。

## 具体的な適用方法

**ポリモーフィズムの利用**
リスコフの置換原則は、ポリモーフィズムを利用して達成することができます。具体的には、基本型のメソッドを派生型でオーバーライドするときに、基本型の振る舞いを変更せず、新しい振る舞いを追加することを保証します。

## リスコフの置換原則を適用することで得られる利益

#### 1. 保守性の向上
リスコフの置換原則を適用すると、基本型のオブジェクトを派生型のオブジェクトで置換しても、プログラムの正当性が保たれるため、バグの導入を防ぐことができます。また、既存のコードが変更されないため、既存の機能が新しい変更によって壊れることがなく、保守性が向上します。

#### 2. 拡張性の向上
リスコフの置換原則に従った設計では、新しい機能を追加するための拡張ポイントが明確になります。これにより、新しい機能の追加が効率的に行えます。

#### 3. テスト容易性の向上
リスコフの置換原則を適用すると、新しい機能を追加するたびに新しいクラスを作成するため、各クラスを単独でテストすることが容易になります。

## C#の具体的なコード

#### 1. 基本型の定義
```cs
public class Bird
{
    public virtual void Fly()
    {
        Console.WriteLine("Flying...");
    }
}
```

#### 2. 派生型の定義
```cs
public class Penguin : Bird
{
    public override void Fly()
    {
        throw new NotSupportedException("Penguins can't fly!");
    }
}
```

#### リスコフの置換原則の解説
- Birdクラスは基本型であり、Flyメソッドを定義しています。これにより、Birdクラスのオブジェクトは飛ぶことができます。

- PenguinクラスはBirdクラスを継承し、Flyメソッドをオーバーライドしています。しかし、ペンギンは飛ぶことができないため、Flyメソッドは例外をスローします。これにより、PenguinクラスはBirdクラスの振る舞いを変更しています。

- この設計はリスコフの置換原則に違反しています。なぜなら、BirdクラスのオブジェクトをPenguinクラスのオブジェクトで置換すると、プログラムの正当性が保たれないからです。具体的には、Flyメソッドを呼び出すと、Penguinクラスのオブジェクトは例外をスローします。

## まとめ
リスコフの置換原則は、派生型がその基本型と置換可能でなければならないという考え方を提供する。この原則を適用することで、新しい機能を追加するたびに既存のコードを変更する必要がなくなり、バグの導入を防ぎ、保守性と拡張性を向上させることができる。また、各クラスを単独でテストすることが容易になり、ソフトウェアの品質を向上させることができる。
SOLID原則-メモ3

## 開放閉鎖の原則について
開放閉鎖の原則（Open-Closed Principle, OCP）は、SOLID原則の一つであり、ソフトウェア設計において、以下の主要なガイドラインを提供します。

**「ソフトウェアのエンティティは開放的であるべきであり、同時に閉鎖的であるべきである」**
ここでの「ソフトウェアのエンティティ」とは、クラス、モジュール、関数などのソフトウェアの構成要素を指します。

- 「開放的である」とは、そのエンティティが新しい振る舞いを追加できるようにすることを意味します。これは、新しい要件や機能が出てきたときに、それらを追加するための拡張ポイントが存在することを保証します。

- 「閉鎖的である」とは、そのエンティティが既存のコードを変更せずに新しい振る舞いを追加できることを意味します。これは、新しい機能を追加しても既存のコードは影響を受けないことを保証します。

## 具体的な適用方法

**ポリモーフィズムの利用**
開放閉鎖の原則は、ポリモーフィズムを利用して達成することができます。具体的には、インターフェースや抽象クラスを定義し、そのインターフェースや抽象クラスを実装する具体クラスを作成します。これにより、新しい振る舞いを追加するたびに新しいクラスを作成し、既存のクラスを変更することなく新しい機能を追加することができます。

## 開放閉鎖の原則を適用することで得られる利益

#### 1. 保守性の向上
開放閉鎖の原則を適用すると、新しい機能を追加するたびに既存のコードを変更する必要がなくなるため、バグの導入を防ぐことができます。また、既存のコードが変更されないため、既存の機能が新しい変更によって壊れることがなく、保守性が向上します。

#### 2. 拡張性の向上
開放閉鎖の原則に従った設計では、新しい機能を追加するための拡張ポイントが明確になります。これにより、新しい機能の追加が効率的に行えます。

#### 3. テスト容易性の向上
開放閉鎖の原則を適用すると、新しい機能を追加するたびに新しいクラスを作成するため、各クラスを単独でテストすることが容易になります。

## C#の具体的なコード

#### 1. 抽象クラスの定義
```cs
public abstract class Shape
{
    public abstract double Area();
}
```

#### 2. 抽象クラスの具体的な実装
```cs
public class Circle : Shape
{
    public double Radius { get; set; }

    public override double Area()
    {
        return Math.PI * Math.Pow(Radius, 2);
    }
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double Area()
    {
        return Width * Height;
    }
}
```

#### 開放閉鎖の原則の解説
- Shapeクラスは抽象クラスであり、Areaメソッドを抽象メソッドとして定義しています。これにより、Shapeクラスを継承するすべてのクラスは、Areaメソッドを実装する必要があります。

- CircleクラスとRectangleクラスは、Shapeクラスを継承し、Areaメソッドを具体的に実装しています。これにより、CircleクラスとRectangleクラスは、それぞれ円と長方形の面積を計算する振る舞いを持つことができます。

- この設計において、新しい形状（三角形、正方形など）を追加するたびに、新しいクラスを作成し、Shapeクラスを継承します。これにより、新しい形状の面積を計算する新しい振る舞いを追加することができます。既存のコード（Shapeクラス、Circleクラス、Rectangleクラス）は一切変更することなく、新しい機能を追加することができます。

## まとめ
開放閉鎖の原則は、ソフトウェアが変更に対して閉鎖的であり、拡張に対して開放的であるべきであるという考え方を提供する。この原則を適用することで、新しい機能を追加するたびに既存のコードを変更する必要がなくなり、バグの導入を防ぎ、保守性と拡張性を向上させることができる。また、各クラスを単独でテストすることが容易になり、ソフトウェアの品質を向上させることができる。
第2回 橋本環奈の画像を正方形にするプログラムを作成してみた

# やったこと
画像分類の勉強のため、入力された画像が橋本環奈さんであるかを判定するAIを作ろうと考えた。
前回紹介したプログラムを使って、集めた画像を正方形にトリミングするプログラムを作成した。

https://qiita.com/Naruhidon/items/985d81c5865b045b73c4

# ソースコード
正方形にする際に画像の四隅の座標を指定する必要がある。画像の中心を基準に正方形を作成すると顔が見切れることがあった。そのため画像のtopの座標は0で固定をした。

```python:TrimSquare.py
import os
import glob

from tqdm import tqdm
from PIL import Image

def crop_to_square(img_path, output_path):
    # 画像を開く
    image = Image.open(img_path)

    # 画像の幅と高さを取得
    width, height = image.size

    # 正方形のサイズを計算
    size = min(width, height)

    # 画像を正方形に切り取る
    left = (width - size) / 2
    top = 0
    right = (width + size) / 2
    bottom = size
    square_image = image.crop((left, top, right, bottom))

    # 正方形に切り取った画像を保存
    square_image.save(output_path)


# 画像のパスを取得
img_list = glob.glob('./Hashimoto/*.jpg')
# 正方形にトリミング
for img in tqdm(img_list):
    square_img_path = f'./Trimed_Hashimoto/{os.path.basename(img)}'
    crop_to_square(img, square_img_path)
```

# まとめ
第1回でダウンロードした画像を正方形にトリミングを行った。一部顔が見切れているものもあるが、一旦このままにして分類モデルを作成する。なおOpenCVやface_recognitionのライブラリを活用して、顔を検知し、顔全体が映るようにトリミングすることで顔が見切れる問題は解決できると考える。ただし1つの画像に複数人が映っている場合には対策が必要となる。

# 関連記事

https://qiita.com/Naruhidon/items/985d81c5865b045b73c4

https://qiita.com/Naruhidon/items/0b4b120c4a2d492dc1ad
テキストファイルのベクトル化とChroma DBへの保存

# はじめに
近年、テキストデータのベクトル化やデータベースへの保存は、機械学習や自然言語処理の分野で非常に重要となっています。この記事では、langchain ライブラリを使用して、テキストファイルをベクトル化し、Chroma DBに保存する方法を解説します。

# 1. テキストファイルの読み込み
まず、DirectoryLoaderを使用して、指定したディレクトリ内のテキストファイルを読み込みます。この例では、`./input/` ディレクトリ内の全ての `.txt`ファイルを読み込むように設定しています。

```py
loader = DirectoryLoader(
    "./input/", 
    glob="**/*.txt", 
    loader_cls=TextLoader, 
    loader_kwargs={'autodetect_encoding': True}
)
data = loader.load()
print(data)
```

# 2. テキストの分割
次に、`CharacterTextSplitter`を使用して、テキストをチャンクに分割します。この例では、2つの連続する改行(`\n\n`)をセパレータとして使用し、各チャンクのサイズを900文字(実際はトークン数)に設定しています。

```py
text_splitter = CharacterTextSplitter(
    separator='\n\n',
    chunk_size=900,
    chunk_overlap=0,
    length_function=len
)
documents = text_splitter.create_documents([doc.page_content for doc in data])
```

# 3. チャンクの出力
分割されたテキストチャンクを`./output/text_chunks.txt`に出力します。各チャンクの間には区切り線を挿入しています。

```py
with open("./output/text_chunks.txt", "w", encoding="utf-8") as file:
    for text in documents:
        file.write(text.page_content)
        file.write('\n--------------------------------------\n')
```

# 4. テキストのベクトル化とChroma DBへの保存
最後に、`OpenAIEmbeddings`を使用してテキストをベクトル化し、Chroma DBに保存します。この例では、`testdb`という名前のディレクトリにデータベースを保存しています。

```py
db = Chroma.from_documents(
    documents=documents,
    embedding=OpenAIEmbeddings(),
    persist_directory='testdb'
)
if db:
    db.persist()
    db = None
else:
    print("Chroma DB has not been initialized.")
```

# まとめ
langchain ライブラリを使用することで、テキストファイルのベクトル化やデータベースへの保存が簡単に行えます。このライブラリを活用することで、大量のテキストデータを効率的に処理し、機械学習や自然言語処理のタスクに活用することができます。


最後にインポートが必要なライブラリを以下に示しておきます。
```python
from langchain.document_loaders import TextLoader, DirectoryLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
```
＊この記事はcode snippetからChatGPTに作らせてます。
SOLID原則-メモ２

## 単一責任の原則について
単一責任の原則（Single Responsibility Principle, SRP）は、SOLID原則の一つであり、ソフトウェアのクラスがただ一つの責任を持つべきである、という設計原則である。

**一つのクラスは一つの責任だけを持つべきである。**
クラスが複数の責任を持つ場合、それらの責任が結合してしまい、変更の影響が他の責任にも波及してしまう可能性がある。これにより、バグの発生リスクが高まり、メンテナンスが困難になる。

**単一の責任を持つことで、クラスの再利用性が向上する。**
単一の責任を持つクラスは、他のクラスとの依存度が低くなるため、他のプロジェクトでも再利用しやすくなる。

## 具体的な適用方法

**小規模なクラスの作成**
クラスが一つの責任だけを持つように、小規模で単純なクラスを設計する。これにより、各クラスが独立し、変更やテストが容易になる。

**メソッドの分割**
一つのメソッドが複数の操作を行っている場合、それぞれの操作を独立したメソッドに分割する。これにより、各メソッドが単一の責任を持つようになる。

## 単一責任の原則を適用することで得られる利益

#### 1. 変更の容易性
単一の責任を持つクラスは、変更が容易である。変更が他の部分に影響を与えるリスクが低いため、保守性が向上する。

#### 2. 再利用性の向上
単一の責任を持つクラスは、他のクラスとの結合度が低いため、他のプロジェクトやモジュールでも再利用しやすい。

#### 3. テストの容易性
単一の責任を持つクラスはテストしやすい。単体テストを行いやすく、バグの特定と修正が容易である。

#### 4. 理解の容易性
単一の責任を持つクラスは理解しやすい。クラスとメソッドが一つの目的だけを持つため、コードの読み手は混乱することなくコードを理解できる。

#### 5. 結合度の低減
単一責任の原則に従うことで、クラス間の結合度が低減され、システム全体の柔軟性とメンテナビリティが向上する。

## C#の具体的なコード

#### 違反例
以下のクラスは、メッセージの生成と表示の2つの責任を持っています。
```cs
public class MessageService
{
    public void ShowMessage(string content)
    {
        string fullMessage = $"[INFO] {content}";
        Console.WriteLine(fullMessage);
    }
}

```

#### 適用例
以下の例では、メッセージの生成と表示を別のクラスに分けています。
```cs
public class MessageFormatter
{
    public string FormatMessage(string content)
    {
        return $"[INFO] {content}";
    }
}

public class MessagePrinter
{
    public void PrintMessage(string message)
    {
        Console.WriteLine(message);
    }
}

```

#### 使用コード
単一責任の原則に基づく実行コードは以下のようになります。
```cs
class Program
{
    static void Main()
    {
        MessageFormatter formatter = new MessageFormatter();
        MessagePrinter printer = new MessagePrinter();

        string content = "Hello, Single Responsibility Principle!";
        string message = formatter.FormatMessage(content);
        printer.PrintMessage(message);
    }
}

```

## まとめ
単一責任の原則とは、ソフトウェアのクラスが一つの責任だけを持つべきであるという原則であり，この原則に従うことで、変更の容易性、再利用性の向上、テストの容易性、理解の容易性が得られ、結合度の低減により、システム全体の柔軟性とメンテナビリティも向上することが分かった。
ExcelVBAからaccessVBAを起動したときにDocmd.quitしてもquitしてくれない問題

qiitaってめっちゃすごい内容じゃなくても技術的なアレなら書いていいんだよね？

以前ExcelVBAでaccessのVBAを呼び出す機会があって、
コードはこんな感じ

dim obja as object
Set obja = CreateObject("Access.Application")
obja.OpenCurrentDatabase "パス名"
obja.Run "モジュール名" "引数1" "引数2"
Set obja = Nothing

で、呼び出されるモジュールの最後にdocmd.quitしてもプロセスが残り続けたのよね。
タスクマネージャで強制終了したらうまくいくんだけど、ユーザー側にタスクマネージャを触らせるのはあり得ない選択肢なんで四苦八苦してたんだけど、
「終了時に最適化する設定がオンになっていると、QuitしてやってもSet = Nothingしてやってもプロセスが残り続ける」ということらしいと数日間無駄にして判明した。
だからdocmd.quitの前に
SetOption "Auto Compact", False
って書いてやって終了時の最適化をオフにしたら解決した。
これの面倒なところはコードとにらめっこしてるだけでは気づけないところ。
access側の設定を見直さないと気づけないので時間を食った。

今時accessを使うとしても、SSMSなりにリンクサーバー飛ばしてaccessにはフォームとレポートだけ持つような設計にするべきだと思う。でも、それができない古いシステムとにらめっこして苦労してる人はきっといるから。

昔Noteに書いたやつの清書版です（パクリじゃないよ）
https://note.com/firedreik/n/n436c8aa7acaf
GA4で使用した SQL3

GA4で使用したSQLの備忘録です。


<br>

### ・前々月に訪問したユーザーが前月にも訪問したユーザー数



サイトへ継続して訪問したユーザーがどれくらいいるか、その割合を確認できるクエリとなっています。
詳細として、前々月に訪問したユーザーのUIDに、前月に訪問したユーザーのUIDを結合することで、継続して訪問したユーザーを抽出しています。

<br>

```
WITH last_month_user as #先月のデータ
(
SELECT
    distinct user_pseudo_id
    , 1 as flag1
FROM
    'pmsg-portal-prd.analytics**************'
WHERE
    _TABLE_SUFFIX BETWEEN FORMAT_DATE ("%Y%m%d", DATE_TRUNC (DATE_SUB (CURRENT_DATE ('Asia/Tokyo'), INTERVAL 1 MONTH),
MONTH））＃今日の日付の1か月前の日付を出し、丸めてN-1月1日を抽出
        AND FORMAT_DATE（"%Y%md"， DATE_SUB（DATE_TRUNC（CURRENT_DATE（'Asta/Tokyo"）， MONTH）， INTERVAL 1DAY））＃今日の日付をめてN月1日を出し、1日前の数値を出すことで、N-1月最終日を抽出できる
)


,two_months_ago_user as #先々月のデータ
(
SELECT
    distinct user_pseudo_id
    ,FORMAT_DATE （“%Y%m%d"， DATE_TRUNC （DATE_SUB（CURRENT_DATE（'Asia/Tokyo"），INTERVAL 1 MONTH）， MONTH））as event_date #先月の日付はこのクエリで入れ込む
, 1 as flag2
FROM 
     'pmsg-portal-prd.analytics**************'
WHERE
    _TABLE_SUFFIX BETWEEN FORMAT_DATE ("%Y%m%d",
    DATE_TRUNC (DATE_SUB(CURRENT_DATE('Asia/Tokyo'),INTERVAL 2 MONTH),
    MONTH））#今日の日付の2か月前の日付を出し、丸めてN-2月1日を抽出
    AND FORMAT_DATE ("%Y%m%d", DATE_SUB (DATE_TRUNC (DATE_SUB (CURRENT_DATE ( 'Asia/Tokyo'), INTERVAL 1 MONTH), MONTH),
    INTERVAL 1DAY））#先月の日付を丸めてN-1月1日を出し、1日前の数値を出すことで、N-2月最終日を抽出

SELECT
    event_date
    , sum (flag2) as two_months_ago_user
    #先々月のユーザー数
    , (SELECT
        sum (flag1)
       FROM
        last_month_user
       INNER JOIN
        two_months_ago_user
       USING
        (user_pseudo_id)
       GROUP BY 
        flag1) as continue_next_month_users #先々月、先月も利用したユーサー数
    , (SELECT
        sum (flag1)
       FROM
        last_month_user
       INNER JOIN
        two_months_ago_user
       USING
        (user_pseudo_id)
       GROUP BY
        flag1) / sum(flag2) as continue_next_month_rete #先々月、先月も利用したユーザー数／先々月のユーザー数割合を算出している
FROM
    two_months_ago_user
GROUP BY
    flag2, event_date
    

```

## まとめ

上記の比率を月毎に見ることで、ユーザーの継続状況を確認することができます。
是非参考にしてみてください。
自分自身(ローカルマシン)のipアドレスを出力するワンライナー

これ

`ip route get 1 | grep -Po '(?<=src\s)[0-9\.]*'`
```
$ ip route get 1 | grep -Po '(?<=src\s)[0-9\.]*'
172.27.44.129
```

## 解説

`ip route get 1`

1は1.0.0.0の省略、`ip`コマンドで1.0.0.0へのルーティングを示します
```
$ ip route get 1
1.0.0.0 via 172.27.32.1 dev eth0 src 172.27.44.129 uid 1000 
    cache
```

`grep -Po '(?<=src\s)[0-9\.]*'`

`src *.*.*.*`はパケットの送信元IPアドレスを意味します。
そこでgrepの正規表現でsrcの次のアドレスを抽出します

-o オプション　マッチした箇所のみを表示
-P オプション　perlの正規表現を使用(前方先読みに必要)

```
$echo "1.0.0.0 via 172.27.32.1 dev eth0 src 172.27.44.129 uid 1000" | grep -Po '(?<=src\s)[0-9\.]*'
172.27.44.129
```

## 参考

https://stackoverflow.com/questions/13322485/how-to-get-the-primary-ip-address-of-the-local-machine-on-linux-and-os-x

参考記事の方法では`uid 1000`部分に騙されて正しく動作しないので修正した
プログラミングスクール卒業後のあれこれ③

プログラミングスクール卒業後のあれこれ。
だいぶ日があいてしまいましたが、続きを書こうと思います。

# 勉強になったこと
Webアプリケーション開発業務に携わることができ、なるほどなと勉強になったことを書きます。
（※わたしは実際に開発する側ではなく、開発を依頼する側の企業に所属していました。）

週に一度ベンダーさんとミーティングを行い、開発の進捗具合や依頼したい機能についての詳細を共有したり、おいおいこんなことにも目を向けたい、、など色々なことを話していました。
私は基本的に議事録を担当していました。

追加機能をデプロイする前にテストを行いますが、先輩から指示をいただきながら実際にテストをするのはわたしが主に行っていました。
- ここをクリックするとこのページに表示される
- 削除ボタンクリックするとコメントが削除される　とかねいろいろなテストをしていました。

わたしはテストに携わることが初めてですが、先輩はシステム開発に関するキャリアがありました。
こちらの会社とベンダーさんとの間の契約がどのようになっているのかわからない故に、テスト内容をピックアップするのがどちらなのか、ベンダーさん側の会社でテストしているのかなど色々とグレーなところがあり、でも早くデプロイさせてユーザーに実際に使ってもらわないといけない事情もあり、こちらで行っていました。

テストしていると、依頼していた機能が追加されていなかったり（例えば削除ボタンクリックしても実際に削除されない）期待する機能ができておらず、テスト→実装されていないため修正依頼→テストという流れが多々ありました。

ベンダーさんとはチャットツールや会社で使っているツールを利用して情報共有をしていましたので、不備があれば都度報告していました。

そこで勉強になったこと。
わたしは、「このページのこの機能ができていなかったので修正をお願いします。」
とキャプチャを撮って、チャットツールや情報共有しているツールに投稿していました。

ベンダーさん側からは期待する値を書いてください。と依頼がありました。
そして、丁寧に例文も添えていただき、書き方を教えていただきました。

いただいた例文をもう見ることはできませんが↓以下のようだったと思います。
```
このページのゴミ箱アイコンをクリックしても削除されていなかったので修正をお願いします。
期待する値：ゴミ箱アイコンをクリックすると、その投稿が削除される。〇〇のページでもその投稿が削除されている。
```
という風に明確な修正内容を添えてお願いをする必要がありました。
今振り返れば当たり前のことだったなぁと思いますが、そこまで丁寧じゃなかった自分が恥ずかしいし、でも勉強になりました。

システム周りに関わるものとして、丁寧さや細かな目配りはとても大事なことだと感じました。


他にもRPAツールを使ってシナリオ作りをしていました。
この時にもたくさんの学びがありました。
それはまた別の投稿で書きたいと思います。