OmniAICreator/Qiita-1.07M huggingface dataset:
LANの標準規格　37、38

### LANの標準化 IEEE 802　委員会
LANは、IEEE 802委員会という組織により、標準化を行っている。
IEEE（Institute　of Elcetrical and Electronics Engineers）
米国の電気電子学会の中で、IEEE802委員会があり、その中でも幾つかのワーキンググループに分かれ

IEEE802.3　メディアアクセス制御にCSMA/CDのLAN⇒イーサネット
IEEE802.4　トークンパス
IEEE802.5　トークンリング
IEEE802.11　無線LAN
IEEE802.15　無線PAN

IEEE802.3はEthernetを基本に規格化した、メディアアクセス制御CSMA/CDを使うLANの規格である。
IEEE802.11はメディアアクセス制御にCSMA/CA方式を使う無線LANの規格である。

### LANのデータ伝送の仕組み
#### データに相手の住所を付加して送る
LANで最も用いられるのがEthernet（イーサネット）で、郵便のように、通信相手に送るデータに、ノードの住所（宛先アドレス）と自分の住所（送信元アドレス）を付加して送信する。
　宛先アドレス+送信元アドレス+データ　　はデータ単位　フレームという。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/5cde6e1e-eb87-fc86-e74c-7ec26f5588cc.png)
#### MACアドレス（LAN上でのノードの住所）
LANに接続してデータのやり取りを行う際、ネットワーク機能をもったNIC（network　interace　Card）というハードウェアが必要。
このNICにMACアドレス（media　access　control　address）という番号が埋め込まれており、このMACアドレスがノードのアドレスになる。
　このMacアドレスは、NIC一枚一枚に割り当てられた48ビットの製品固有番号。先頭の24ビットのOUIは各メーカーに割り当てられた番号で、後続の24ビットの固有製造番号（製品に割り当てた番号）から構成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293109/640626a4-a53d-bb59-c017-65786b12c915.png)

イーサネットLANでは、データの宛先を特定するため　Macアドレス　が用いられる。
Macアドレス、NICに割り当てられた48ビットの製品固有番号である。24ビットのOUIと24ビットの固有製品番号から構成する。
TCP/IPを使用したLANでは、IPアドレスといった論理アドレスも使用する。
S3へのアップロードをLambdaで検知してslackに通知する

## 概要
業務フローの最適化を目指してS3へのアップロードを検知してslackに知らせるシステムを構築してみようと思います。イメージはこんな感じ。
![名称未設定ファイル.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/7cf271d3-8eb4-5ae4-6336-80415f7d2e20.png)

## 前提条件
- Awsアカウントを作成済みであること（自由に触れる）
- S3のバケットが用意してあること
- slackアカウントを持っていること

## Lambda環境の用意
こちらにまとめてあるので割愛

https://qiita.com/nero-15/items/7a4b6e1b9a273c68159b

## トリガーを設定する
これは編集画面ですが、新規作成もほぼ一緒です。s3のバケットの特定のディレクトリにアップロードされた際にLambdaが動くように設定
![スクリーンショット 2023-08-18 0.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/8aaad2e6-3d46-e38d-a4b7-f133f47bd863.png)
コードをちょいと調整
```javascript
module.exports.handler = async (event) => {
  console.log(event['Records'][0]['s3']['bucket']['name']);
  console.log(event['Records'][0]['s3']['object']['key']);
  
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'success!!',
        input: event,
      },
      null,
      2
    ),
  };
};
```
画像をアップロードしてCloudWatchを確認
![スクリーンショット 2023-08-18 0.52.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/6dd8560e-f2b9-eaef-fdbc-acc906f0692c.png)
いけてるね！

## slackに通知を送る
slackアプリの作成はこちらにまとめてあるので割愛

https://qiita.com/nero-15/items/a9c2b99e057ae6988df6

Lambda全体のコードはこんな感じ
```javascript
const https = require('https');

module.exports.handler = async (event) => {
  const bucket = event['Records'][0]['s3']['bucket']['name'];
  const key = event['Records'][0]['s3']['object']['key'];
  const request = https.request('https://slack.com/api/chat.postMessage', {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer {アクセストークン}"
    },
  });
  request.write(JSON.stringify({
    channel: "#{チャンネル名}",
    text: (bucket + '/' + key + 'ファイルがアップロードされました'),
  }));
  request.end();

  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'success!!',
        input: event,
      },
      null,
      2
    ),
  };
};
```
結果
![スクリーンショット 2023-08-18 2.43.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/7db60b60-0ee3-a900-9613-b8d2cb50a23a.png)

:::note warn
警告
本番環境にdeployしたところ意図した動作にならないバグが発生中。作業時間が取れたら確認しようと思います。非同期処理が怪しいとは思う...
:::

## まとめ
S3へのアップロードを検知してslackに知らせるシステムを簡単に実装することができました！

## 今後の展望
弊社の動画配信で使用しているブライトコーブクラウドには動画アップロード用のAPIが存在する

https://ja.apis.support.brightcove.com/dynamic-ingest/getting-started/source-file-upload-api-dynamic-ingest.html

今回のシステムをベースに自動アップロードシステムを構築すれば現状で人が介入している業務フローが改善するのではないか？
![名称未設定ファイル.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/aa95be52-1dc4-052f-7fc3-e4dbd978a20a.png)
業務フローを全てシステム化して動画コンテンツの準備が整い次第、最速で配信をユーザに届けたい！！

## 最後に運動通信社について
運動通信社は「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、一緒に働く仲間を募集しています！
PMやアプリエンジニア、Webエンジニアなど色んな職種を募集しておりカジュアル面談大歓迎なので是非採用フォームよりご連絡ください！
ぜひ一緒に、自分たちも世の中もワクワクするサービスを作りましょう！

https://sportsbull.jp/about/#recruit

Greenも活用中です

https://www.green-japan.com/company/9598
AWS Certified Cloud Practitioner 試験を受けました！

初めまして
私は来月くらいには日本のIT会社に入社する韓国人です。
あ！私の日本語、まだJLPT　N2　レベルだからおかしい部分を発見しても許してくださいっ！:relaxed:

実は今月、会社で要求するAWSのテスト！
AWS Certified Cloud Practitioner試験　合格しました
（一番簡単な試験なんですけどね(笑)）

・　試験難易度
・　試験にどんな問題が出るのか
・　勉強方法

簡単に紹介します。
（Googleでもこの試験に関する情報があまりないので、試験を準備してる方に少しでも力になれると思うので作成します）


![스크린샷 2023-08-18 002732.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532853/ab9c81da-b4ca-5b15-b965-24ea2698b911.png)
（韓国で受けたので韓国語です(笑)）


私、非専攻者・Cloud経験がないので心配したんですけど
あまり心配しなくても大丈夫ですよ。
十分に合格できる試験です。



----------------------------------------------
【試験難易度】
--------------------------------------------

ー　確かにCloudの経験とかAWS　Cloud　サービスを利用したことがない方には
　　ちょっと勉強しべきな試験です

ー　そんなに難しいとは思いません


【試験にどんな問題が出るのか】
--------------------------------------------

ー　概念をちゃんと覚えてるかどうかの問題ですね
    例）ミリ秒で処理できるし非関係データベースは？
    １）DynamoDB
    ２）RDS
    ３）S3 Glacier
    ４）Global Accelerator
    
    正解）１．DynamoDB


ー　こんな感じです
    　　問題によって答えを1つ選ぶ問題もあるし、二つ選ぶのもあります

ー　似てる問題も出るから、もしよく分からないのがあれば１～３個
　　✖間違えるかもしれません。



【勉強方法】
----------------------------------------------
ー　AWSで提供する動画を見て基本的な流れを覚える
    　（これだけで合格するのは無理だと思いますけど基本的なのは勉強出来ます。）

ー　AWS　ホワイトペーパーをもとに勉強
      　 （これ一番大切です！！！！！）
    　・　カテゴリに分流して勉強するのがいいと思います。
    　・　例えば、ストレージサービスに何があるか、何が違うのかを覚えてください。

ー　https://www.examtopics.com/exams/amazon/aws-certified-cloud-practitioner/
　・　リンクで問題を解いてみるのはマジで大切！
   　・　正解がおかしい部分がたくさんあるので他の人達が選んだ答えを見てください。
    　・　私の場合はここで3~5個くらいは同じ問題が出ました。

ー　YouTubeとか他の教育サイトの動画を見て復習

--------------------------------------------

まーこんな感じですね

皆様もできるし、私より高い点数に合格するのももちろん出来ます！

応援します！！！！！

ここまで読んでくれてあざっす！:bow:

速く日本に行きたい！！！！！！！！！！！！！
slackチャンネルへシステムから通知を送る

## 概要
slackチャンネルに対してシステムから通知を送るコードを実装します

## slackアプリ画面にて設定
通知を実装するにあたってslackアプリを作る必要があります

https://api.slack.com/apps

### 1.Create New App
Create New Appからアプリ作成画面を開き、必要項目を入力
![スクリーンショット 2023-06-21 21.42.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/bd6f2a4a-bb45-0ded-e601-6c8808182cff.png)

### 2.アプリ情報を編集
サイドバーの「Basic Information」から遷移。Display Informationセクションにて編集しましょう
![スクリーンショット 2023-06-21 22.08.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/eb7771fc-9341-2135-c564-e547692c3c49.png)

### 3.権限設定
サイドバーの「OAuth & Permissions」から遷移。Scopesセクションにて書き込み権限を指定する。
![スクリーンショット 2023-06-21 21.50.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/ab066520-dc15-a3e7-fc68-021e19c7128a.png)

### 4.ワークスペースにインストール
サイドバーの「Basic Information」から遷移。Building Apps for SlackセクションのInstall your appからワークスペースへ紐付けましょう

![スクリーンショット 2023-06-21 22.09.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/2c30b7d7-6f2f-b85b-735d-841baa04c4bc.png)

### 5.slackチャンネルのインテグレーションに追加
![スクリーンショット 2023-08-18 1.12.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/6797ed4e-8cc8-e5b2-5bc5-e61dbdf0fe1f.png)

### 6.認証トークンを取得
サイドバーの「OAuth & Permissions」から遷移。OAuth Tokens for Your Workspaceセクションにて認証トークンをコピーしておきましょう
![スクリーンショット 2023-06-21 22.12.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/8ae2a827-0b08-6f00-dcab-3ab34c0a9396.png)

これで準備は完了！

## 通知するコードを実装
Node.jsで書くとこんな感じ
```javascript
const https = require('https');
const request = https.request('https://slack.com/api/chat.postMessage', {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer {アクセストークン}"
    },
});
request.write(JSON.stringify({
    channel: "#{チャンネル名}",
    text: "test",
}));
request.end();
```
結果
![スクリーンショット 2023-08-18 2.01.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/212fee46-4390-d13a-a1c4-c35cb8a48a6d.png)

## まとめ
システムからslackに通知することができましたね！

## 最後に運動通信社について
運動通信社は「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、一緒に働く仲間を募集しています！
PMやアプリエンジニア、Webエンジニアなど色んな職種を募集しておりカジュアル面談大歓迎なので是非採用フォームよりご連絡ください！
ぜひ一緒に、自分たちも世の中もワクワクするサービスを作りましょう！

https://sportsbull.jp/about/#recruit

Greenも活用中です

https://www.green-japan.com/company/9598
GitHub Pagesを使用したWebページの公開

# 1.はじめに
フロントエンドのみで構成されたアプリケーションを公開する際にGitHub Pagesを使用したので一連の流れを記録します。

# 2.事前準備
GitHub登録済み

# 3.手順
### 1.リポジトリを作成する

GitHubの`Repositories`の右上のあるNewをクリックします

Repository nameの部分に作成するアプリ名を入力します

今回はwebページを公開するため、Publicを選択し右下の`CreateRepository`をクリックしてください
これでリポジトリが作成できました
![スクリーンショット 2023-08-18 0.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2904183/dfe093b0-8c54-071d-67f2-cc2ac4984590.png)
作成後の画面のURLは後ほど使用するので保存しておきましょう
![スクリーンショット 2023-08-18 0.53.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2904183/9b81e870-d2ed-8f60-1475-b5d74aa35af5.png)

### 2.公開したいファイルをリポジトリ内にアップロードする
まず、アップロードしたいファイルのディレクトリへ移動して、以下コマンドでローカルリポジトリを作成します
```
$ git init
```
その後ステージング
```
$ git add -A
```
コミットして
```
$ git commit -m "コミット名"
```
mainブランチを作成します
```
$ git branch -M main
```
そして先程表示されていたURLを使用してローカルとリモートを紐付けます
```
$ git remote add origin 先程表示されていたURL
```
最後に以下コマンドでリモートリポジトリにpushします
```
$ git push -u origin main
```
ここまでできたら、GitHubでファイルが追加できていることを確認してみてください

### 3.GitHub Pagesの公開
リポジトリの画面の右上`setting`をクリックして`Pagesをクリック`します
![スクリーンショット 2023-08-18 1.21.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2904183/48aa8850-50cb-0b93-8c68-4b7e3807dd5c.png)
![スクリーンショット 2023-08-18 1.21.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2904183/5dd11ba4-a8e6-c591-7bb2-521daa81467e.png)

Branch部分を先程作成したmainブランチに変更後`save`をクリックします
![スクリーンショット 2023-08-18 1.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2904183/3ef4b0af-d558-7636-5306-7d38140ca867.png)

Visit siteと表示される(時間がかかります)ので、クリックするとwebページを確認できます
![スクリーンショット 2023-08-18 1.21.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2904183/7347d4e1-9974-0a10-08f9-4e3f6509a503.png)

Webページを開いた際に画像が出ないことがありますがしばらくすれば表示されます。

これで、GitHub Pagesを使用したwebページを公開できました
PHP超簡単スクレイピングでプロ野球の試合結果を取得する

Web開発修行中のやきうオタクです。
NPB公式戦のスコアや勝敗を自動取得する方法を探しているのですが、それっぽい手頃なAPIが見つかりませんでした。

[NPB公式サイト](https://npb.jp/)の日次試合結果が掲載されているページが
・日程別にページURLが規則的であること
・チーム名、スコア部分のhtml書式が規則的であること
・年度問わず掲載コンテンツのレイアウトが統一されていること
から、スクレイピング的な処理でも簡単に任意日程のスコアを取得できそうだったので試してみました。

スクレイピングといってもPHPでページコンテンツの簡易的な解析を行うのみで、特にライブラリなどは使用していません。

## サンプルコード
```test.php
<?php

// 対象チームと試合日の指定
$targetTeam = 'オリックス';
$date = new DateTime('2023-08-05');
$dateStr = $date->format('Ymd');

// 試合結果ページのURL生成
$url = 'https://npb.jp/bis/' . $date->format('Y') . '/games/gm' . $dateStr . '.html';

// ページのコンテンツを文字列で取得
$html = file_get_contents($url);

// 試合結果の情報テキスト部分を分割
$scoreTexts = explode('<td class="contentsTeam">', $html);

// テキストを試合ごとに配列に分割
$elements = [];
foreach($scoreTexts as $text) {
    $elements[] = explode('</td>', $text);
}

// 配列の各テキストから要素を抽出
$output = [];
for($i=1; $i<=12; $i++) {
    $output[$i] = [
        $elements[$i][0], // ホームチーム名
        $elements[$i+1][0], // ビジターチーム名
        $elements[$i][1], // ホームチーム得点
        $elements[$i][3], // ビジターチーム得点
    ];
    // スコア部分のタグを除去
    $output[$i][2] = str_replace('<td class="contentsRuns">', '', $output[$i][2]);
    $output[$i][3] = str_replace('<td class="contentsRuns">', '', $output[$i][3]);

    $i += 1; // 偶数番目は必要情報を持たないためスキップ
}

// 抽出結果を出力
print $date->format('Y年n月j日') . 'の' . $targetTeam . 'の試合結果は、';
foreach($output as $item) {
    if ($item[0] == $targetTeam || $item[1] == $targetTeam) {
        print ($item[0] . ' ' . $item[2] . '-' . $item[3] . ' ' . $item[1] . "\n");
    }
}
```

##  出力結果
こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1974587/e0afdbca-a645-066f-4cdb-d0aedadb918c.png)

## 調査過程と処理について
ざっくりとだけ書きますとただの泥臭い作業です←

まず `file_get_contents` でHTMLテキストを取得し、欲しい球団名とスコアの部分の構造を解析しながら抽出・加工 → テキスト出力 を期待する文字列結果になるまで繰り返します。

1. 抽出ターゲットとなる箇所を囲っているタグを見つける
1. 対象の開始タグ・閉じタグ部分で `explode` 関数を使ってテキストを切り取る
1. 配列に入れて出力してみる
1. 球団名、スコアを値として持つ要素番号を見つける
1. 不要タグなどを除去しながら出力する



## 課題と応用
スクレイピング共通の課題ですが、NPB公式ページを勝手に解析しているだけなので、サイト側の書式やレイアウト、URLの構造などが変わると一発で詰みます。

応用パターンとしては、コード上にベタ書きしている対象球団・日程を変数として任意の入力値で計算させれば、贔屓球団の特定日程のスコアと勝敗を取得できるので、「自分が観に行った日の推しチームの通算成績」などが算出できるようになると思います。
※ゆくゆく自分用の観戦備忘録として活用したいなと考えています。

NPBさん、個人開発者にも手を出せるいい感じの速報APIの提供をぜひともお願いします！←
【Llama2】1トークンずつ推論結果を表示してChatGPT風に見て楽しむ

# 実装

HuggingFaceのLLM推論モジュールにLangChainなどを連携させてトークンずつデータを流すStream機能がありますが、**今回はこの機能を使わず自力でナイーブな実装をしてみました**。

特に効率が良いわけでもなく、**あえて1トークンずつ推論＆表示させるプログラムにすることで、ChatGPT、GPT-4のようにリアルタイムに出力結果が表示されておもしろい、ただそれだけのプログラムです。**

今回はLlama2で実行しましたが、その他HuggingFaceに対応したLLMであればあまり修正せずに動くと思います。

https://github.com/keisuke-okb/llm-tokenwise-inference

※推論結果をその都度強制的にprintするため、バッファの効率や推論速度は無視です

```python
class TokenWiseLLM:
    def __init__(self, model_name, use_bitsandbyts=False):
        self.model_name = model_name
        
...＜中略＞...

    def inference(self, prompt, max_length=1000):
        prompt = f"### Question: {prompt}\n### Answer: "
        print(prompt, end="")
        step = 0
        while step < max_length:
            inputs = self.tokenizer(
                prompt,
                return_token_type_ids=False,
                return_tensors="pt",
            ).to("cuda:0")

            with torch.no_grad():
                sequences = self.model.generate(
                    **inputs,
                    do_sample=True,
                    top_k=10,
                    num_return_sequences=1,
                    max_length=len(inputs['input_ids'][0]) + 1,
                    eos_token_id=self.tokenizer.eos_token_id,
                    pad_token_id=self.tokenizer.pad_token_id,
                )
            output = self.tokenizer.decode(sequences[0], skip_special_tokens=True)
            print(output[len(prompt):], end="", flush=True)
            if sequences[0][-1] == self.tokenizer.eos_token_id:
                break
            prompt = output
            step += 1
        
        print("")
        return


```




# 実行の様子

![tokenwisellm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1373557/2ded7754-24ac-8045-881c-05ab2f1bf365.gif)

リアルタイムで生成されてるされてる～～！！と感じることができる、それだけです。
【数学】三角関数の勉強メモ 〜加法定理の視覚的な理解〜


このような角度 α と角度 β を考える

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421285/88cb1f0d-d9b3-9c98-2a43-9f9985c3ed94.jpeg" width="50%">

このとき、このような３つの直角三角形が出現することがわかる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421285/3f4c7089-13ff-ff14-8dba-ee98fbf191ff.jpeg" width="50%">

直角三角形の底辺と高さはそれぞれ
底辺は 斜辺 × cosθ
高さは 斜辺 × sinθ
で求めることができるので、この直角三角形の長さは以下のようになる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421285/237ce5f2-15a3-0412-7732-a8b88799e082.jpeg" width="50%">

この事から cos(α + β) は cos β cos α から sin β sin α を引く事で求まることがわかる。
同様に sin(α + β) も cosβsinα と sinβcosα を足す事で求められることがわかる。

```
cos(α + β) = cos β cos α - sin β sin α
sin(α + β) = cos β sin α + sin β cos α
```

cos(α - β), sin(α - β) はこの角度βの直角三角形を反転させることで以下のように求められる

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421285/65685156-3310-63fe-eeaf-8471853dd27e.jpeg" width="50%">

cos β cos α と sin β sin α を足す事で cos(α - β) が、
sin β cos α から cos β sin α を引く事で sin(α - β) が
それぞれ求めることができた。

```
cos(α - β) = cos β cos α + sin β sin α
sin(α - β) = sin β cos α - cos β sin α
```

ついでにこの図から正弦定理を求めることもできる。
角度βの三角形を二つ作ったことで弧が出来上がった。
この弧からの中心角度は２βであり、円周角の定理からこの弧から作られる角度は中心角の半分、つまり角度βになる。
そして中心を通るように直線を引き、直角三角形を作るとこんな感じになる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421285/960f0d3b-3454-c32e-0563-b350bed870b3.jpeg" width="50%">

角度βに向かい合う辺の長さは２ sin βなので、 $\frac{2 sin β}{sin β} = 2R$ となる
Quest2でPassThroughするための手順

Quest2で単純なPassThroughを実行するための手順です。
手順を実施するのがめんどくさい人は[こちら](https://github.com/machidyo/quest-passthrough)からgit cloneしてもらえればすぐ試せます。

# 前提
- Windows 11
- Unity 2022.3.5f1
- Oculus Integration v55
- Meta Quest 2 v54.0.0.155….(略)

# 手順
1. Unityプロジェクトを新規作成
2. [Oculus Integration](https://assetstore.unity.com/packages/tools/integration/oculus-integration-82022)をインストール
3. Build SettingsでAndroidにSwitch Platformします
4. Project Settingの変更
    1. Player/Other Settingsを3ヵ所設定
        1. Rendering/Color SpaceをLinearに設定
            ![2023-08-17_23h13_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/ae315d37-bc82-c3f5-45c6-aa0acc21f5ca.png)
        2. Configration/Scripting BackendをIL2CPPに設定
        3. Configration/Target ArchitecturesをARM64のみにチェック
            ![2023-08-17_23h13_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/c5931548-a982-abeb-e8ec-f413a4393685.png)
    2. XR Plugin-in Management
        1. Install XR Plugin Managmentボタンを押します
        2. Oculusにチェック
            ![2023-08-17_23h18_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/9573b86a-7375-7c42-4693-cabc3d370f28.png)
5. Window → Rendering → Lighting を開いて、Enviromentを選択し、Skybox MaterialとSunSourceに設定されている設定を削除（選択してdelキーを押します）
    ![2023-08-17_23h22_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/a9dab146-a76f-e590-b4ea-a948cdafca82.png)
6. OVRCameraRig
    1. Oculus/VR/Prefabs/OVRCameraRigをHierarchyに追加
    2. Tracking/Tracing Origin TypeにStageを設定
        ![2023-08-17_23h26_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/cea96fc3-3657-f91f-1128-6d65e0974d77.png)
    3. Quest Features/General/PassThrough SupportをSupportedに設定してから、Enable PassThroughにチェック
        ![2023-08-17_23h29_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/027cfc20-1593-5b22-2a7e-d990aeec809e.png)       
    4.  OVRPassThroughLayerをアタッチして、PlacementをUnderlay、Composition Depthを1に設定
        ![2023-08-17_23h30_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/cb088163-f40d-6864-9f7d-8d1a848d3665.png)
7. CenterEyeAnchorの設定
    ![スクリーンショット 2023-08-17 233523.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/c2963634-f96e-32e4-5e90-0ce73bf4574a.png)
8. OVRContollerPrefabの設定
    1. 左手用にOVRContollerPrefabを入れて、ControllerにL Touchを設定
        ![2023-08-17_23h38_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/50637025-f101-292f-f304-b59a882d26a7.png)
    2. 右手用にOVRContollerPrefabを入れて、ControllerにR Touchを設定
        ![2023-08-17_23h38_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/ad4a73d6-21d4-b1f5-063b-d4671e393b22.png)        
9. 実行
    1. Oculus QuestとPCをつなぎます
    2. Build Settingsを開きます
    3. Add Open Scenes（1回目のみ）
    4. Build And Run
        1. 1回目のビルドは結構時間がかかりますが、2回目からは早くなります
React Routerで中ページ404エラーを解消！Apacheの.htaccess設定法


**目次**
1. 問題の背景
2. なぜこの問題が起きるのか？
3. 解決方法: Apacheの.htaccess設定
4. 設定の詳細解説
5. まとめ

---

#### 1. 問題の背景
React Routerを使用してシングルページアプリケーションを構築する際、中ページのURLに直接アクセスすると404エラーになる現象に直面することがよくあります。これに対処するためのApacheサーバーの設定方法をご紹介します。

---

#### 2. なぜこの問題が起きるのか？
React Routerはクライアントサイドでのルーティングを扱っているため、サーバーには実際のファイルやディレクトリが存在しないURLに対してリクエストが行われた場合、サーバーは404エラーを返してしまいます。

---

#### 3. 解決方法: Apacheの.htaccess設定
Apacheサーバーの `.htaccess` ファイルを用いて、この問題を解消します。

```apache

# React Routerのための設定
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
```

この設定により、ユーザーが中ページのURLに直接アクセスしても、`index.html` にリダイレクトされ、React Routerが適切にルーティングを行います。

---

#### 4. 設定の詳細解説
- `RewriteEngine On`: リライトエンジンを有効化。
- `RewriteBase /`: リライトのベースURLをルートに設定。
- `RewriteRule ^index\.html$ - [L]`: `index.html` への直接アクセスを許可。
- `RewriteCond %{REQUEST_FILENAME} !-f` および `RewriteCond %{REQUEST_FILENAME} !-d`: リクエストされたパスが実ファイルやディレクトリでない場合のみ、次のルールを適用。
- `RewriteRule . /index.html [L]`: 上記条件に一致する場合、すべてのリクエストを `index.html` にリダイレクト。

---

#### 5. まとめ
React Routerでのルーティング問題は、適切なサーバー設定を行うことで解消できます。Apacheを使用している場合、上記の `.htaccess` の設定を参考にして、ユーザー体験を向上させましょう。

いいねや共有は、他の開発者にもこの情報が届く大きな力となります。もし役に立ったら、ぜひともいいねや共有をお願いします！
Leetcode 542. 01 Matrix

https://leetcode.com/problems/01-matrix/description/

# アプローチ
- BFS

```java
class Solution {
    class Point {
        public Point(int x, int y, int level) {
            this.x = x;
            this.y = y;
            this.level = level;
        }

        int x;
        int y;
        int level;
    }


    public int[][] updateMatrix(int[][] mat) {
        int height = mat.length;
        int width = mat[0].length;
        int[] dx = {1, 0, -1, 0};
        int[] dy = {0, 1, 0, -1};

        Queue<Point> q = new LinkedList<>();

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (mat[i][j] == 0) {
                    // 0のところは、すべてQueueに入れる
                    q.add(new Point(i, j, 0));
                    continue;
                }
                    // 他は-1 でおいておく
                mat[i][j] = -1;
            }
        }

        while (!q.isEmpty()) {
            Point nowPoint = q.poll();
            for (int i = 0; i < 4; i++) {
                int newX = nowPoint.x + dx[i];
                int newY = nowPoint.y + dy[i];

                if (newX < 0 || height <= newX || newY < 0 || width <= newY || mat[newX][newY] != -1) {
                    // mat[newX][newY] != -1
                    // 上記の意味は、すでにQueueに入っているので、見なくていいという意味
/*
                                0 0 0
                                0 1 0
                                1 1 1
                                上記の場合、map[0][0]は自動的に横の要素が-1ではないので、捨てられる
                                1と近い要素から確認する
*/
                    continue;
                }

                q.add(new Point(newX, newY, nowPoint.level + 1));
                mat[newX][newY] = nowPoint.level + 1;

            }
        }

        return mat;
    }
}

```
.run_in_executorによる非同期処理はwait関数を無視して次のコード行へ移る

Seleniumを非同期で使い、ページ収集したかった。しかし、収集前に処理が終了してしまうため、困っていた。

原因は`.run_in_executor`であった。`.run_in_executor`は同期関数を非同期化できる関数である。
しかし、loop.run_until_completeと併用でコード完了までプログラムは実行できるかもしれないが、
loop.run_until_completeの次の行へ処理が移るので、非同期処理群を完了してから、次の処理に移りたい時には使えない。最初どこに原因があるか分からず、`asyncio.wait`併用で止めようと試みた。知らなかったのでMEMO.

||`.run_in_executor`による非同期化|素直な非同期化関数|
|---|---|---|
|`.run_until_complete`で非同期可処理群の終了まで**プログラム終了を待つ**か？|YES?|YES|
|`asyncio.wait`と併用で、非同期可処理群の終了までコード停止。**次の行へ処理進まない**か?|**NO**|YES|

- 問題のコード
```python
"""
参考元: https://stackoverflow.com/questions/50303797/python-webdriver-and-asyncio
こちらのコードは、loop.run_until_completeがあっても、取得未完了でも、次の行のコードに到達してしまう。
"""
import asyncio
from concurrent.futures.thread import ThreadPoolExecutor

from selenium import webdriver
from loguru import logger
from selenium.webdriver.chrome import service

executor = ThreadPoolExecutor(10)


def scrape(url, *, loop):
    logger.debug(f"scrape func in. {url=}")
    # 注意) .run_in_executorは同期関数を非同期化できる関数である。
    # しかし、loop.run_until_completeと併用でコード完了までプログラムは実行できるかもしれないが、
    # loop.run_until_completeの次の行へ処理が移るので、非同期処理群を完了してから、次の処理に移りたい時は使えない
    loop.run_in_executor(executor, scraper, url)


def scraper(url):
    logger.debug(f"scraper func in. {url=}")
    chromedriver = '/opt/homebrew/bin/chromedriver'
    chrome_service = service.Service(executable_path=chromedriver)
    driver = webdriver.Chrome(service=chrome_service)
    driver.get(url)
    print(driver.page_source)
    print("END of scraper func")
    return driver.page_source


loop = asyncio.get_event_loop()
for url in ["https://www.google.com/"] * 10:
    scrape(url, loop=loop)

res = loop.run_until_complete(asyncio.gather(*asyncio.all_tasks(loop)))
asyncio.wait(res, return_when=asyncio.ALL_COMPLETED) # 非同期関数処理が終了前にこちらの行へ移る。
loop.close()
print(f".run_until_completeを抜けた!:{res=}")
```

解決策は`.run_in_executor`を使わず、素直に非同期関数として実装する。

- 修正後のコード
```python
"""
https://stackoverflow.com/questions/50303797/python-webdriver-and-asyncio
こちらのコードは、`loop.run_until_complete`で次の行のコードに到達せず待つ。
"""
import asyncio
from concurrent.futures.thread import ThreadPoolExecutor

from selenium import webdriver
from loguru import logger
from selenium.webdriver.chrome import service

executor = ThreadPoolExecutor(10)


async def scrape(url, *, loop): # 非同期関数化した。
    logger.debug("scrape func in")
    await loop.run_in_executor(executor, scraper, url)


def scraper(url):
    logger.debug(f"scraper func in. {url=}")
    chromedriver = '/opt/homebrew/bin/chromedriver'
    chrome_service = service.Service(executable_path=chromedriver)
    driver = webdriver.Chrome(service=chrome_service)
    driver.get(url)
    print("scraper func3")
    print(driver.page_source)
    print("END of scraper func")
    return driver.page_source


loop = asyncio.get_event_loop()
for url in ["https://www.google.com/"] * 10:
    scrape(url, loop=loop)

res = loop.run_until_complete(asyncio.gather(*[scrape(url, loop=loop) for url in ["https://www.google.com/"] * 10]))
print(f".run_until_completeを抜けた!")  # gatherで非同期処理すべて終わってからこちらのコードへ移る
print(res)
```
AutodeskDynamoで作成した3DモデルをBlenderに読み込ませる

# Dynamo
Autodesk RevitやCivil3Dに付属しているDynamoですが、単体でDLして使うこともできます。
http://dynamobim.org/download/
ビジュアルスクリプトで3Dモデルを作成できて便利ですが、Dynamoだけだとレンダリングなどができないので、Blenderで読み込ませるように出力してみました。
### Dynamo画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470113/4e9b2d3a-87ff-06e2-481d-028a3e5bcfd1.png)
### Blender画面
![スクリーンショット 2023-08-17 231211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470113/f13c4982-3db1-8d47-2a7f-d145a2f26420.png)

# DL方法
DynamoBIMのGETDynamoからDYNAMOSANDBOXをDLします。
ZIPファイルがDLされますが、解凍時に7zipで解凍しないと起動できなくなるので要注意です。
https://primer2.dynamobim.org/2_setup_for_dynamo
https://7-zip.opensource.jp/

# 作成した3Dモデルをstlファイルに出力
標準機能でモデルをSTLに書き出すことができるようなのですが、出力しなくてよいものが混じってしまったので、追加パッケージのMeshtoolkitを利用してジオメトリをメッシュに変換し、メッシュデータをエクスポートしました。
### 標準stl出力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470113/3a2a9f25-57d6-a7f1-666d-b30afddac086.png)

### MeshToolKit_MeshByGeometry
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470113/4d7d66d3-d334-16e0-0660-30d2f9ec41dd.png)

### MeshToolKit_ExportMeshes
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470113/7df3234c-1f6f-a92d-63bb-3e203fcc735e.png)

エクスポートしたstlファイルをBlenderで読み込めば、無事転送完了です。
元は四角形で作ってましたが、三角形のメッシュになってました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470113/bed209d1-b148-38de-d17b-5a4a1baf8b6e.png)
Blenderで適用したいマテリアル単位に小分けで出力するのがよいかな？
【Mac】ターミナルからアプリケーションを起動・終了する方法


## アプリケーションを起動する
アプリケーションを起動するには次のようにコマンドを実行します。

```terminal
osascript -e 'tell application "アプリケーション名" to run'
```

以下のコマンドを実行するとリマインダーが起動します。

```terminal
osascript -e 'tell application "Reminders" to run'
```

次のように実行してもアプリケーションを起動できます。
こちらの場合には上記と違い、ウィンドウも表示されます。

```terminal
osascript -e 'tell application "アプリケーション名" to activate'
```

以下のコマンドを実行するとリマインダーが起動し、ウィンドウが表示されます。

```terminal
osascript -e 'tell application "Reminders" to activate'
```

また、次のコマンドも`activate`と同様の結果になります。

```terminal
open -a 'アプリケーション名.app'
```

## アプリケーションを終了する
アプリケーションを起動するには次のようにコマンドを実行します。


```terminal
osascript -e 'tell application "アプリケーション名" to quit'
```

以下のコマンドを実行するとリマインダーが終了します。

```terminal
osascript -e 'tell application "Reminders" to quit'
```
単体テストの設計をやってみた

# 単体テスト？何それおいしいの？
先日単体テストとやらの設計をやってみました

まずは、単体テストとは、なんぞや

```
「単体テストとは、プログラムを組んだモジュールやコンポーネントといった機能単位の動作などを、単体で確認するテストのことです。ユニットテストとも呼ばれます。」
```

なるほど。わからん。

参考記事
https://www.intra-mart.jp/im-press/useful/unit_test


ということで私なりの単体テストについて、
を説明してから、テスト設計について書いていこうと思う。

# 単体テストとは、私の解釈
単体テストとは、
非常に噛み砕いていうと、、、

「一つのアクションをできる限り細分化してもれなくテストすること」

ではなかろうか。

例えば、
データを追加する場合の単体テスト内容は、
「追加ボタンが押せること」
「入力フォームが表示されていること」
「入力フォームに値が入力できること」
、、、という内容になるわけだ。

細かい！細かい！

単体テストとはこういうものらしい。
当たり前にできるだろう、というものですらテスト項目にあげて、
確認していくのだ。

「一つのアクションについて、できる限り細分化して、各項目の確認を行う。」

これが単体テストだとのこと。
ひええ！

# 結合テストってものもあるらしい。おいしそう。
```
結合テストとは、単体テストを終えた各モジュールを組み合わせて、意図した通りの動作や挙動になっているかを確認するテストです。一般的なウォーターフォールモデルの開発においては、プロジェクトの中盤から終盤にかけてさまざまな組み合わせの結合テストが複数回に渡って実施されます。
```
参考資料
https://products.sint.co.jp/obpm/blog/join-test


なるほど、わからん。

単体テストを経て、
「さて、このモジュールはいい感じに動いているようだ、他のモジュールと一緒にテストしてももんだいなかろう、やってみっか！」

というのが結合テストということだようだ。

つまり、私はこの後、結合テストの設計も行うこととなるだろう。
単体テストの設計書作成は大変じゃった、、、

自動化ツール作りたいぞ。

ではまた、結合テストにてお会いしましょう

みなさん、よきエンジニアライフを。
睡眠不足は精神を狂わせますよ。

おわり。
【Docker】Dockerfileで親ディレクトリを参照する

## Dokerfileで親ディレクトリを参照する方法
Dokerfileで親ディレクトリを参照するにはDocker-composeのbuildの箇所でcontextとdockerfileを指定します。

```compose.yml
services:
  api:
    build:
      context: .
      dockerfile: ./docker/api/Dockerfile
```

Dockerfileには親ディレクトリから見たパスを記述します。

```Dockerfile:Dockerfile
FROM ruby:3.1.1

WORKDIR /myapp

COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock  /myapp/Gemfile.lock
RUN bundle install

COPY docker/api/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

EXPOSE 3000

ENV TZ=Asia/Tokyo

CMD ["rails", "server", "-b", "0.0.0.0"]
```
SQL実例_テーブルの中で一番新しいデータを取得（特定のグループ毎）

例えばshopというテーブル。それに紐づく別テーブルのitemsの中で、一番最新のデータを取りたい場合。

すごくシンプルに、テーブルはこんな感じ

```
・itemsテーブル
shop_id
item_id
item_name
cdate
```

それぞれのitemはどこかのshopに紐づいています。

## やりたいこと
この状態で、それぞれのショップの中で一番新しいデータを取りたい。
（同じshopのidで一番新しいデータを取る。）

例えば
```
・itemsテーブル

shop_id 1
item_id 1
item_name おもちゃA
cdate 2023-09-01

shop_id 1
item_id 2
item_name おもちゃB
cdate 2023-09-04

shop_id 1
item_id 3
item_name おもちゃC
cdate 2023-09-01
```
というデータがあった場合。取りたいのは一番新しいおもちゃBです。
シンプルにshop_idがわかってれば、whereでshop_idで絞って、order byでcdateで最新アイテムをとればいいのですが、
お店は何百もあり、itemもたくさんあります。
ので、shop_idを指定せずに全店舗の一番新しいitemをとりたい。ということになります。

## 間違ったケース
最初に考えて間違ったのは、itemsテーブルをshop_idでgroup byして、最新をとったパターン。
group byはshop_id毎にまとめることはできますが、どのitem_idのデータが取れるかわかりません。
ので、group by したところで一番新しいデータが取れる保証はありません。


## 良さそうなクエリ
itemsテーブル と
itemsテーブル as temp_items を比べます。
同じshop_id同士で、cdateの大きい方を選びます。

```
select *
from items
where NOT EXISTS (
    select 1 from items temp_items
    where items.shop_id = temp_items.shop_id and items.cdate < temp_items.cdate
);
```
これをやることで、小さい（古い）itemがshop_id毎に生き残るので、
not existsでそれ以外を選ぶ、ことで、一番新しいデータが取れます。


### まとめ

実は何度かこの方法ググって何度か辿り着いた（いろんな方が近しいことをしている）のですが、
毎回調べているので備忘録として記事にしましたw
これで忘れない！多分！
量子ハイプは、なぜいけないのか

ビッグデータ、機械学習、ブロックチェーン、、、新しい技術が知られるにつれ、必ず付きまとうのが「ハイプ」です。
私は量子コンピュータに携わる人間ですので、特に量子コンピュータのハイプ(量子ハイプ)に対して問題意識を持っています。
ネットには量子ハイプが溢れていて、誤解している方も大勢います。そういったこともあり、次のような記事を書いたこともあります。

https://qiita.com/snuffkin/items/150b2e6d9684a9df5b18

量子ハイプは、なぜいけないのでしょうか？
いくつかの観点から整理してみます。

# 景品表示法に違反する犯罪です
日本には不当景品類及び不当表示防止法(以下、景品表示法)という法律があります。
[消費者庁のサイト](https://www.caa.go.jp/policies/policy/representation/fair_labeling/)から引用すると、次のような法律です。

> 消費者なら、誰もがより良い商品やサービスを求めます。ところが、実際より良く見せかける表示が行われたり、過大な景品付き販売が行われると、それらにつられて消費者が実際には質の良くない商品やサービスを買ってしまい不利益を被るおそれがあります。
> 景品表示法は、商品やサービスの品質、内容、価格等を偽って表示を行うことを厳しく規制するとともに、過大な景品類の提供を防ぐために景品類の最高額を制限することなどにより、消費者のみなさんがより良い商品やサービスを自主的かつ合理的に選べる環境を守ります。

この景品表示法が禁止しているものに「優良誤認表示」があります。
消費者庁が公開している「[事例でわかる景品表示法](https://www.caa.go.jp/policies/policy/representation/fair_labeling/pdf/fair_labeling_160801_0001.pdf)」には、優良誤認表示の説明として次のように記載されています。

> 商品やサービスの品質、規格などの内容について、実際のものや事実に相違して競争事業者のものより著しく優良であると一般消費者に誤認される表示を優良誤認表示として禁止しています。

また、次のようにも書かれています。

> 合理的な根拠がない効果・性能の表示は、優良誤認表示とみなされます。

適正な比較をしていないにもかかわらず、あたかも「大学合格実績No.1」であるかのように表示する予備校の合格実績広告などが、優良誤認表示の例として記載されています。

実際の性能を偽ってコンサルティングしたりサービス提供するのは優良誤認表示であり、景品表示法に抵触する犯罪です。
その技術に詳しくない一般の方をだまして不当に利益を得るのはよくないですよね。
程度が過ぎると「ハイプと言わずに景品表示法違反と言った方がいいのでは」と思いますし、消費者庁から改善指導が入ってからでは遅いですよ。。。

# 事実でないことを世の中に広めてしまう

事実でないことを広めてしまうと何が問題でしょうか。いくつか挙げてみます。

- 誤った政策判断・投資判断をさせ、結果的に分野の発展を遅らせる
科学的エビデンスに基づかない判断としては、HPVワクチンの接種勧奨中止などが挙げられると思います。影響の大きな誤判断は生死に関わる可能性もあります。
量子ハイプで亡くなる方はいないかもしれませんが、非現実的なことに税金を投入して結果が出ないのはもったいないです。
科学的判断に基づいて分野の発展につながることに投資した方がいいですよね。


- 業界の信頼性が低下する
ハイプを許容し、はびこらせていても、いずれ化けの皮は剥がれます。そのとき、ハイプを許容していた業界はどんな目で見られるでしょうか？
量子コンピュータが発展すれば、知的財産に関わる計算を行いたくなるユーザも現れると思いますが、信頼できない人に大切なデータを預けるのは躊躇しないでしょうか？

- 誤情報を元に誤った内容を学習してしまう
誤った情報があふれていると、量子コンピュータを学びたい方が、誤った内容を学習してしまう可能性が高くなります。実際、ネットを見ると、多くの方が誤情報に基づいた量子コンピュータ像を持っているように思います。
また、人間だけでなく、生成AIが質の悪いデータで学習してしまうのも心配です。
嘘も100回言えば真実になるため、量子ハイプはやめて欲しいです。

# 倫理観の欠如した業界になってしまう
せっかく量子コンピュータ業界に新たな人材が入ってきても、業界の先輩たちを見て「ハイプしても大丈夫なんだ」と思ってしまったら、将来的に倫理観の欠如した業界になってしまわないでしょうか？
私も新参者ですが、そういう業界になったら嫌です。

実用化まで険しい道だとしても、ハイプがはびこる倫理観の欠如した業界になって欲しくありません。
　
　
　
**これらの観点から、量子ハイプはいけないと考えています。**
簡易的にrails_adminに認証を作る方法

# 環境
ruby 3.2
rails 7.0.2

# 目的
deviseでrails_adminの認証を作るのではなく、rails_admin自体に入る認証を作りたい。
→devise制御にすると複雑そうだったから

方法としてはbasic認証にする

# 導入方法
```ruby:config/application.rb
ADMIN_USER=admin_user
    config.admin_username = 秘密
    config.admin_password = 秘密
```

ひみつの部分は環境変数を使うといい。

```config/initializers/rails_admin.rb
  config.authenticate_with do
    authenticate_or_request_with_http_basic('Site Message') do |username, password|
      username == Rails.application.config.admin_username && password == Rails.application.config.admin_password
    end
  end
```

# あとがき
今の所ローカルしか仕え無さそうなので本番でも使えるようにしたい。

rails_admin以外と奥が深い・・・
Vueを触っていて躓いたところメモ

普段はサーバーサイドばかり触っていますが、少しフロントの勉強を始めたのでメモ程度に書き残しました。

## Vue3のComposition APIの基本

#### リアクティブなデータの作成
Composition APIでは、`ref` と `reactive` という2つの関数を使用してリアクティブなデータを作成します。

### ref

1. **単純な値に使用**: `ref`は主にプリミティブなデータ型（文字列、数値、ブーリアンなど）のリアクティブな参照を作成するために使用されます。
2. **.valueでアクセス**: 作成されたリアクティブ変数にアクセスする際には `.value` プロパティを使用します。
   
   サンプル：
   ```javascript
   const message = ref('Hello, Vue!');
   console.log(message.value); // 'Hello, Vue!'
   ```

### reactive

1. **オブジェクトに使用**: `reactive`はオブジェクトや配列などの複雑なデータ構造をリアクティブにするために使用されます。
2. **直接的なプロパティアクセス**: 作成されたリアクティブオブジェクトのプロパティには直接アクセスできます。
   
   サンプル：
   ```javascript
   const profile = reactive({ name: 'John', age: 30 });
   console.log(profile.name); // 'John'
   ```

#### setup 関数

setup 関数は、コンポーネントの`created` と `beforeMount`ライフサイクルの間に一度だけ呼び出されます。
この関数内で、リアクティブなデータやメソッドを定義します。

サンプル:
```vue
export default {
  setup() {
    const name = ref('John');
    
    function greet() {
      alert('Hello, ' + name.value);
    }

    return {
      name,
      greet,
    };
  },
};
```

### 「this」コンテキストは使えなくなり「setup」メソッドに(できなくはない)

従来、Vue2ではコンポーネントのインスタンスプロパティにアクセスするためにthisキーワードを使用していました。しかし、Vue3ではインスタンスプロパティへのアクセスの仕方が変わりました。

Vue3ではComposition APIの`setup`という関数があります。しかし、`setup`関数内では、「`this`」というキーワードを使うことができなくなりました。理由は、`setup`関数が、オブジェクトが完成する前の段階で動作するためです。

代わりに、Vue 3では、上述した`ref`関数を使ってデータプロパティを作成します。作成したデータプロパティを変更するためには、`.value`でアクセスします。

サンプル：
```vue
<script>
import { defineComponent, ref } from 'vue';

export default defineComponent({
    name: "ModalComponent",
    setup() {
        const modal = ref(false);

        const toggleModal = () => {
            modal.value = !modal.value;
        };

        return {
            modal,
            toggleModal,
        };
    },
});
</script>
```

このコードでは、`modal`という名前のリアクティブな参照を作成し、その値を読み書きするために`modal.value`を使用しています。

## イベント名のケースに関する注意点

Vue.jsでコンポーネント間で情報をやり取りする時には、カスタムイベントを使います。しかし、イベントの命名や使用には注意点があります。

HTMLは、基本的に「ケースインセンシティブ」です。これは、大文字と小文字を区別しないという意味です。そのため、Vue.jsでは、イベント名を作成する際には、「ケバブケース」（kebab-case: 単語間をハイフンで繋ぐ形式）を使用するのが一般的です。

以下の例を見てみましょう：
```vue
<!-- 子コンポーネント -->
<script>
export default {
  methods: {
    changeStatus() {
      this.$emit('change-modal-status', true); // イベント名はケバブケースで定義しています。
    },
  },
};
</script>

<!-- 親コンポーネント -->
<template>
  <child-component @change-modal-status="handleChangeStatus"></child-component> <!-- イベントをリスニングしています -->
</template>

<script>
export default {
  methods: {
    handleChangeStatus(status) {
      console.log(status); // イベントがトリガーされた時に実行される関数
    },
  },
};
</script>
```

この例では、子コンポーネントから親コンポーネントへchange-modal-statusというイベントを送信して、親コンポーネントでそれを受け取っています。

```vue
<child-component @change-modal-status="handleChangeStatus"></child-component> 
```

子コンポーネントから親コンポーネントへイベントを発行する際には、イベント名をケバブケースで定義してリスニングして、親コンポーネント側では`handleChangeStatus`のようにキャメルケースで記述します。


1. `@change-modal-status`: この部分は、`child-component`内から`change-modal-status`という名前のイベントが発火されたときに、特定のメソッドをトリガーするリスナーを設定しています。`@`は`v-on:`の省略形であり、イベントリスナーを設定するVue.jsのディレクティブを示しています。

2. `"handleChangeStatus"`: これは、`change-modal-status`イベントがトリガーされたときに呼び出されるメソッドの名前です。このメソッドは親コンポーネント内に定義されているべきで、その中で何らかの処理を行います（例：受け取ったデータを使用して親コンポーネントの状態を更新する）。
統計的因果推論の初歩の初歩－－因果推論のモチベーションと基本的発想

# 因果推論の初歩の初歩
統計的因果推論に関する初歩の初歩として、「なんで統計的因果推論なんてものを導入するの？」「手法はいろいろあるけれど、なにをやっているの？」という問委に答えるためのスライドをつくりました。
<iframe src="https://docs.google.com/presentation/d/1s5UJi9qf4Hp7VSPNngqXz3LIejIKgfUD/edit#slide=id.p4" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
同時に複数個のStreamlitアプリを起動しよう！

# はじめに
Pythonのライブラリの1つである、WebフレームワークのStreamlitを用いてWebアプリケーションを作成していたところ
「違う機能を持ったStreamlitアプリを使うとき、いちいちアプリを停止して、コマンドたたくの面倒くさいな…」
と感じたことがありました。
Streamlitアプリは「streamlit run 〇〇.py」というコマンドを使用して、アプリを起動しますが、同時に2つのアプリを起動することができません。
違うアプリを使用したいのであれば、一度アプリを閉じ、再度コマンドをたたく必要があるのです。
めんど！！！と思ったので、今回はStreamlitアプリを同時に起動する方法についてまとめたいと思います。

# 実際にやってみた
今回はsubprocessというライブラリを使用していきます。
subprocessとは、Pythonの標準ライブラリで、外部プロセスを生成したり、制御するために使用されます。つまり、Pythonプログラムから外部プログラムやコマンドを呼び出すことが可能です。
今回の簡単な流れです。
1. 必要なライブラリをインポート
1. ファイルを読み込むウィジェットを作成し、ファイルを読み込む
1. 読み込んだファイルの中身を一時的に保管するファイルにコピー
1. subprocessライブラリを使用して、一時的に保存したファイルに対して、指定のコマンドを実行する

それではコードを書いてみましょう。

```python
import streamlit as st
import subprocess

st.title("ファイルを読み込んで実行")

# ファイルを選択するウィジェットを作成
file = st.file_uploader("ファイルを選択してください", type="py")

if st.button("Streamlitアプリを実行") and file is not None:
    # 選択されたファイルを一時ファイルとして保存
    with open("temp_script.py", "wb") as f:
        f.write(file.read())

    # subprocessライブラリを使用して、別のPythonスクリプトを実行
    subprocess.Popen(["streamlit", "run", "temp_script.py"])

```

ボタンを押下することで、with構文を使用して読み込んだファイルの中身を一時ファイルとして保存し、同時に指定したコマンドを実行します。

ボタンを用意した理由は、ユーザビリティを高めるためです。
ファイルの読み込みと同時に実行されてしまうと、ユーザーが誤ってファイルを選択してしまった場合でも直ぐに実行してしまいます。面倒ですよね。

ちなみにこのスクリプトもStreamlitアプリとして起動するので、こいつ自体はコマンドを入力して起動しておく必要があります。

# まとめ
おかげでいろんな作業を行き来することが可能になりました！
特に意味のあるプログラムかと言われたら、そうでもないような気もしますが、自分の作業効率が少しでも上がったのでヨシとします！
それでは！！！
Next.js(TypeScript) × Docker(Compose V2) 最速構築Tips.

## はじめに
こんにちは！ @Keichan_15 です！

勉強の一環でNext.jsを使用したTech Blogの作成を始めたのですが、環境構築にDockerを使用したので備忘録も兼ねて残しておこうと思います。

シンプルな構成ではありますが、改善点等あればコメント頂けますと幸いです！:bow:

## 準備
まず、任意のディレクトリに新規フォルダを作成し、該当フォルダに移動します。
※筆者は `nextjs_techblog` という名前のフォルダを作成しました。ここはご自身でお好きなお名前にしてくださいね。

```terminal:terminal
$ mkdir nextjs_techblog
$ cd nextjs_techblog
```

## Dockerfile

続いて`Dockerfile`を作成します。
`Dockerfile`を作成するディレクトリは、新規フォルダの直下で構いません。

```dockerfile:Dockerfile
FROM node:18.17.1

WORKDIR /app
```

node.jsのバージョンは [推奨版](https://nodejs.org/ja) を参考にして設定しています。

https://nodejs.org/ja

## compose.yaml
続いて`compose.yaml` を作成します。
こちらも`Dockerfile`と同様、新規フォルダ直下に作成してください。

```yaml:compose.yaml
services:
  app:
    build:
      context: .
    tty: true
    volumes:
      - ./src:/app
    environment:
      - WATCHPACK_POLLING=true
    command: sh -c "npm run dev"
    ports:
      - "3000:3000"
```

補足として、Next.jsのホットリロード機能を有効にするために以下の記述を`compose.yaml`に記述しています。
ホットリロード、凄い便利…。

```diff_yaml
+    environment:
+      - WATCHPACK_POLLING=true
```

その他の記述は他の構築記事と遜色無いシンプルな構成にしています。

ちなみに、ここまでのディレクトリ構成は以下の通りになります。

```
(任意のディレクトリ名)
├── Dockerfile
└── compose.yaml
```

## アプリ作成
ここまで完了したら、以下のコマンドを入力してください。

```terminal:terminal
$ docker compose run --rm app sh -c 'npx create-next-app . --typescript'
```

ちなみに `create-next-app` を叩くと選択を迫られる例の質問は、以下のように設定しました。
ここは個人的な好みの問題になってくるので、あくまで参考までに…:expressionless:

```bash:terminal
Need to install the following packages:
  create-next-app@13.4.19
Ok to proceed? (y) y
✔ Would you like to use ESLint? … No / Yes → Yes
✔ Would you like to use Tailwind CSS? … No / Yes → Yes
✔ Would you like to use `src/` directory? … No / Yes → Yes
✔ Would you like to use App Router? (recommended) … No / Yes → Yes
? Would you like to customize the default import alias? › No / Yes → No
```

```bash:terminal
added 329 packages, and audited 330 packages in 2m

117 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Success! Created app at /app
```

`Success!`の表記が出ていれば、アプリのひな型の作成は完了しています。
最後にコンテナを起動してみましょう。

```console:terminal
$ docker compose up
```

無事コンテナの起動が完了したら、http://localhost:3000/ にアクセスしてNext.jsのページが開くか確認してみましょう。
以下のような表示になっていれば成功です！お疲れ様でした！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2798073/dea1c0a0-4777-232b-d730-cfdb9f5810af.png)

## 参考

https://zenn.dev/peishim/articles/de0dd58ba89ca8

https://zenn.dev/ikkik/articles/51d97ff70bd0da

## おわりに
いかがでしたでしょうか。

今回は極力最小構成でNext.jsの環境構築をDockerで行いました。

Next.jsの構築記事はいくつも見かけるのですが、中々シンプルなものが無かったりして少し難儀したこともあり、今回執筆に至りました。

次はVercelでデプロイしてみたいなあ～～:rolling_eyes:(ウワサでは凄い楽チンと聞く)
【Docker】docker pushしたら denied: requested access to the resource is denied となった



# 目次

[1. 環境](#1環境)
[2. やりたいこと](#2やりたいこと)
[3. 現在の状況](#3現在の状況)
[4. 結論](#4結論)
[5. 背景](#5背景)
[6. 試したこと](#6試したこと)
[7. 参考](#7参考)


# 1.環境

- macOS Ventura 13.5.1
- Docker version 24.0.5


# 2.やりたいこと

作成したイメージをDockerHubにプッシュしたい。


# 3.現在の状況

DockerHubにリポジトリを作成してプッシュしたところ、エラーになった。

```
PC名 ~ % docker push fuga/my-repo
Using default tag: latest
The push refers to repository [docker.io/fuga/my-repo]
44b26f6970d0: Preparing 
61bbeda53374: Preparing 
denied: requested access to the resource is denied
```

調べたところ、以下の記事を見つけたのでユーザー名を確認したが、
イメージのユーザー名とDockerHubのユーザー名は同じ(=fuga)だった。

https://qiita.com/shundayo/items/4ae35930fe9f85f535b0


# 4.結論

Docker DesktopとDockerHubのユーザー名が異なっていた…。


# 5.背景

- 新しいPCにDocker Desktopをインストール
- （以前登録していた）DockerHubと異なる名前にしたので、異なるユーザー名にプッシュしようとしている状態になった

Docker Desktop：hoge
DockerHub：fuga


# 6.試したこと

イメージを作り直して再度プッシュを行う。

詳細は以下に記載する。

①DockerHubをサインアウト→Docker Desktopと同じアカウントで再度入り直す。
②ログインを行う。（`docker login -u ユーザー名 -p パスワード`）
```
PC名 ~ % docker login -u hoge -p xxxxxxxx
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded

Logging in with your password grants your terminal complete access to your account. 
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
```
③pushするも、ローカルにイメージがないよとエラーが出る。
```
PC名 ~ % docker push hoge/my-repo 
Using default tag: latest
The push refers to repository [docker.io/hoge/my-repo]
An image does not exist locally with the tag: hoge/my-repo 
```

④ローカルのイメージを新しく作り直す。
(IMAGE IDは、先頭の数文字を指定したらOKらしい😲)　

★：作り直したもの
```
PC名 ~ % docker images
REPOSITORY              TAG       IMAGE ID       CREATED        SIZE
fuga/my-repo         latest    b14c78352fa8   4 hours ago    69.2MB
PC名 ~ % docker tag b14 hoge/my-repo:test
PC名 ~ % docker images                               
REPOSITORY              TAG       IMAGE ID       CREATED        SIZE
★hoge/my-repo         test      b14c78352fa8   4 hours ago    69.2MB
fuga/my-repo         latest    b14c78352fa8   4 hours ago    69.2MB
```

:::note info
`docker tag 元のイメージ名 レジストリの場所/命名したいリポジトリ名:タグ名` で、イメージにタグ名を付けて複製している。
:::

⑤再度pushを行う。
```
PC名 ~ % docker push hoge/my-repo:test
The push refers to repository [docker.io/hoge/my-repo]
44b26f6970d0: Pushed 
61bbeda53374: Pushed 
test: digest: sha256:b9a9564798489074b343d4e46305b010b34267752b3c759fee86e96f8b381c36 size: 736
```
pushできた！


# 7.参考

https://qiita.com/shundayo/items/4ae35930fe9f85f535b0

https://www.kagoya.jp/howto/cloud/container/dockerlogin/

https://tarovlog.com/2021/01/15/docker-tag/

書籍：小笠原種高, 仕組みと使い方がわかるDocker & Kubernetesのきほんのきほん, マイナビ出版, 2021.
Laravel Eloquentで大量レコードを取得できない


# 発生した事象

Laravel Eloquentで大量レコードを取得しようと試みた。

```php
$builder = Post::where('id', '<>' , 1);
$posts = $builder->get();
foreach ($posts as $post) {
  // 各行のデータを処理する
}
```

get()した時、メモリ不足でエラーになった。該当するレコードは1,000,000件以上ある。

```
Fatal error: Allowed memory size of *** bytes exhausted in ...
```

# 実行環境

Laravel 10.x

# 案1: SQLの実行と結果取得でEloquentを使うのを止めて、`cursor()`でデータを取得する

```php
$builder = Post::where('id', '<>' , 1);
$cursor = DB::connection()->cursor($builder->toSql(), $builder->getBindings());
foreach ($cursor as $row) {
  // $row は stdClass
  $data = get_object_vars($row);
  // $data は [colmun_name1 => column_value1, colmun_name2 => column_value2, …] の連想配列になる
  // 各行のデータを処理する
}
```

## 欠点

- 1行のデータはEloquentのModel(ここではPost)にならない。
- Model に `HasMany` などのrelationが定義されていても、取得できない。代わりに `$builder->join()` `$builder->select()` などを駆使して関係するデータを取得したり、整理する必要がある。
- つまり、概ねPDOStatementによる開発に近くなる。開発者のスキルと合わなくなったり、開発効率が下がったりする可能性がある。

# 案2: `lazyById()` などでカーソルページネーションする

```php
$builder = Post::where('id', '<>' , 1)->lazyById(1000, $column = 'id');
foreach($posts as $post){
  // 各行のデータを処理する
}
```

上記を実行すると、複数のSELECT文を実行してデータを取得する。

```sql
SELECT * FROM posts ORDER BY id ASC LIMIT 1000
SELECT * FROM posts WHERE id > 1000 ORDER BY id ASC LIMIT 1000
SELECT * FROM posts WHERE id > 2000 ORDER BY id ASC LIMIT 1000
・・・
```

 `lazyById()` その他の選択肢について、下記リンクが詳しい。

Laravel の取得系メソッド cursor() や chunk() を徹底比較する
https://qiita.com/nekohan/items/eba0816fe8c21e3cc077

# 欠点

- 同一時点のデータを取得する必要がある場合、利用できない。
- idカラムの代わりに、複合キー(2カラム以上で構成された一意キー)を指定してページネーションする方法が無い。
  - `lazyById()` に限らず、EloquentのModelを使うと良く起きる話。
初投稿に伴うテスト　自己紹介

本日初投稿という事でテスト投稿します。
マークダウン記法も初見という事で、自己紹介にあわせて色々触れていきます。


## 自己紹介
現在私は29歳、仕事内容は運用監視オペレータやってます！
IT系と括ってしまっていいのかは分からないですが、IT系の仕事につきたいと思ったきっかけは2年少し前、当時ビジネス系youtuberが流行っており、**ITエンジニアは稼げるぞ！、IT人材が不足しているから今がチャンス**等という甘い文言に誘われて、あ、なりたいって思った事がきっかけです笑

それから転職を支援してくださる某サービスにお世話になり、数々の面接を行っては落ちの繰り返し、
「**俺ってダメなんだなー。**」って悟り始めた時期にようやく面接に合格して受かった現会社は人材派遣会社で、人が商品なので、とにかく面接に来た人ほとんど合格出しているような会社だと思います（派遣先で元会社が一緒の同僚達が次々謎の失踪を遂げた為。失踪する前は平気で勤務中ゲームをしていたらしい。）

そんな会社に所属しており、派遣先は運用監視オペレーターの上に特注で作ってもらったシステムなので、培った経験も他で活かす事が出来ないと分かっており、このままでは年齢だけ重ねて何の取り柄もなく死んでいくんだ（言い過ぎかも）と今までの人生に深く反省するのと同時に現状をどうにかしなければと思った為、　**転職を決意しました**

### 現在の目標　
**自社開発企業に転職する**
その為にQiitaをメモ帳代わりに利用する事でQiitaに慣れていきたい一方で同じ初学者の方の手本になできるような記事を目標にして書ければと思います。

`以上ちょっとした記事をテストで書いてみました！`

``` 
owari 
```
XYM版XEMReceiverの機能紹介

:::note
この記事はサービス終了したnemlogより転載したものです。
2021-05-02 00:14:50　作成
:::

先日 XYM対応版XEMReceiverをリリースしました。
機能が少し複雑ですので、nemlogで紹介したいと思います。
XEMReceiverの基本コンセプトとしては、
ブロックチェーンはファイナライズの概念があるので決済には使いづらい
というイメージを払拭することです。
かといって、決済には物の流れが発生するためにどうしても送金の確定を待ちたいのも事実です。

「顧客と連絡を取れる体制を取っていれば、ごく稀に発生するロールバックは許容できるのではないか？」
「常態的に送金を受け取るような業務でなければ、実際ロールバックはほぼ無視できるのでは無いか？」
「本人に支払い意思があることは確認できたのだから、イベントなどの使用はロールバックを許容してもよいのではないか？」

サービスを提供する側にもいろいろな気持ちを持たれていると思います。
そんな人たちに、より自分の店舗にあった決済のあり方を見つけていただけるように
XEMReceiverを開発しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29187/3522fd63-0de6-74a7-c82e-fcbbcde5e3ca.png)

# 基本機能
XEMReceiverを表示すると、現在のレート(Zaif価格)が表示されます。
注文IDを入力すると出力されるQRコード内に送金メッセージとして含めることができます。
日本円価格を入力すると現在のレートから必要なXYM価格が自動計算されます。
QRコード出力ボタンで注文ID、XYM価格を含んだQRコードが出力されます。
入金を検知すると注文状況の一覧にトランザクションが追加されます。
ノードの接続状況がファイナライズの接続ノードに●[緑]マークで表示されていますが、
送金したのに、なかなか反映されてないなどのトラブルがありましたら、
[確認]からエクスプローラーへ遷移してトランザクションを確認してください。

# 従来機能からの変更点

### XYM価格
以前は整数値で切り捨てでしたが、
今回は小数第２位で四捨五入しています。
### 対象トランザクション
以前は、注文IDと紐づくトランザクションのみが監視対象でしたが、
今回は、受信するすべてのトランザクションが監視対象となります。
つまり、どのウォレット、QRコードを使用しても入金を検知します。
### 価格固定
以前はQRコード出力時にXYM相場の価格固定を行いましたが、
今回は画面表示時に固定となります。
日本円を変更してQRコード出力ボタンを押せば、必要なXYM価格は都度更新されます。

# 新機能
### ファイナライズ情報の表示
次のファイナライズが発生するまでの予測時間を表示します。
現状 Symbolネットワークは大体10分に1度、ファイナライズが発生しています。
次回ファイナライズ発生時にどこまでの注文分がファイナライズされるかを表示します。
ただし、ファイナライズ直前に決済しても、次のファイナライズに含まれないのでご注意ください。
### 注文状況の表示
受信したトランザクションをリアルタイムで一覧表示します。
その際●マークでステータスが確認できます。
グレー：未承認状態です。
茶色：1承認状態です。
オレンジ：3承認状態です。
緑：ファイナライズ済みです。
赤：ロールバックが発生したブロックに含まれるトランザクションです。

グレーは支払い意思が確認できた状態です。トランザクションのアナウンス後数秒でこの状態になりますが、送金は実施されていません。
茶色は一部のノードで送金が実施されましたが、ロールバックが発生する可能性があります。
オレンジになれば、常態的に使用していない限り、ロールバックが発生することはほぼなくなります。
(取引所で採用されているような6承認待ちが必要な人は、最寄りのNEMアプリ開発者にご相談ください)
緑色になると、きわどいハードフォーク発生に巻き込まれたとしても、ロールバックが発生することはありません。
また、赤色になったからと言っても、トランザクションが消えているとは限りません。ロールバック後に再承認されている可能性もあります。該当するリンクをクリックしてエクスプローラでトランザクションが存在しているか確認してください。

なお、現在設定している価格と同じXYM額の入金があった場合は価格表示にチェックマークが付与されます。
### 最後に
XEMReceiverのXEMという表記が気になる人がいると思います。
XEMBookやXEMReceiverの名前を変更する予定はありません。
どうしても、という方はgithubにて公開しているので、フォークしたのち名前を修正してご利用ください。