OmniAICreator/Qiita-1.07M huggingface dataset:
GitHubのWikiをFork先に取得

GitHubのリポジトリをForkしても，Fork元のwikiはコピーされません．Fork元（upstreamとします）のwikiをFork先（originとします）に取得する備忘録です．SSHの利用を前提とします．originのリポジトリをローカルにCloneし，デフォルトブランチで作業します．

GitHub（origin）でwikiを有効にします．メニュー右上のSettingsをクリックし，Wikisにチェックを入れます．WikiでNew pageをクリックし，タイトルをHomeにし，本文をtest（何でもよいですが，文字を入力しないと作成できません）にして，saveします．

ローカルリポジトリでoriginのwikiをcloneします．**Clone this wiki locally**をクリックすると `https://github.com/<user>/<repo>.wiki.git` がコピーされますが，これをSSHに書き換えてgit cloneし，`<repo>ディレクトリ`に移動します．`github.com`のあとは `/` ではなく，`:` です． 
```bash
git clone git@github.com:<user>/<repo>.wiki.git
cd <repo>
```

Fork元のwikiをupstreamとして登録します．
```bash
git remote add upstream git@github.com:<upstream>/<repo>.wiki.git
git remote -v　 # 確認
```

upstreamをローカルに取得します．
```bash
$ git fetch upstream
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/upstream/master
```
upstreamのwikiのブランチ名は不明でしたが，この例ではmasterだったことが分かります．wikiは`<repo>`とは独立したリポジトリで，ブランチはmasterになるようです．

ローカルをupstreamの内容にresetし，originに強制的にpushします．
```bash
git reset --hard upstream/master 
git push --force origin master
```

GitHubのWikiは`<repo>`のブランチに依存せず，`<repo>`のすべてのブランチで同じものになります．すなわち，`<repo>`のブランチ毎にWikiを作成することはできません．
iSHで複数セッション開けるようにする

大した記事ではないです
SSHを使用して、複数セッションを開けるようにします
tmuxでも似たようなことはできますが、開いたセッションにセッションに対してスクロールができなかったり少しいまいちだったため、sshを使います

## SSH初期設定など
```sh
apk add openssh
ssh-keygen -A
# ログインパスワードを設定します
passwd 
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
```

開くポートの変更
```sh
vi /etc/ssh/sshd_config
# Port 22000を追記
```

sshd起動
```sh
/usr/sbin/sshd
```

iSHをバックグラウンドで動かせるようにする(位置情報を許可する必要があります)
```sh
cat /dev/location > /dev/null &
```

次に、SSHクライアントアプリをインストールします
私のおすすめはPortXというアプリです
他のアプリは一つのサーバーに対して複数同時接続ができなかったり、タブを開く機能が有料であったりいまいちでした

https://apps.apple.com/jp/app/portx-ssh-sftp-client/id1566480505


![IMG_6173.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785521/e42510dc-baa7-1832-eabe-32bdc1b84407.png)

これで複数のセッションを開けるようになりました
ブラウザ上で AlaSQL を利用するための下調べ（簡単なメモ）

ずいぶん前に見かけて、それから気になりつつも手をつけてなかった「[AlaSQL](https://alasql.org/)」に関する記事です。

●AlaSQL/alasql: AlaSQL.js - JavaScript SQL database for browser and Node.js. Handles both traditional relational tables and nested JSON data (NoSQL). Export, store, and import data from localStorage, IndexedDB, or Excel.
　https://github.com/AlaSQL/alasql

まずは、ブラウザで扱う想定で、その下調べをしてみました。

## AlaSQL について
AlaSQL は、上記のリポジトリの説明にあるとおり、以下の内容のものです。

- ブラウザでも Node.js でも使えるデータベース
- リレーショナルなテーブルにも ネストされた JSON のデータ（NoSQL） にも対応
- データベースの元に、ローカルストレージ、IndexedDB、Excel のデータを扱える

これをブラウザで扱うにあたって、役立ちそうな情報源をまとめてみます。

## AlaSQL に関する記事など

### CDN
まず、サクッと試す場合に便利な CDN をチェックしてみます。

有名どころで見てみたら、例えば以下はどちらも最新版を扱えそうです。

●alasql - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
　https://cdnjs.com/libraries/alasql

●alasql CDN by jsDelivr - A CDN for npm and GitHub
　https://www.jsdelivr.com/package/npm/alasql

### 公式の情報
公式の情報で、後で見てみる／試してみるつもりのものをメモしてみます。

#### サンプル
とりあえずの動作確認には、まずは以下の内容そのものか、少し変更をしたものを使ってみようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9b066822-4c36-9569-3c3f-a46f19db604c.png)

#### ドキュメント
公式ページのメニューの「Document」を選択して遷移するページが、以下の Wiki でした。
こちらから、自分が必要になりそうな情報をピックアップしていこうと思います。

●Home · AlaSQL/alasql Wiki
　https://github.com/alasql/alasql/wiki

### 日本語の記事
次に、日本語の記事をいくつかピックアップしてみます。

#### 簡単な動作確認など
以下の記事は、簡単に試せる動作確認手順などが掲載されていそうです。

●ブラウザでも使えるSQL「AlaSQL」を試そう ~動作確認から検索画面まで~ - 虎の穴開発室ブログ
　https://toranoana-lab.hatenablog.com/entry/2021/01/22/182928

#### CSV や JSONファイルを元にする
以下では、CSV や JSON のファイルを使う方法が書かれています。

●AlaSQLのデータベースに外部ファイルやWebAPIを使う方法 | あんこエデュケーション
　https://anko.education/archives/611

#### Excel のファイルを扱う
以下では、Excel のファイルを扱う話が書かれています。

●AlaSQLで、ExcelファイルからSQLを使って値を取り出す
　https://zenn.dev/nkiyo/articles/25ae4feaa1a0fe

#### ローカルストレージ上でデータベースを扱う
以下は、ブラウザのローカルストレージとの組み合わせの話について書かれています。

●ローカルストレージ上にAlaSQLのデータベースを構築する | あんこエデュケーション
　https://anko.education/archives/633

## その他

### 気になった記事
上記の記事を探す中で気になった、AlaSQL に関する何らかの内容を含む記事のメモです。

#### 方向性が類似したもの

●offline first db
　https://zenn.dev/mizchi/scraps/3d743f79adb9fd
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/992a15ce-01f8-6c8f-4ba9-b960eceb179b.png)
有機ELのSSD1306に全画面ブロックを表示(Arduino UNO)


目的
もじを表示を出来たらいいなーーーー

![o_coq109.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/97bcfb0c-efd7-fb1b-3b49-369fde565ee3.jpeg)



```c++


//ssd1306_bol_UNO_1


//ヘッダーファイル
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//1234567890
uint8_t ch_data7[8*10] = {
  0x70, 0x88, 0x98, 0xa8, 0xc8, 0x88, 0x70, 0x00, //( 48) 0 
  0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x10, 0x00, //( 49) 1 
  0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xf8, 0x00, //( 50) 2 
  0x70, 0x88, 0x08, 0x30, 0x08, 0x88, 0x70, 0x00, //( 51) 3 
  0x18, 0x28, 0x48, 0x88, 0xf8, 0x08, 0x08, 0x00, //( 52) 4 
  0xf8, 0x80, 0x80, 0xf0, 0x08, 0x08, 0xf0, 0x00, //( 53) 5 
  0x70, 0x88, 0x80, 0xf0, 0x88, 0x88, 0x70, 0x00, //( 54) 6 
  0xf8, 0x08, 0x08, 0x10, 0x20, 0x20, 0x20, 0x00, //( 55) 7 
  0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, //( 56) 8 
  0x70, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70, 0x00, //( 57) 9 
};

uint8_t c_block[8] = {
  0b11111110,
  0b11111110,
  0b11111110,
  0b11111110,

  0b11111110,
  0b11111110,
  0b11111110,
  0b00000000
};

uint8_t t_block[2][8][8];


//初期化
void setup() {

  //i2cの初期化
  Wire.begin();

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

  //表示方向
  display.setRotation(0);

}//setup


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

  // 画面表示をクリア
  display.fillScreen(BLACK);

for(int ii=0;ii<2;ii++){
  for(int y=0;y<8;y++){
    for(int x=0;x<8;x++){

t_block[ii][y][x] = 1;

    }//for x
  }//for y
}//for ii

//t_block[0][3][3] = 0; //debug

for(int ii=0;ii<2;ii++){
  for(int y=0;y<8;y++){
    for(int x=0;x<8;x++){

if( t_block[ii][y][x] != 0){
  display.drawBitmap( (x*8) + (ii*64) , y*8, c_block, 8, 8,  WHITE);
}//if
      
    }//for x
  }//for y
}//for ii



  // 描画バッファの内容を画面に表示
  display.display();

  delay(1000); //1秒待つ

}//loop



```
【ServiceNow】【入門編】Customer Service Management有効化

# はじめに
本記事では、ServiceNowでCustomer Service Managementを有効化する方法を記載します

# Customer Service Managementとは
公式サイトでは下記の通り、特徴が記載されています
> - 顧客が容易に取り組めるようにする
> - タスクを企業全体でアサイン
> - 問題を監視してケースを自動で作成
> - 今後の呼び出しを防止
> - ケースのボリュームをセルフサービスで削減

引用：https://docs.servicenow.com/ja-JP/bundle/utah-customer-service-management/page/product/customer-service-management/concept/customer-service-bus-unit-overview.html

簡単にまとめると、組織と顧客間でのコミュニケーションツール・管理ツールといったところです
- 顧客とのコミュニケーションをとるための窓口の機能
- 顧客からの問い合わせ（ケース）のアサイン自動化、履歴管理、ステータス管理
- ナレッジベース機能　etc...

# 導入手順
Customer Service Managementはデフォルトではインストールされていない機能です
そのため、プラグインをインストールする必要があります

①検索バーより、Pluginsを検索します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/af59d302-3e48-dfe8-1d42-749983c5aca5.png)

②Search your licensed applications and pluginsにて、【com.sn_customerservice】を検索します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/02080b3a-89eb-6a92-5ab2-61e3852c5b89.png)

③Family plugins欄にある【Customer Service】を押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/7afba084-b225-fbba-50f8-6597bd13bd1d.png)

④【Install】を押下します
※下部には依存関係にあるプラグインが表示されており、同時にインストールされます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/8ec51a9e-3928-7175-4a4e-d1f7e4a82be3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/173f807a-9bb5-c9cc-fd71-5aa7b80275bf.png)

⑤【Install now】を選択して、【Install】を押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/e3e0192e-f06f-f242-f853-1d1e5962ce44.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/dd799e9b-a832-d77e-c819-11aca8579691.png)

⑥インストールが完了するまで待機します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/25d0ebee-8849-77b7-cbb3-28fe8fbe5ab7.png)

※インストールが完了すると下記画面になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/64c6c6f6-b1b8-94d9-2a2f-03fee50df755.png)

⑦ログアウト・ログインしてから、Allを確認すると、Customer Serviceという項目が増えています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3698496/8b0a8b43-1fdd-eeaf-5308-118271b4ed72.png)

以上でCustomer service Managementの有効化は完了です

# おわりに
今回はCustomer Service Managementの有効化の仕方を記載しました
他のServiceNowの機能についても同様の方法でインストールが可能です
また、今回の方法はCustomer Service Managementの基礎の機能だけ入っているため、オプション機能を有効化する場合はまたプラグインの導入が必要になります

# 参考
https://docs.servicenow.com/ja-JP/bundle/utah-customer-service-management/page/product/customer-service-management/task/t_ActivateCustomerService.html
有機ELのSSD1306にブロックを表示(Arduino UNO)


目的
ブロックのパターンを作りたい。


![o_coq108.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/fba7a2d6-ed2a-1813-0b9c-72a4a261fa6d.jpeg)


```c++




//ssd1306_bol_UNO_1


//ヘッダーファイル
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//1234567890
uint8_t ch_data7[8*10] = {
  0x70, 0x88, 0x98, 0xa8, 0xc8, 0x88, 0x70, 0x00, //( 48) 0 
  0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x10, 0x00, //( 49) 1 
  0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xf8, 0x00, //( 50) 2 
  0x70, 0x88, 0x08, 0x30, 0x08, 0x88, 0x70, 0x00, //( 51) 3 
  0x18, 0x28, 0x48, 0x88, 0xf8, 0x08, 0x08, 0x00, //( 52) 4 
  0xf8, 0x80, 0x80, 0xf0, 0x08, 0x08, 0xf0, 0x00, //( 53) 5 
  0x70, 0x88, 0x80, 0xf0, 0x88, 0x88, 0x70, 0x00, //( 54) 6 
  0xf8, 0x08, 0x08, 0x10, 0x20, 0x20, 0x20, 0x00, //( 55) 7 
  0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, //( 56) 8 
  0x70, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70, 0x00, //( 57) 9 
};

uint8_t c_block[8] = {
  0b11111110,
  0b11111110,
  0b11111110,
  0b11111110,

  0b11111110,
  0b11111110,
  0b11111110,
  0b00000000
};

uint8_t t_block[2][8][8];


//初期化
void setup() {

  //i2cの初期化
  Wire.begin();

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

  //表示方向
  display.setRotation(0);

}//setup


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

  // 画面表示をクリア
  display.fillScreen(BLACK);


  display.drawBitmap( 0, 0, c_block, 8, 8,  WHITE);


  // 描画バッファの内容を画面に表示
  display.display();

  delay(1000); //1秒待つ

}//loop



```
自作PCにSSDを増設してWindowsとUbuntuをデュアルブートしてみた

WindowsとUbuntuをデスクトップPCにデュアルブートしてみました。SSDを
増設しそれぞれのディスクに別々にインストールする方法を共有しています。
誰かの参考になれば幸いです。

# はじめに
メインのOSとしてWindowsがインストールされた自作PCを組みました。
仕事でUbuntuを触ることが多く、プログラミングや機械学習の勉強をLinux(Ubuntu)環境で行いたいためLinuxの環境構築を行いました。
※記事内でLinuxやUbuntuと表記ゆれがありますが、同じものを指していると考えて下さい

WindowsPCでLinux開発を行うのであればWSLやVirtualBoxなどといった仮想マシン上で行うこともできます。しかし、WindowsOS上に構築したLinuxではリソースに制約がかかったり、そもそも開発中はWindowsOSが立ち上がっている必要がないため生のLinuxをデュアルブートして開発を行おうと考えました。

# 今回実施するデュアルブート方法について
デュアルブートは1つのディスクに2つのOSを入れることで実現もできますが、ネットの記事を調べると1つのディスクにWindowsとLinuxを入れるとブートローダが正常に動作しなくなってしまったり、パーティションをいじることで起動不能になったりもすることがあるようです。(この記事にたどり着くあなたであればこれらの報告はすでにご覧になっているかと思います。)
またMicrosoftの公式の回答でも[Microsoftは、OSのデュアルブートでの動作を保証していない](https://answers.microsoft.com/ja-jp/windows/forum/all/windows1110%e3%81%ae%e3%83%87%e3%83%a5%e3%82%a2/4ab98578-17b8-40cb-8725-d2ce3f3901cb)とのこと。

Windows、Linuxの両OSともに大事なデータが入っており起動できなくなってしまっては困るので、今回はSSDを増設しWindowsとLinuxがインストールされたディスクを分け、それぞれ個別に管理できる環境を目指します。

# PC環境

今回デュアルブート環境を構築する自作PCは以下の構成となっています。

* SSD:キオクシア KIOXIA SSD 1TB NVMe M.2 (×2枚)
    * 搭載OS（1枚目SSD）：Windows11 Pro(23H2)
    * 追加OS（2枚目SSD）：Ubuntu Desktop 24.04 LTS
___
* マザーボード：ROG STRIX B760-G GAMING WIFI (ASUS)
* CPU：Intel(R) Core(TM) i7-14700F
* GPU：RTX4070

# Ubuntuインストールメディアの作成
今回は[こちらのURL](https://jp.ubuntu.com/download)から`Ubuntu Desktop 24.04 LTS`をインストールします。
インストールメディア作成の詳しい方法はネット上にたくさん上がっているので、詳しく知りたい方はそちらを参考にしてください。

**インストールファイル：**
![iso_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604944/87e116a8-e061-4931-2618-6b563bdf1500.png)

次にインストール用のUSBメディアを作成します。
[rufas](https://rufus.ie/ja/)というソフトウエアを使用して以下の手順でインストール用のUSBメディアを作成します。

1. デバイスにインストール用のUSBメディアを選択します
2. ブートの種類を選択します。選択ボタンをクリックし先ほどダウンロードした`Ubuntu.iso`を選択します
    2'. 選択したファイルが表示される
3. フォーマットオプションを設定します
4. 状態が準備完了となっていることを確認し、スタートボタンをクリックします
5. 出力されるウインドウをOKを押して作業を進めます


![rufas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604944/4d3fadfb-f6fd-89f5-140f-98e7c62d62d3.png)
※USBをフォーマット（初期化）するので、USB内に保存してあるデータは消えてしまいます。消えてほしくないデータがある場合は別の場所にバックアップを取ってください。


# 増設SSDへubuntuをインストール
実際に増設したSSDにUbuntuをインストールして行きます。
まず最初にすでにWindows11が入ったSSDをマザーボードから取り外し、UbuntuをインストールするSSDのみを取り付けます。

|SSD1（Win11インストール済み）|SSD2（Ubuntuのインストール先）|
|:---:|:---:|
|![SSD1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604944/9e6ce5b7-f18c-f089-5883-d0c464d7300b.png)|![SSD2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604944/fbe690eb-a7fc-ae43-3d45-0e567ab04878.png)|

インストール用のUSBを差し込みPCを起動させます。
※インストール画面のスクショを撮影していたのですが、SSDディスクにインストール時にディスクを削除してインストールしたため保存画像が消えてしまいました。:sob:
手順としては[こちらのページ](https://higmasan.com/ubuntu/ubuntu24-04/install-ubuntu-24-04-lts/)と同じなので、こちらを参考にしてください。

インストールが完了したのを確認したのち、PCの電源を切りWindows11が入ったSSDを取り付けます。
![dualSSD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604944/cbabc8c6-8e2b-415b-d5d7-44cf78dc7d20.png)


# BIOSの確認
2つのOSが正しく認識されているかを確認します。
BIOS（UEFI）画面に入りブートの設定を確認します。
以下画面はASUSのUEFIとなります。

![UEFI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604944/e9a5ec58-3605-c692-a8c4-44553cad24c4.png)

画面右側の起動優先順位の箇所で`Ubuntu（M.2‗2）`と`Wondows Boot Manager（M.2_1）`と2つのOSがそれぞれのSSDで認識されていることがわかります。
オブジェクト指向プログラミングにおけるカプセル化の重要性と実践方法

## はじめに
カプセル化は、オブジェクト指向プログラミングにおいて非常に重要な概念です。この記事では、カプセル化の概要とその重要性、さらに実際のコーディングでのカプセル化の実践方法について解説します。

## カプセル化とは
カプセル化は、データ（変数）とそのデータに対する操作（メソッド）を一体化し、外部からのアクセスを制限するプログラミングの手法です。主な特徴は次の通りです。

1. **データ隠蔽**: オブジェクトの内部で使用されるデータを外部から隠蔽し、直接アクセスできないようにする
2. **データの安全性**: データ隠蔽により、データが外部で誤って変更されることを防ぎ、データの安全性を確保する
3. **情報の集約**: 関連するデータと操作を一体化して管理し、オブジェクトの内部構造を隠蔽しつつ機能を提供する
## カプセル化の実践方法
以下は、TypeScriptを使用した実践的なカプセル化の例です。

```ts
class Car {
    private speed: number; // プライベートな変数

    constructor() {
        this.speed = 0;
    }

    accelerate(amount: number) {
        this.speed += amount;
    }

    getSpeed() {
        return this.speed;
    }
}

let myCar = new Car();
myCar.accelerate(50);
console.log(myCar.getSpeed()); // 結果は 50
```
この例では、Car クラス内の speed 変数をプライベートにしています。外部から直接 speed 変数にアクセスすることはできませんが、accelerate メソッドを通じて speed 変数の値を変更できます。また、getSpeed メソッドを通じて speed 変数の値を取得できます。これにより、データの隠蔽と安全な操作が実現されています。

## まとめ
カプセル化は、オブジェクト指向プログラミングにおいてデータの隠蔽と安全な操作を実現する重要な概念です。適切なカプセル化を行うことで、コードの保守性や拡張性を向上させることができます。
「Наф напы кэр̌ӄӈ идыйныд лу」はUniversal Dependenciesで書けるのか

蔡熙鏡『[ニヴフ語東サハリン方言の参照文法](https://doi.org/10.15026/99812)』(東京外国語大学大学院総合国際学研究科, 博士(学術)論文12603甲第286号, 2020年3月)を横目に、「Наф напы кэр̌ӄӈ идыйныд лу」をUniversal Dependenciesで書いてみることにした。

```
# text = Наф напы кэр̌ӄӈ идыйныд лу 
1	Наф	наф	ADV	副詞	_	4	advmod	_	_
2	напы	напы	ADV	副詞	_	4	advmod	_	_
3	кэр̌ӄӈ	кэр̌ӄӈ	NOUN	名詞	_	4	obj	_	_
4	идыйныд	идыдь	VERB	動詞	_	0	root	_	_
5	лу	-ло	PART	疑問助詞	_	4	mark	_	_
```

![niv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/0a9ea550-b07f-619c-3d73-ef21d3137d1e.png)

LEMMA(辞書見出し形)を、Чунер Михайлович Таксами『[Словарь нивхско-русский и русско-нивхский](https://e.nlrs.ru/open/52663)』(Просвещение, 1996年)に接地することにしたが、この辞書には品詞が書かれていない。とりあえずXPOSは、丹菊逸治『ニヴフ語サハリン方言基礎語彙集(ノグリキ周辺地域)』(東京外国語大学アジア・アフリカ言語文化研究所, 2008年3月)から借りてくることにした。ニヴフ語の動詞に対しては、FEATSを充実する方がいいとは思うのだが、作業量を考えて現時点では空欄にしている。

こうして書いてみると、この例文に関しては私(安岡孝一)が見る限り、二ヴフ語と[イテリメン語](https://qiita.com/KoichiYasuoka/items/966ec19eeaabc69a9440)と[アイヌ語](https://qiita.com/KoichiYasuoka/items/f39e1c5f8716a810df9e)と[韓国語(形態素単位)](https://qiita.com/KoichiYasuoka/items/e3b458c98c83473d1e95)で、言語構造が全く異なっている。他言語のUniversal Dependenciesからの知識転移は、かなり困難だと思われる。
【JavaScript】アニメーション完了後にstyleの一部を変更する方法

以下のように記述するとアニメーション完了後に一部のstyleを更新できます。

```js
const animation = element.animate(
  [
    { height: '0px', width: '100px' },
    { height: '200px', width: '100px' },
  ],
  {
    duration: 200,
    easing: 'ease-out',
    fill: 'forwards',
  }
)
// アニメーションの完了を待つ
animation.finished.then(() => {
  animation.commitStyles()  // アニメーション完了時のスタイルをstyle属性に反映
  animation.cancel()  // アニメーションをキャンセル
  element.style.height = 'auto'  // style の height を auto に変更
})


```
`animation.commitStyles（）`を実行してstyle属性に完了時のスタイルを反映します。

`animation.cancel()`しないとアニメーション完了時の`height: '200px'`が優先されてしまいます。

https://developer.mozilla.org/ja/docs/Web/API/Animation/finished

https://developer.mozilla.org/ja/docs/Web/API/Animation/commitStyles

https://developer.mozilla.org/ja/docs/Web/API/Animation/cancel
kindをインストールする。

うまくできなかったので、ここにkindインストール方法を書きます。

```
WSLを削除しました。
PowerShellで
wsl --unregister Ubuntu
を使ってUbuntuの登録を解除します。
wsl.exe --install Ubuntu24.04
これで再インストール。
```
まずubuntuのバージョンを22.04→24.04に上げました。

つぎにgoのインストール
```
~$ wget https://go.dev/dl/go1.22.2.linux-amd64.tar.gz
~$ tar zxvf go1.22.2.linux-amd64.tar.gz
~$ sudo mv go /usr/local/
~$ rm -rf go1.22.2.linux-amd64.tar.gz
~$ cat << "EOF" >> ~/.bashrc
export PATH=$PATH:/usr/local/go/bin
EOF
~$ /bin/bash
~$ go version
go version go1.22.2 linux/amd64
```

Docker インストール
```
~$ sudo apt-get update
~$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
~$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
~$ sudo apt-get update
~$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
~$ systemctl is-enabled docker.service
```
```
kubectl インストール
~$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
~$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
~$ sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
~$ kubectl version --client
```

kind インストール
```
~$ GOPATH=/usr/local/go/ go install sigs.k8s.io/kind@v0.22.0
~$ which kind
/usr/local/go/bin/kind
~$ kind --version
kind version 0.22.0
```

こうなればOK!

```
kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.29.2) 🖼 
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Have a nice day! 👋
```

参考サイト
```
https://techblog.ap-com.co.jp/entry/2024/04/23/120021#kubectl-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
```
Flutter 〜Extract Widgetでクラスの分割〜

コードが煩雑になったときにクラスを分割する。
以下のようなコードがあったとする。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            //PaddingでTextFieldをラッピング
            Padding(
              padding: const EdgeInsets.all(30.0), //寄せる量を指定
              child: TextField(
                decoration: InputDecoration(
                    labelText: '名前',
                    hintText: '名前',
                    icon: Icon(Icons.account_circle)),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

```
実行するとこんな画面
<img width="40%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/ddf7dd81-e75e-d913-7db0-7955d1eaa0f2.png" >

bodyのColumnウィジェットを別のクラスとして定義する。
Columnウィジェットを選択し、電球マークをクリック→Extract Widgetをクリック。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/30078fde-efa8-cd13-86ff-4c5297934840.png">

Widget名を入力する。とりあえずデフォルトのNewWidget。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/5595cb56-f06e-387c-2d42-cd081b84bc37.png)

body部分がNewWidgetクラスとして自動的に定義される。
実行しても見た目に変化はない。
```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: NewWidget(),
      ),
    );
  }
}

class NewWidget extends StatelessWidget {
  const NewWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        //PaddingでTextFieldをラッピング
        Padding(
          padding: const EdgeInsets.all(30.0), //寄せる量を指定
          child: TextField(
            decoration: InputDecoration(
                labelText: '名前',
                hintText: '名前',
                icon: Icon(Icons.account_circle)),
          ),
        ),
      ],
    );
  }
}
```
<img width="40%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/ddf7dd81-e75e-d913-7db0-7955d1eaa0f2.png" >
TypeScriptの基本構文一覧

## 1. HelloWorld
```typescript
console.log('Hello World!');
```
## 2. 変数宣言
```typescript
// 文字列
let message: string = 'Hello TypeScript';
// 数字
const number: number = 42;
// 小数もnumber
const pi: number = 3.14159;
// 論理値
const bool: boolean = true;
```
## 3. 分岐
### if文
```typescript
let score = 90;

if (score > 80) {
    console.log('素晴らしい！');
} else if (score > 60) {
    console.log('頑張りましたね！');
} else {
    console.log('より良い結果を目指しましょう。');
}
```
### switch文
```typescript
let color = 'red';

switch (color) {
    case 'red':
        console.log('止まれ！');
        break;
    case 'yellow':
        console.log('注意！');
        break;
    case 'green':
        console.log('進め！');
        break;
    default:
        console.log('無効な色です。');
}
```
### 三項演算子
```typescript
let isAuthenticated = true;
console.log(isAuthenticated ? 'ログイン済み' : 'ログインしてください');
```
## 4. 繰り返し
```typescript
for (let i: number = 0; i < 5; i++) {
    console.log(i);
}
```
## 5. 関数
```typescript
function greet(name: string): string {
    return 'Hello, ' + name;
}

console.log(greet('TypeScript'));
```
#### アロー関数
```typescript
const greetArrow = (name: string) => `Hello, ${name}`;

console.log(greetArrow('TypeScript'));
```
## 6. クラスとオブジェクト
```typescript
class Person {
    name: string;

    constructor(name: string) {
        this.name = name;
    }

    greet(): void {
        console.log('Hello, ' + this.name);
    }
}

const person = new Person('John');
person.greet();
```
## 7. エラー処理
```typescript
try {
    throw new Error('Something went wrong');
} catch (e: any) {
    console.error(e.message);
}
```
## 8. リスト（配列）
```typescript
let numbers: number[] = [1, 2, 3, 4, 5];
console.log(numbers);
```
## 9. 辞書（連想配列）
```typescript
// key が String、value が String ある事を宣言している
let person1: { [key: string]: string } = {
    name: 'John',
    age: '30' // String
};
console.log(person1.name);
```
## 10. ファイル入出力
```typescript
import {readFile, writeFile} from 'fs/promises';

async function writeFileExample() {
    await writeFile('example.txt', 'Hello TypeScript');
    console.log('File written');
}

async function readFileExample() {
    const content = await readFile('example.txt', 'utf8');
    console.log(content);
}

writeFileExample().then(() => readFileExample());
```
【Vue3】definePropsで宣言したpropsを参照する

`<script setup>` タグの中で参照するには次のように `porps.` を付けて記述する。

```vue
<script setup>
const props = defineProps({
    id: {
        type: Number,
        required: true
    },
    title: {
        type: String,
        required: true
    },
})

function navigateToPage() {
    // defineProps で宣言した props を参照
    window.location.href = '/articles/' + props.id
}
</script>

<template>
    <div class="card" @click="navigateToPage">
        <!-- props.title と書く必要はない -->
        <h2>{{ title }}</h2>
    </div>
</template>
```

参考

https://ja.vuejs.org/guide/essentials/component-basics.html#passing-props
K3sでNGINXのPodを動かしてみた

# はじめに
[以前の記事](https://qiita.com/fukunagt/items/f7994f8fb32a9b758c6a)で、WSL2のDebianでK3sを起動してみました。本記事ではNGINXのPodをK3sで動かしてみました。


# 構成図
```
+-----------------------+
| +-------------------+ |
| | +---------------+ | |
| | | +-----------+ | | |
| | | | +-------+ | | | |
| | | | | NGINX | | | | |
| | | | +-------+ | | | |
| | | | K3s       | | | |
| | | +-----------+ | | |
| | | Debian 12     | | |
| | +---------------+ | |
| | WSL2              | |
| +-------------------+ |
| Windows 10            |
+-----------------------+
```

# マニフェストファイルを作成する
1. nginx.yamlファイルを作成してください。
   ```sh
   touch nginx.yaml
   ```
1. viなどで以下のように編集してください。
   ```yaml
   apiVersion: v1
   kind: Pod
   metadata:
     name: nginx
     labels:
       app: nginx
   spec:
     containers:
       - name: nginx
         image: nginx
         ports:
         - containerPort: 80
   ---
   apiVersion: v1
   kind: Service
   metadata:
     name: nginx
   spec:
     type: NodePort
     ports:
       - name: nginx
         protocol: TCP
         port: 80
         targetPort: 80
         nodePort: 30080
     selector:
       app: nginx
   ```
1. 上記ファイルを適用してください。
   ```sh
   sudo k3s kubectl apply -f nginx.yaml
   ```
1. PodおよびServiceが作成されていることを確認してください。
   ```sh
   $ sudo k3s kubectl get pod,svc
   NAME        READY   STATUS    RESTARTS   AGE
   pod/nginx   1/1     Running   0          18s
   
   NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
   service/kubernetes   ClusterIP   10.43.0.1     <none>        443/TCP        13h
   service/nginx        NodePort    10.43.73.97   <none>        80:30080/TCP   18s
   ```
1. NGINXにアクセスできることを確認してください。
   ```sh
   curl 127.0.0.1:30080
   ```
   - Windowsから実行する場合は、DebianのIPアドレス (e.g., 172.23.210.56) を`ip a`コマンドなどで確認してください。
     ```ps
     curl 172.23.210.56:30080
     ```
     ```ps
     PS C:\> curl 172.23.210.56:30080
     <!DOCTYPE html>
     <html>
     (snip)
     <body>
     <h1>Welcome to nginx!</h1>
     (snip)
     ```
1. ついでに、`kubectl top`コマンドも実行してください。
   ```
   $ sudo k3s kubectl top pod
   NAME    CPU(cores)   MEMORY(bytes)   
   nginx   0m           4Mi 
   ```

# さいごに
K3sでNGINXを動かすことに成功しました。せっかく作ったK3s環境なのでいろいろ試してみたいと思います。
【AtCoder】備忘録ABC347-B


## 問題

https://atcoder.jp/contests/abc347/tasks/abc347_b

PHPで解いています。
B問題はネストした繰り返し処理が肝のよう。

## 解答

```php
<?php

$s = trim(fgets(STDIN)); 
$n = strlen($s); //文字数の長さを取得

$substrings = [];

//全ての部分文字列を生成し、集合に追加する
for ($i = 0; $i < $n; $i++) {
    for ($j = $i + 1; $j <= $n; $j++) {
        $sub = substr($s, $i, $j - $i); 
        $substrings[$sub] = true;
    }
}


echo count($substrings);

```

## つまづいたポイント
:::note info
**重複する部分文字列を複数回数えていた。**<br>→各部分文字列を集合（セット）に格納し、最終的にその集合の要素数を出力する
:::

```php
$substrings[$sub] = true;
```
↑これより、重複する部分文字列は集合に一度しか追加されず、最終的な集合の要素数が部分文字列の種類の数となる。
var_dumpすると、、、
```php
$substrings = [
    "a" => true,
    "aa" => true,
    "aab" => true,
    "aaba" => true,
    "aabab" => true,
    "aababc" => true,
    "ab" => true,
    "aba" => true,
    "abab" => true,
    "ababc" => true,
    "b" => true,
    "ba" => true,
    "bab" => true,
    "babc" => true,
    "a" => true,
    "ab" => true,
    "abc" => true
];
```
OracleMaster Silver取得への道①

## はじめに
こちらは、資格試験準備セミナー: ORACLE MASTER Silver DBA 2019 / Certification Exam Prep Seminar ORACLE MASTER Silver DBA (JP)に参加し、学んだことをまとめたものになります。

## OracleDBアーキテクチャ、インスタンス管理
### シングル構造のDBとインスタンス
・シングル構造のOracleDBサーバは、インスタンスとDBが1:1の関係、そして、インスタンスとDBファイルは、同一のサーバ上に配置される。
・１つのDBサーバに複数のDBファイルを配置することができ、それぞれのDBファイルに対応したインスタンスを起動することになる。

### バックグラウンドプロセス
| プロセス名  |     説明      |
| --- | ----------- |
| データベースライター（DBWn）　| データベースバッファキャッシュ内の変更済みブロックをデータファイルに書き込む |
| ログライター（LGWR）    | RED0ログバッファのRED0データ（変更履歴情報）をRED0ログファイルに書き出す |
| チェックポイント（CKPT）    | DBWnに対して、データベースバッファキャッシュ内の変更済みブロックをデータファイルに書き込む指示を出す（チェックポイント）。併せて、制御ファイルにチェックポイント情報を書き込む |
| システムモニター（PMON）    | プロセスが異常終了した場合、そのプリセスが使用していた様々なデータやリソースの後処理（クリーンアップ）を実行する。アイドル時間を超えたセッションを検知し、強制終了などの対処を指示する |
| 管理モニター（MMON）    | AWRスナップショットなど、性能分析で使用される様々な統計情報を定期収集する |
|アーカイバ（ARCn）　     |ログスイッチの発生後、RED0ログファイルのRED0データをアーカイブファイルとしてコピーする|
|リスナー登録プロセス（LREG）|インスタンスに関する情報をリスナーに登録する|

### OracleDB立ち上がるまで
![スクリーンショット 2024-05-11 17.40.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759541/04794bff-bee0-822c-f124-10b19b06fed3.png)

### データ・ディレクショナリに関して
Oracleデータベースで最も重要な部分の1つであり、データベースに関する情報を提供する読取り専用の表の集合。データ・ディクショナリには次のものが含まれる。

* データベース内のすべてのスキーマ・オブジェクト（表、ビュー、索引、クラスタ、シノニム、順序、プロシージャ、ファンクション、パッケージ、トリガーなど）の定義
* スキーマ・オブジェクトに割り当てられている領域と、現在使用されている領域の容量 
* 列のデフォルト値
* 整合性制約に関する情報
* Oracle Databaseユーザーの名前
* それぞれのユーザーに付与されている権限とロール
* 各種スキーマ・オブジェクトにアクセスまたは更新したユーザーなどの監査情報
:::note
ポイント
データ・ディレクショナリはsysの所有物である
:::

### トレースファイルに関して
* サーバー・プロセスによって書き込まれる
→エラーが起こった時だけに書き込まれるものじゃない、診断のようなもの
* バックグラウンド・プロセスにとって書き込まれる
* トレースファイルの名称
→```<SID>_ora_<process_id>.trc```
dify-dockerをMacで立ててみた

# 注意
archlinuxでdifyを立てる領域にまだ僕は（エラーがいっぱい出ます）

docker と docker-composeについては
mac:brewです
archlinux:yayです

ubuntu:[dockerのインストール](https://qiita.com/nanbuwks/items/0ba1d13b3cd27e5c6426)を参考にしています。

# インストール
difyのインストール
```
git clone https://github.com/langgenius/dify.git
```

# 起動方法
```
cd dify
cd docker
docker compose up -d
```
終わり

# 感想
完走した感想ですが、とても簡単ですね☺️

# 参考
https://qiita.com/nanbuwks/items/0ba1d13b3cd27e5c6426
複数のサーバーでobnizが動いてしまっている時


Node-REDでobnizを使っていると、obnizがこんな感じでconnecting...から動かないってことがたまにあります。

> ![スクリーンショット 2024-05-11 22.52.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c133058c-8f59-15f8-9263-b19c8defa417.png "スクリーンショット 2024-05-11 22.52.29.png")

他のサーバーを見てみるとつながっていることが分かりました。

> ![スクリーンショット 2024-05-11 22.52.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/fde3a773-7b8c-7dc4-1b2a-ad06d6e3e5b0.png "スクリーンショット 2024-05-11 22.52.32.png")

これをどうやって見つけるか。


## obnizのコンソールからIPをチェック

コンソールを見るとIPがわかってどこからのアクセスが今有効になっているのかがわかります。

> ![スクリーンショット 2024-05-11 22.55.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c14bac78-f295-84ed-8bf6-b00548b4c98f.png "スクリーンショット 2024-05-11 22.55.37.png")


## トークンを使って強制解除

![スクリーンショット 2024-05-11 22.59.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/e447e195-ca21-acaa-4478-49ec30329ed8.png "スクリーンショット 2024-05-11 22.59.31.png")

![スクリーンショット 2024-05-11 22.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/fea1255e-9237-b5a4-32f9-6aad3920c4e5.png "スクリーンショット 2024-05-11 22.59.49.png")

こんな感じでトークンを発行すると強制的に接続が解除されます。

アクセストークンを発行して少し経つと

> ![スクリーンショット 2024-05-11 23.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b74aff8c-7e45-c1bf-7ae2-e045cdebcb80.png "スクリーンショット 2024-05-11 23.01.11.png")

obniz IDを管理コンソールに最初に登録してないとだめですが

## 新しく接続するNode-RED環境でトークンを指定

このままだと全てアクセスできないので新しい環境にはトークンを指定します。

> ![](https://i.gyazo.com/97aa622ee009cc2dc4ca1b6e45cba9a9.png)

obnizの設定ノードに設定できます。

再度デプロイすると新環境の方でconnectedになりました。

> ![スクリーンショット 2024-05-11 23.07.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a5a7f864-046a-cc45-fa5b-37843ced2475.png "スクリーンショット 2024-05-11 23.07.29.png")

これで入れ替え完了です。
【Tableau prep】prepを用いた差分更新の方法

Tableau serverやTableau prepで標準機能としてある増分更新は有名ですが、
昨日入力したデータが誤りで修正したい場合など、既に入力してあるデータが更新されている場合にパブリッシュ先でも更新する**差分更新** の手法を紹介いたします！

## 想定する差分更新とは （増分ももちろん反映されます。）
すでに入力されているデータが更新された場合と新規にデータが入力された場合に反映。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/54673003-ca18-90aa-b8f1-25023fc3ee9d.png)


## 用意したデータ
●2020/1/31　時点のデータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/9f75420d-4a53-992b-7327-913262b62723.png)

●2020/2/1　時点のデータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/5b8bd34c-a444-3b78-7f55-5e6c401f5f76.png)

●2020/2/1　【データ更新後の想定される結果】
過去に入力された伝票に変更があった場合は更新する。
新しく入力された伝票も反映する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/c22acbb8-6f81-509d-6550-29fc458523eb.png)

## prep作成
それでは実際にprepを作成していきます。
2020/1/31が青、2020/2/1がオレンジのデータです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/7b29f087-d270-7cd2-2398-0e2c7b934cc9.png)

### ①結合
一意であるコードを結合句として完全外部結合(FULL JOIN)をします。
今回の場合は、会社コード、商品コード、得意先コードが結合句となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/90e9e50f-ac53-9920-9caa-0859ae192134.png)

### ②マージ
先ほど結合句として使用した会社コード、商品コード、得意先コードをマージする
※-1がついている方が新しいデータです。（今回の場合2020/2/1）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/f80e014a-d212-7cd2-9204-8237e95b97b9.png)

マージ後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/aa303524-708a-2940-e667-e7effe8d2806.png)

### ③更新

●今回値を更新したい、仕入金額、仕入商品個数、売上金額について
データが更新されている場合、もしくは新規に行が追加されている場合更新していきたいと思います。
※-1がついている方が新しいデータです。（今回の場合2020/2/1）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/455cf23b-bb97-9ca1-f271-eb047bc8295b.png)
```
IF [更新日付-1]>[更新日付]
THEN [仕入金額-1]
ELSE IFNULL([仕入金額],[仕入金額-1])
END
```
同じように、仕入商品個数、売上金額についても計算式を作成する。

●更新日付についても計算式を作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/b4893197-472d-7ad9-70eb-da228fac5c30.png)
```
IF [更新日付-1]>[更新日付]
THEN [更新日付-1]
ELSE IFNULL([更新日付],[更新日付-1])
END
```
更新後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/46600b82-9754-402f-0e64-7a393178d9a3.png)

### ④整える
今回はわかりやすくするために計算式で作成した項目名の末尾に「_更新済み」と付けました。
元となるデータについては不要なのでここで削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/0e6d622b-2418-ee81-3e5d-18a85cb7ec96.png)

### ⑤出力
実際に出力したExcelファイルを見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/cca649e3-2c52-5e89-0b27-75ca92a3290f.png)

想定される更新結果と同じになっていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/c22acbb8-6f81-509d-6550-29fc458523eb.png)

解説は以上になります！
最後まで読んでいただきありがとうございました！
もしよろしければ「いいね👍」お願いいたします！
Discord.pyを使ったDiscord botの作成方法

# Discord.pyを使ったDiscord botの作成方法

## はじめに
この記事では、Pythonライブラリであるdiscord.pyを使って簡単なDiscord botを作成する方法を紹介します。

## 必要な環境
- Python 3.6以降
- discord.pyライブラリ

## 手順

### 1. ライブラリのインストール
まずは、discord.pyライブラリをインストールしましょう。ターミナルやコマンドプロンプトで以下のコマンドを実行してください。

```bash
pip install discord.py
```

### 2. botアカウントの作成
Discordの開発者センターにアクセスし、アプリケーションを作成します。アプリケーションのページから「Bot」タブを選択し、「Add Bot」ボタンをクリックしてbotアカウントを作成します。

### 3. botトークンの取得
作成したbotアカウントのページで、トークンをコピーします。このトークンは後ほどコード内で使用します。

### 4. コードの記述
以下のコードをPythonスクリプトファイル（例: bot.py）に記述します。トークンの部分は、先ほど取得したトークンに置き換えてください。

```python
import discord
from discord.ext import commands

# botのトークン
TOKEN = 'YOUR_BOT_TOKEN'

# botのインスタンスを作成
bot = commands.Bot(command_prefix='!')

@bot.event
async def on_ready():
    print(f'{bot.user}がログインしました。')

@bot.command()
async def hello(ctx):
    await ctx.send('こんにちは！')

# botの起動
bot.run(TOKEN)
```

### 5. botの実行
ターミナルやコマンドプロンプトで、作成したスクリプトファイルが保存されているディレクトリに移動し、以下のコマンドを実行してbotを起動します。

```bash
python bot.py
```

### 6. テスト
Discordサーバーにログインし、botが追加されているチャンネルで「!hello」と入力してみましょう。botが「こんにちは！」と返信することを確認してください。

## おわりに
この記事では、discord.pyを使って簡単なDiscord botを作成する方法を紹介しました。あなたのbotが多くの人に愛されるようになることを願っています。
【Mysql x Docker】エラー「MySQLdb._exceptions.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)")」の原因

# 概要

docker-composeでdockerコンテナを起動時、「たまに」以下のエラーが出る状態でした。
なぜこれが「たまに」だったのか、またどうすればでなるくなるかわかったので紹介します。

```
MySQLdb._exceptions.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)")
```

とか

```
sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (2002, "Can't connect to MySQL server on 'db' (115)")

(Background on this error at: https://sqlalche.me/e/14/e3q8)
```

# 原因
原因は、アプリサーバのサービスがMySQLサービスよりも先に起動してしまい、MySQLサーバーがまだ準備ができていないため。

Docker Composeはサービスを並行して起動するのですが、毎回このエラーが出るわけではないのは、MySQLサービスが先に起動してくれることもあるからなのでしょう。

`docker-compose.yaml`の以下の箇所を追加したら、エラーが出なくなりました。

```yaml
version: "3.8"

services:
  sample_server:
    build:
      context: ../../
      dockerfile: ./docker/Dockerfile
    volumes:
      - ../../web_app:/xxx/web_app
    image: sample_server
    container_name: sample_server
    hostname: sample-server
    privileged: true
    restart: always
    tty: true
    ports:
      - "80:80"
    networks:
      fixed_compose_network:
        aliases:
          - backend
    depends_on:　 # 追加
      mysql:　 # 追加
        condition: service_healthy　 # 追加

  mysql:
    image: mysql:8.0
    container_name: mysql-container
    restart: always
    volumes:
      - ./database/sql:/sql
    ports:
      - "3306:3306"
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    networks:
      fixed_compose_network:
        aliases:
          - db
    healthcheck: # 追加
        test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] # 追加
        interval: 10s # 追加
        timeout: 5s # 追加
        retries: 5 # 追加

networks:
  fixed_compose_network:
```

最初は`depends_on`オプションで`mysql`を指定したのですが、それだけではエラーが解決しませんでした。起動の順番は制御できるようですが、正常起動したかどうかまではみてくれない？ようです。

> depends_on expresses startup and shutdown dependencies between services.
引用元：https://docs.docker.com/compose/compose-file/05-services/#depends_on


そこで、`healthcheck`を組み合わせて、依存先のサービスがhealthy（=操作可能）になるまで待つように追加してみました。これで実行したところ、エラーが出ることは無くなりました。

### `healthcheck`とは
`healthcheck`キーは、サービスが正常に動作しているかどうかを定期的に確認するもの。

`test: ...`がヘルスチェックのテストコマンド。このコマンドが成功（終了コード0）を返すと、サービスは`healthy`と見なされます。
`interval: 10s`は、ヘルスチェックが10秒ごとに実行されますよ、という間隔。
`timeout: 5s`は、ヘルスチェックがタイムアウトするまでの時間。
`retries: 5`は、ヘルスチェックが連続して失敗するとサービスが`unhealthy`と見なされるまでの回数を定義します。

以前postgresでも似た事象があったのでご参考までに。

https://qiita.com/Ryo-0131/items/25d75106b2f5e082be37
ABC353をPythonで（A～D）

AtCoder Beginner Contest 353

https://atcoder.jp/contests/abc353

# A問題
順番に見ていく
```python:A
n = int(input())
h = list(map(int, input().split()))

for i, h_i in enumerate(h, 1):
    if h[0] < h_i:
        print(i)
        exit()

print(-1)
```

# B問題
シミュレーション
```python:B
n, k = map(int, input().split())
a = list(map(int, input().split()))

ans = 0
chair = k
for a_i in a:
    if a_i <= chair:
        chair -= a_i
    else:
        ans += 1
        chair = k - a_i

print(ans + (chair < k))
```

# C問題
順番に見て行って、その数と足すと$10 ^ 8$以上になるものの数を数えてその分%10^8$を引く
```python:C
from sortedcontainers import SortedList

n = int(input())
a = list(map(int, input().split()))
mod = 10 ** 8

ans = 0
S = SortedList()
for i, a_i in enumerate(a, 1):
    t = S.bisect_left(mod - a_i)
    ans += a_i * (n - 1) - mod * (i - 1 - t)
    S.add(a_i)

print(ans)
```

# D問題
後ろから見て行って
1. 等倍で足すのはそれより後に出てくる数の個数
1. その数より前に$j$桁の数が$d_j$個あったとき、$a_i \times 10 ^ j \times d_j$答えに加算される
```python:D
n = int(input())
a = list(input().split())
mod = 998244353

d = [0] * 20
ans = 0
for i, a_i in enumerate(reversed(a)):
    ans += int(a_i) * (n - 1 - i) % mod
    for j, d_j in enumerate(d):
        ans += int(a_i) * 10 ** j * d_j % mod
    ans %= mod
    # print(ans)
    d[len(a_i)] += 1

print(ans)
```
tmuxでターミナル上に時計表示してみようぜ

tmux上で時計を表示できます!!

```shell
# tmuxを起動
tmux

# 時計を表示する
ctrl + b -> t
```

表示できた
![スクリーンショット 2024-05-11 22.49.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1212014/80714e9e-101a-2a98-0a01-f40e0a614f3b.png)
Git-4 ブランチについて

# 前提知識
gitでは、gitリポジトリにコミットを積み上げることで、プロジェクトの各時点での状態及びその変更の軌跡を辿ったり、任意の時点の状態を復元することができる。

コミット同士の前後関係は、コミット自体が「直前のコミット（親コミットと言う）は何か」という情報を持っているため、親コミットを辿っていくことにより知ることができる。

![c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985939/2d14f643-b0a3-9245-bc22-f35d66ae66b7.png)


# ブランチ
## 概要
ブランチとは、特定のコミットへの参照を保持するポインタのような領域である。

このように説明すると「ブランチとは枝分かれするための機能である」というイメージと乖離しているかもしれないが、結果的にはこの「特定のコミットへの参照を保持するポインタ」がコミットの軌跡を枝分かれさせることを可能にしている。

![d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985939/f36f140f-faca-b10a-aafa-66e9fb811693.png)

## 説明
では、ブランチとはどのような役割を果たす機能なのか、改めて説明していく。

### デフォルトブランチ
git initを実行して空のgitリポジトリを作成した時、まだコミットもブランチもない状態である。

最初のコミットを実行した時、同時にブランチが1つ作成される。
これが**デフォルトブランチ**である。

デフォルトブランチは、通常masterやmainという名前が付けられる。
※デフォルトブランチの名称は`git config`による設定で変更可能である。

この時、デフォルトブランチは最初に作成したコミットへの参照を保持している。
その後、新しいコミットを作成する度に、デフォルトブランチの参照先は自動的に新しいコミットに切り替わっていく。

### 新しいブランチの作成
ここから下記の`git branch`コマンドでgitリポジトリに新しいブランチを作成することができる。
```
git branch topic_1
```
このコマンドでは、topic_1という名前で現在のブランチ（デフォルトブランチ）と同じコミットを参照するブランチが作成される。

この時点ではデフォルトブランチとtopic_1は同じコミットを指しているが、この後、"**現在のブランチの切り替え**"を行うことによって、コミット履歴を枝分かれさせることができる。

### 現在のブランチの切り替え
gitリポジトリには、「今どのブランチで作業しているか」という情報を保持する領域がある。
それは"**HEAD**"と呼ばれており、こちらもポインタのような領域で、今作業しているブランチへの参照を保持している。
"現在のブランチの切り替え"とは、HEADが参照しているブランチを変更することを意味している。

現在のコミット、ブランチ、HEADの状態の確認。
```
git log --oneline --decorate
```

下記の`git checkout`コマンドで現在のブランチをtopic_1に切り替えることができる。
```
git checkout topic_1
```
これにより、HEAD領域はtopic_1を指した状態となる。この状態でコミットを実行すると、topic_1が参照するコミットが新規コミットへと更新されていく。

### 本流とは別のコミット履歴の積み上げ
ここから、topic_1が参照するコミットを起点として新しいコミットを実行していくことで、本流とは異なるコミット履歴を積み上げていくことができる。

例えば、現在のブランチがtopic_1の状態で3回コミットを実行したとしよう。
この時、全体のコミット履歴の中で、topic_1ブランチは最新のコミットを、デフォルトブランチはその3回前のコミットを参照している状態である。（コミットは親コミットを参照することでコミットの歴史を作り上げていくことを思い出そう。）

ここで、現在のブランチをデフォルトブランチに切り替える。この時、HEAD領域の参照先はtopic_1からデフォルトブランチに切り替わり、ワーキングディレクトリもデフォルトブランチが参照するコミットの状態に復元される。

すると、デフォルトブランチが今参照しているコミットから、topic_1ブランチとは別の流れ（デフォルトなので立ち位置的には本流）のコミット履歴を積み上げていくことができる。

これで、デフォルトブランチとtopic_1ブランチは最初は同じコミットを参照していたが、そこから別々にコミットを積み上げていくことにより、ある時点からコミット履歴を枝分かれさせるという状態を実現することができた。

ここまで述べたのブランチ機能の要点を下記にまとめておく。
- gitリポジトリでは、コミットが親コミットを参照していることにより、1本のコミット履歴を作ることができる。
- ブランチとは特定のコミットへの参照を保持する領域である。
- HEAD領域が参照するブランチを変更することで、現在作業しているブランチを切り替えることができる。
- 現在のブランチを切り替えると、ワーキングディレクトリにブランチが参照するコミット時点のスナップショットが復元される。
- 現在のブランチが参照するコミットから新規コミットを実行し、独自にコミット履歴を積み上げていくことができる。この時、他のブランチが参照するコミットは変わらない。
- 他のブランチに切り替えた時、既に作成したコミット履歴とは別の流れのコミット履歴を積み上げていくことができる。結果、gitリポジトリ内のコミット履歴を複数本に枝分かれさせることができる。
docker-compose.ymlでのMYSQL_ROOT_PASSWORDの設定困る。

# 前提
今勉強で作っている環境でMySQLを使うのですが、docker-compose.ymlにMySQLの情報を記載して、勉強の時に簡単に同じ環境を作れるようにしたいと考えました。

今の環境は
docker-compose : Docker Compose version v2.24.6-desktop.1
mysqlイメージ : original_mysql_world

# 困った点
さて、docker-compose.ymlでDBの設定を書き込む場合には、MYSQL_ROOT_PASSWORDで設定してあげる必要があります。
MYSQL_ROOT_PASSWORDは必須の変数で、これを省くとDockerの起動時に
```
Database is uninitialized and password option is not specified
You need to specify one of the following as an environment variable:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
```

というエラーがでて、つまり設定忘れないでねと言われます。
<br>
ここで困るのが、たとえばMYSQL_ROOT_PASSWORD="password"で設定すると、「いくら勉強でもgithubにこのままあげるたら人に見られた時にアホの子だと思われそう。。」
ということ。

「docker-compose upで動くことが確認できたら後で設定すればいい話なのかもしれないな。。」とは思いつつ、デファクトスタンダードはどれなんだかわからないので平文でパスワード載せないように工夫をしたいと思いました。

# 解決策
### 1. MYSQL_ALLOW_EMPTY_PASSWORDを使う

この変数を記述してyesを設定すると、rootユーザのパスワードが空で起動できます。
ただ普通にセキュリティ的にだめすぎるので、よくないですね。
一応無事起動するのを確認。


### 2. MYSQL_RANDOM_ROOT_PASSWORDとMYSQL_ONETIME_PASSWORDを使う
MySQLのリファレンスに書いてあった推奨の方法です。

```docker
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_ONETIME_PASSWORD: "true"
```
のように設定して使います。

dockerのビルドの時にログに下のような表示でパスワードが記載されるので、これを使ってログインが可能です。
```
 GENERATED ROOT PASSWORD: ~~~~~~~~~
```
こんな感じで無事入れます。
![スクリーンショット 2024-05-11 21.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775726/9ddc505f-f624-87f6-26e2-dfffb47e0101.png)

これ一回入ったらもうこのパスワードが使えなくなるって意味だと思って設定してみたけど全然そんなことない。
どういう使い方なんだろうか。。

ちなみにこれらのブール変数は長さが0以外の文字列だとtrueを設定しているのと等価です。

### 3.外部ファイルに記述する
今までは
```
mysql:
    build: 
      context: ./db_Mysql
      dockerfile: docker/db/Dockerfile
    volumes:
      - ./db_Mysql/db:/db
    image: original_mysql_world
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "yes"
      MYSQL_ONETIME_PASSWORD: "true"
```
という感じでenvironmentの中に変数を記載してましたが、環境ファイルを作って参照してもらう場合には、env_fileで指定してあげます。
```docker
mysql:
    build: 
      context: ./db_Mysql
      dockerfile: docker/db/Dockerfile
    volumes:
      - ./db_Mysql/db:/db
    image: original_mysql_world
    env_file: env/db_env
```

これも予定通り無事起動、db_envに記載してるパスワードでmysqlに入れました。


# 結論
環境変数を別ファイルで設定して、.gitignoreつければよい。と思う。

# 参考文献

- [DockerでMySQLサーバーを構築するときの環境変数の設定](https://www.lifewithpython.com/2021/05/python-docker-env-vars.html)


- [2.5.6.2 Docker での MySQL Server のデプロイに関するその他のトピック
](https://docs.python.org/3/using/cmdline.html#cmdoption-u) 

パスワードはこれでも確認できるらしい。自分は普通にdocker desktopから履歴を見たけれど。
- [MySQLのデフォルトパスワードを確認する
](https://qiita.com/chii-08/items/a0d41f4bb94309876763)
PythonでPC用通知システムを作る

# PC用通知システム
notify-pyライブラリを使うことでPC用の通知システムが簡単に作れます。

pip install notify-py

でライブラリをインストールできる

## テストコード(Linux用)
```python:ntf
#!/usr/bin/python3

from notifypy import Notify

# 通知オブジェクトを作る
n=Notify()
# 何も操作しなければ通知エリアにメッセージが残るように設定
n.urgency="normal"
# メッセージタイトル
n.title="テスト通知"
# メッセージ
n.message="メッセージテスト"
# 通知送信
n.send()
# この他にも、アイコンや音 等も設定できる。

```
このファイルに実行権をつけてください。

## 応用
外部データベースやAPIと連携することで、独自通知システムが可能になる。
TypeScript kyselyでSQLの生のログがほしい

knexからkyselyへの移行中。
knexはtoStringでSQLが取得できたけれど、kyselyではどうすれば良いのか。

一応、マニュアルには以下の通り書いてある。

[Compile a query](https://kysely.dev/docs/recipes/splitting-query-building-and-execution#compile-a-query)

```ts
const compiledQuery = db
  .selectFrom('person')
  .select('first_name')
  .where('id', '=', id)
  .compile()

console.log(compiledQuery) // { sql: 'select "first_name" from "person" where "id" = $1', parameters: [1], query: { ... } }
```

compileしたqueryを実行することもできる。

```ts
const compiledQuery = db
  .selectFrom('person')
  .select('first_name')
  .where('id', '=', id)
  .compile()

const results = await db.executeQuery(compiledQuery)
```

こうすることで、まずcompileしたSQLをlog用のDBにinsertしておいて、そのあとに実行するということができるようになる。

ところが、`.compile()`はプレースホルダーがMySQLなら`?`,postgresであれば`$`として表示される。実際にinsertやupdateした値をそのままログに残したい場合もあるだろう。そういうときは以下のような関数をつくって、?をparametersと入れ替えてあげればよい。

```ts
export const toRawSql = (
	sql: string,
	parameters: readonly unknown[],
): string => {
	let sqlWithValues = sql;
	parameters.forEach((param) => {
		sqlWithValues = sqlWithValues.replace("?", param as any);
	});
	return sqlWithValues;
};
```

何も考えずに書いたヘルパ関数。
reduceとか使うならこんな感じか

```ts
export const toRawSql = (
  sql: string,
  parameters: readonly unknown[],
): string => {
  return parameters.reduce((currentSql, param) => {
    return currentSql.replace("?", param as any);
  }, sql);
};
```

reduceのほうはテスト書いてないから自信ないけどたぶん動くはず。

knexは最近アップデートが滞っている。Databaseを切り替えるような運用だとパスワードが消えるという本当にどうしようもないバグがずっと残ったままで、issueで何回かアップデートをお願いしたがどうもダメっぽいので本格的にkyselyへ移行しようと考えている。

kyselyはいまだにver0台だが、productionで使用している企業もあるようなので、もうちょっと社内ツールなどでテストしてから本番環境でも使っていきたい所存。sqlcは昨日まで頑張っていたがいろいろ困りどころがあって折れました。