OmniAICreator/Qiita-1.07M huggingface dataset:
データに誤差が無い場合の回転行列の算出

## 概要
[3次元回転](https://www.amazon.co.jp/3%E6%AC%A1%E5%85%83%E5%9B%9E%E8%BB%A2-%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E8%A8%88%E7%AE%97%E3%81%A8%E3%83%AA%E3%83%BC%E4%BB%A3%E6%95%B0%E3%81%AB%E3%82%88%E3%82%8B%E6%9C%80%E9%81%A9%E5%8C%96-%E9%87%91%E8%B0%B7-%E5%81%A5%E4%B8%80/dp/4320113829/ref=asc_df_4320113829/?tag=jpgo-22&linkCode=df0&hvadid=342429876379&hvpos=&hvnetw=g&hvrand=15050800337442378170&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009242&hvtargid=pla-795610139000&psc=1&th=1&psc=1)の本のchapter4の内容をまとめた記事です。点群データ(a1,...,aN)を回転行列Rだけ回転させた点群データ(a'1,...,a'N)があったとします。このとき、回転前と回転後のデータをもとに、Rを推定する手法をまとめます。今回はデータに誤差が無いときの手法を実装しますが、その場合はデータは2組の対応するベクトルがあれば十分です。データに誤差がある場合の手法については[こちら](https://qiita.com/Hiroaki-K4/items/8e02d76ad060e9efffaf)をご覧ください。

```math
a\prime_i=Ra,  i=1,..,N
```

## 手法
コードは[こちら](https://github.com/Hiroaki-K4/3d_rotation/blob/main/estimate_R_from_2points.py)にまとめています。
下画像のように、2点(ori1, ori2)をRだけ回転させた場合(rot1, rot2)のRを求めていきます。
![2points.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/7a24a52b-9526-aa5e-1917-42f6ab1d3d4f.png)

まず、2点の外積ベクトルをそれぞれ求めて、単位ベクトルに正規化します。

```math
ori_1*ori_2 = Norm[ori_1 × ori_2]
```
```math
rot_1*rot_2 = Norm[rot_1 × rot_2]
```

下画像の**ori1*ori2**と**rot1*rot2**が求めたベクトルです。
![cross1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/eb5548f0-d922-b310-98ed-8ed2169b4845.png)

次に、**ori1**と**ori1*ori2**の外積ベクトルを求めて、正規化します。rotについても同様です。

```math
ori_1*(ori_1*ori_2) = Norm[ori_1 × (ori_1 × ori_2)]
```
```math
rot_1*(rot_1*rot_2) = Norm[rot_1 × (rot_1 × rot_2)]
```

![cross2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/11110f5a-44cf-16c6-6f86-7211c7cc5a89.png)

先ほど求めたベクトルを整理すると、以下のような正規直交系が得られます。

```math
r_1 = Norm[ori_1], r_2 = Norm[ori_1 × ori_2], r_3 = Norm[ori_1 × (ori_1 × ori_2)]
```
```math
r_1\prime = Norm[rot_1], r_2\prime = Norm[rot_1 × rot_2], r_3\prime = Norm[rot_1 × (rot_1 × rot_2)]
```

これらを列ベクトルとする行列R1, R2は直交行列となります。

```math
R_1=\begin{pmatrix}
r_1 \\
r_2 \\
r_3\\
\end{pmatrix},
R_2=\begin{pmatrix}
r_1\prime \\
r_2\prime \\
r_3\prime \\
\end{pmatrix}
```

R1, R2はそれぞれ基底{e1, e2, e3}を{r1, r2, r3}, {r1', r2', r3'}に写像します。下の式の.Tは転置です。
よって、

```math
R = R_2R_1^\intercal
```

となり、Rは{r1, r2, r3}を{r1', r2', r3'}に写像します。これが求める回転行列Rとなります。
それぞれの関係は下画像のようになります。
![rotation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/421f46a9-c290-405d-4c12-c9565ad052d3.png)

## まとめ
データに誤差が無い場合は、今回説明した手法でRを計算できました。ただ、現実世界ではデータに誤差が乗ってくるので、最小2乗解を解くなどして、推定する必要があります。
Professional Scrum Master I (PSM I) 合格体験記

## 概要
[Professional Scrum Master Iとは](https://www.scrum.org/assessments/professional-scrum-master-i-certification)

> PSM I は、スクラムの習得の基本的なレベルを示す認定資格として業界に認められています。PSM I 認定資格保持者は、スクラム ガイドに記載されているスクラムと、スクラム チームでスクラムを適用する方法を理解していることを証明しました。PSM I 保有者は、スクラムに対して一貫した用語とアプローチを持っています。 

2023/2/19に合格をした。得点は72/80。90%の正解率。13問、間違えると不合格だと思う。
今後仕事にスクラムを導入するかもという話があり、どんなものかを知るために勉強を行った。

## 勉強期間
一か月。50Hぐらいだと思う。1/17に勉強を開始し、2/19に試験を受けた。びっくりしたことに勉強記録を見る限り毎日何かしら勉強していたようである。
英語の翻訳と自分のまとめのノート作成に20Hぐらい頑張ったかもしれない。ノートは暗記に使う。
勉強費用として英語の翻訳で１０００円、模擬試験で２０００円、計３０００円ぐらいだった。

## 勉強方法
他の合格体験記にたくさん書いてあるので、簡潔に書く。私は[Professional Scrum Master に合格したので体験記](https://qiita.com/MxShun/items/9adb7624a453c5b84c3d)を見させてもらった。



- SCRUM BOOT CAMP THE BOOK【増補改訂版】。まずはScene No1を暗記します。あとは余裕があれば読みましょう。

https://www.seshop.com/campaign/agile

- scrum-openの問題を解く。最初は暗記でOK。試験問題はこれと同じ形式で出ます。

https://www.scrum.org/open-assessments/scrum-open

- ミハイルさんの問題を解く。最初は暗記でOK。２０２０年版スクラムガイドに対応してないらしいが気にしなくていいと思う。
https://mlapshin.com/index.php/scrum-quizzes/sm-learning-mode/
https://mlapshin.com/index.php/scrum-quizzes/sm-real-mode/

- スクラムガイドを読む。最初は意味不明なので、scrum-open、ミハイルさんの試験で９割解けるぐらい知識UPしてから読むと理解が深まる。

https://scrummaster.jp/scrum-guide

- mplazaの有料試験を解く。２０２０年版スクラムガイドに対応した問題があるので経験しておくとよい。ここは回答の解説があるので良いサイトだと思う。これは必須ではないが、安心を買うと思ってほしい

https://mplaza.training/exam-simulators/psm/

- ヤフーのまとめの図が覚えるのにいい感じ。これは２０２０年版スクラムガイドに対応していると思われる。

https://techblog.yahoo.co.jp/entry/2021051030146469/

- google翻訳がよくわからないときはdeeplを使う。有料会員にすると楽です。scrum-openではちゃんと動きます。ミハイルさんのサイトでは一部動かないので少し工夫が必要です。実際の試験では動かなかった気がする。

https://www.deepl.com/translator

- ２０１７年版スクラムガイドと２０２０年版スクラムガイドの違い。フーン程度でいいので目を通しておく。この違いで不合格になることはないと思う。

https://qiita.com/viva_tweet_x/items/efa7b464852669292ef5

- 自分が覚えてないことをノートにまとめ復習する。ノートはwebで見れるところがいいと思います。

上記を順番に一か月2時間程度繰り返せば合格すると思います。

## 受験後の感想
見たこともない問題は出る。まったくわからない問題は消去法で乗り切ろう（全部間違えた可能性はある）。模擬試験暗記だけでは不合格になるかもしれない。私は合格したので自分が思っている以上に理解できているのかもしれない。
スクラムガイドのページ数（PDF15頁ぐらい）と勉強時間からもわかるが、他の資格試験とかと比べると合格は簡単である。だが他の研修を要するスクラムの資格より合格ラインは高いので知識だけでいうとこの試験が一番身に付くと思う。あとは実践のみである。
試験中のグーグル翻訳の精度に不安はあったが、十分なものであった。
[PSM II Assessment](https://www.scrum.org/assessments/professional-scrum-master-ii-certification)に興味も持ったが、模擬試験とかなさそうな感じで、真に理解している人しか無理そうな印象なのでニワカの私はやめておく。
意地悪な問題はでないので、ある程度自信がついたら受験すればいいと思います。
受験するときの気持ちはスクラムを理解するではなく、PSMを合格すると切り替えた方がいいです。大事なのは試験対策です。

## 合格後に見つけたページ、ちょっと面白い

https://qiita.com/sugulu_Ogawa_ISID/items/c12dd5ca8f33f047242c

https://scrummaster.jp/downloads/Why-Scrum-Isnt-Making-Your-Company-Very-Agile-jp.pdf

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131136/cb0cfce7-f342-c561-78ab-740e55d26799.png)

まさか日本人がスクラムを作っていたとは思わなかった
Microsoft Certified: Power Platform Fundamentals（PL-900）資格勉強方法

MicrosoftのMicrosoft Certified: Power Platform Fundamentalsに2022年7月に合格したので、勉強方法を共有します。

# 試験概要
概要まとめとしては以下3つがわかりやすくまとまっている

https://qiita.com/gomasa/items/27041cd7d859fba1e4d3

https://qiita.com/nvtomo1029/items/778cf866308b5b1ebe96

https://qiita.com/ueda_it/items/950ddd7698e3616c6d57

# 勉強方法
日本語ベースで学習できる教材は公式のもののみ。
書籍等もあまり出ていないため、公式のラーニングが一番まとまっている。

## Microsoft Learn
公式にて無料で学習できる

https://docs.microsoft.com/ja-jp/certifications/power-platform-fundamentals/

上記Learnの内容を半日で凝縮したウェビナー
参加すると試験1回分の無料バウチャーがもらえる

https://www.microsoft.com/ja-jp/events/top/training-days/powerplatform?activetab=a1:primaryr4

無料でウェビナー形式の問題集解説
上記トレーニングと比べると、試験改定直後のものであり、改定前の用語を使用しており、あまりおすすめではない。
ただし、問題形式に慣れるために受けるのがいいかと。

https://info.microsoft.com/JA-PowerApps-WBNR-FY21-05May-03-MKTOFY21PL900PrepSessionOndemandWebinar-SRDEM73329_LP02OnDemandRegistration-ForminBody.html
配列、連想配列、Mapオブジェクト　まとめ

<h1>配列、連想配列、Mapオブジェクト　まとめ</h1>
<p>結構適当にやってると、頭の中でごちゃごちゃになって、
初心者ミスでコードが動かないことが結構あります。</p>

<p>カンニングペーパーの様に時々見返して脳みそに書き込んで置けたら
いいな。と思って書いてみました。</p>

<p>ある程度、玄人向けなので、余計な説明は付けていないので、説明が必要な人は別のサイトで勉強してください。</p>

<p>随時、追加していきます</p>

<h1>配列</h1>
<h3>初期化</h3>

```Javascript:
let array = []; // 連想配列と同じ
let array = Array(10); // 10は初期化する数 // newは省略できる
let array = [ 1, 2, 3 ];
```

<h3>文字列から配列</h3>

```Javascript
let array = '1 11 5'.split(' '); // 指定した文字列(例では' ')で区切って配列にする // [ 1, 11, 5 ]
let array = 'hello'.split(''); // 1文字ずつ配列にする // [ 'h', 'e', 'l', 'l', 'o' ]
let array = 'hello'.split(); // 単に一つの配列にする // [ 'hello' ]
```

<h3>関係のない変数に展開(分割代入)</h3>

```Javascript
let [ one, two, three ] = array; // {}ではなく[]
```

<h3>追加</h3>

```Javascript
let item = array.unshift('hello'); // 最初に追加
let item = ['bye', ...array];      // 最初に追加
let item = array.push('hello');    // 最後に追加
let item = [...array, 'bye'];      // 最後に追加
```

<h3>取得して元の配列も同時に操作</h3>

```Javascript
let item = array.shift(); // 最初を取得してarrayからは消す
let item = array.pop();   // 最後を取得してarrayからは消す
```

<h3>配列の切り出し</h3>

```Javascript
let array = [ 1, 2, 3, 4, 5 ];
console.log(array.splice(1, 2)); // index1(2番目)から2つを返す // [ 2, 3 ]
console.log(array);              // 切り出した残りの部分になる // [ 1, 4, 5 ]
```

<h3>その他</h3>

```Javascript
let length = array.length; // 配列の総数を取得 // ()は要らない
let unique = [...new Set([ 1, 1, 3, 3, 5 ])]; // 重複削除 [ 1, 3, 5 ]
```

<h1>連想配列</h1>
<h3>空の初期化</h3>

```Javascript
let array = []; // 配列と同じ
let array = { 'hello' : 0, 'bye' : 1 }; // 定義する場合は[]ではなく{}
```

<h1>Mapオブジェクト</h1>
<h3>初期化</h3>

```Javascript
let map = new Map(); // 空のMap
let map = new Map([[ 'hello', 0 ], [ 'bye', 1 ]]); // []は2重 // 初期化のペアは:ではなく,
let map2 = new Map(map); // 複製
let map3 = new Map([...map, ...map2], [1, 'hello']); // マージ (同一キーは後勝ち) // 配列もマージ可能
```

<h3>配列にする</h3>

```Javascript
let keys = [...map.keys()];
let values = [...map.values()];
```

<h3>その他</h3>

```Javascript
let count = map.size; // 要素数の取得 // ()は要らない // 配列のようにlengthではない
let hasHello = map.has('hello'); // 要素が存在するか

map.delete('hello'); // 要素の削除
map.clear(); // 全要素の削除
map.forEach((v, k) => console.log('key:' + k + ', value:' + v)); // 反復処理
```
FastAPI勉強用(Router編)

# 目的
FastAPIのRouter機能の勉強用

# サンプルソース
初期設定のサンプルソースを以下のように追加
```diff:main.py
from fastapi import FastAPI
+from routers import user
+from routers import priv

app = FastAPI()
+app.include_router(user.router)
+app.include_router(priv.router)

@app.get("/")
async def root():
    return {"message": "Hello World2"}
```
```
$ mdkir routers
$ cd routers
$ touch __init__.py
$ vi users.py
$ vi priv.py
```

```routers/user.py
from fastapi import APIRouter

router=APIRouter()

@router.get("/user/", tags=["user"])
async def user_list():
    return [{"account": "user1", "name_sei": "山田", "name_mei":"太郎"},
            {"account": "user2", "name_sei": "海野", "name_mei":"次郎"},
            {"account": "user3", "name_sei": "空野", "name_mei":"三郎"}]

@router.get("/user/{userid}", tags=["user"])
async def user_info(userid):
    return {"username": userid}
```
```routers/priv.py
from fastapi import APIRouter

router=APIRouter()

@router.get("/priv/", tags=["priv"])
async def priv_list():
    return ["adviser", "student"]
```

# 確認
uvicornを再起動してブラウザで確認
https://IPアドレス/api/user/
https://IPアドレス/api/priv/


# 参考
https://zenn.dev/sh0nk/books/537bb028709ab9/viewer/86648d

https://qiita.com/sand/items/ebd4812138e0a5d3a444

https://qiita.com/aKuad/items/d213dc1f7075ab2dd69a

https://self-methods.com/fastapi-file/

https://qiita.com/Akimoto_30s/items/a84a06111f6373b50dc3

https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9
【C++】Dinic法の実装

# Dinic法とは
グラフの最大流を求めるためのアルゴリズムです。やっていることはFord-Fulkerson法とまあまあ似ていますが、最短の増加パスに注目することで計算量を小さくすることを目指します。ちなみに、最大流とは
- グラフ$G=(e,v)$において、$s$から$t$に向かって最大でどれだけの量のフローを流せるかを求める

という問題のことです。
**Dinic法**は以下の手順で行います。
1. 距離が増加する向きの辺のみで構成されたグラフをbfsで取得する。
1. グラフにおける増加パスをdfsで求め、フローを流す。
1. 全ての増加パスにフローを流しおわったら1に戻り、これを増加パスが存在しなくなるまで繰り返す。

1は常に最短の増加パスを考える操作に相当しますが、最短の増加パスの長さはフローを流すにつれて真に増加していくため、違う残余グラフで同じ経路を巡るということはありません。

# Dinic法の計算量
bfsでのグラフ取得は$O(|V|)$で行えます。増加パスを求めるdfsですが、距離が増加する向きの辺のみで構成することによって同じ辺を調べるという操作がなくなるため、各ステップに対して$O(|E|)$、つまり全体として$O(|V||E|)$で行えます。
結局、1と2を合わせた計算量は$O(|V||E|)$となり、これを最大で最短パスの長さの種類分、つまり$|V|-1$回繰り返すので、Dinic法の計算量は$O(|V|^2|E|)$となります。
しかし個々の最悪ケースは互いに両立しないため、実際にはここまでの計算量になることはなく、$O(|V|^2|E|)$で危なそうでも通ってしまうことが多いみたいです。

# Dinic法の実装
用いる変数は以下の通りです。
```cpp
struct edge{int to,cap,rev;}; //辺を記述 to:行き先,cap:容量,rev:逆辺の位置
int level[MAX_V]; //sからの距離
int iter[MAX_V]; //どこまで調べ終わったか
vector<edge> G[MAX_V];//辺の隣接リスト表現
```
辺を追加する操作は以下の通りです。Ford-Fulkerson法と同様に、逆辺も追加する必要があることに注意してください。`vector`の最後尾を逆辺の位置として管理します。
```cpp
void add_node(int from, int to, int cap){
    edge e = {to,cap,G[to].size()}; //辺
    G[from].push_back(e);
    e = {from, cap, G[from].size()-1}; //逆辺
    G[to].push_back(e);
}
```
bfsでグラフを取得する操作は以下の通りです。本当にただのbfsです。
```cpp
void bfs(int s){
  memset(level,-1,sizeof(level));
  queue<int> Q;
  Q.push(s); level[s]=0;
  while(!Q.empty()){
    int v=Q.front(); Q.pop();
    for(int i=0;i<G[v].size();i++){
      edge& e = G[v][i];
      if(e.cap >0 && level[e.to]<0){ 
        level[e.to] = level[v]+1;
        Q.push(e.to);
      }
    }
  }
}
```
dfsで1つの増加パスを取得する操作は以下の通りです。
```cpp
int dfs(int v, int t, int f){
  if(v==t) return f; //到達した
  for(int& i=iter[v];i<G[v].size();i++){ //呼び出しながらiterを更新
    edge& e=G[v][i];
    if(e.cap>0 && level[v]<level[e.to]){ //距離が増加する向きのみ
      int d = dfs(e.to, t, min(f,e.cap));
      if(d>0){
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0; //到達できない
}
```
最大流を求める操作は以下の通りです。``while``の二重となっていてギョっとしますが、特に心配はいりません。どうしても心配なら繰り返し回数が考えうる最大流量を超過したときに中断するような処理を追加すればよいでしょう。
```cpp
int max_flow(int s, int t){
  int flow=0;
  while(true){
    bfs(s);
    if(level[t]<0) return flow; //パスが存在しなくなった
    memset(iter,0,sizeof(iter));
    int f;
    while(f=dfs(s,t,infi) >0){//増加パスが存在するまで
      flow += f;
    }
  }
}
```
Laravelのweb.phpとapi.phpの違い【ルーティングファイル】

## はじめに

Laravel のルーティングファイルについて、何気なく触っていたので備忘録として残します。
※Laravel8 を使用

## 対象者

この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者

## ルーティングファイルの種類

- web.php
- api.php

## 違いについて

#### web.php

デフォルトでCSRF保護の機能が有効になっているため、外部から POST することができない。

#### api.php

CSRF保護が有効になっていないため外部から POST ができる。

## 詳細

kernel.php に web.php と api.php のそれぞれの設定がミドルウェアとして組み込まれています。
デフォルトでは下記の通りの設定となっており、api.php には`VerifyCsrfToken`が入っていないため CSRF保護が機能しておりません。

```php:kernel.php
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            /* CSRF保護 */ 
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
```

## 検証

実際にどのような動きになるのか curlコマンドを使用して検証してみます。

### web.php の場合

事前準備としてエンドポイントを設定します。

- ルーティング

```php:web.php
Route::post('/test', [TestController::class, 'test']);
```

- コントローラーはリクエストをそのまま返却する処理とします

```php:TestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
  function test(Request $request)
  {
    return $request;
  }
}
```

```
curl -X POST -H "Content-Type: application/json" -d '{"name":"太郎"}' http://localhost:8000/test
```

```
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Page Expired</title>
```

CSRF保護の機能が有効になっているため、「Page Expired」が表示されています。

### api.php の場合

上記と同様に事前準備としてエンドポイントを設定します。

- ルーティング

```php:web.php
Route::post('/test', [TestController::class, 'test']);
```

- コントローラー

```php:TestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
  function test(Request $request)
  {
    return $request;
  }
}
```

```
curl -X POST -H "Content-Type: application/json" -d '{"name":"太郎"}' http://localhost:8000/api/test
```

```
POST /api/test HTTP/1.1
Accept:         */*
Content-Length: 17
Content-Type:   application/json
Host:           localhost:8000
User-Agent:     curl/7.64.1

{"name":"太郎"}
```

CSRF保護が有効になっていないため、外部からPOSTでアクセスできます。

## おわりに

PHPのルーティングファイルについてまとめました。
CSRF保護のデフォルト設定が異なっており、主な使い分け方としては下記の通りとなります。

- web.php
  画面に表示するようなルーティングを設定する場合に使用する
- api.php
  外部からの HTTP リクエストを受けて値を返却する場合に使用する
`pandas.DataFrame.pivot_table`での「If any error is raised, this will raise an exception in a future version of pandas.」という警告メッセージへの対応方法

# 環境
* Python 3.10.2
* pandas 1.5.3


# やりたいこと
`pandas.DataFrame.pivot_table`を使って、以下のような集計を行いたいです。


```
>>> df = pandas.DataFrame(
        {
            "count": [1, 2, 3, 4],
            "phase": ["A", "A", "B", "B"],
            "user_id": ["alice", "alice", "alice", "bob"],
        })

>>> df
   count phase user_id
0      1     A   alice
1      2     A   alice
2      3     B   alice
3      4     B     bob

>>> df.dtypes
count       int64
phase      object
user_id    object
dtype: object

>>> df.pivot_table(values="count", columns="phase", index="user_id", aggfunc=numpy.sum)
phase      A    B
user_id          
alice    3.0  3.0
bob      NaN  4.0
```

# 起きたこと
空のDataFrameに対してpivot_tableメソッドを実行したところ、「If any error is raised, this will raise an exception in a future version of pandas. Drop these columns to avoid this warning.」という警告が発生しました。
警告メッセージの内容はよく分かりませんでした。

```
>>> df_empty = pandas.DataFrame(columns=["count","phase","user_id"])

>>> df_empty
Empty DataFrame
Columns: [count, phase, user_id]
Index: []

>>> df_empty.dtypes
count      object
phase      object
user_id    object
dtype: object

>>> df_empty.pivot_table(values="count", columns="phase", index="user_id", aggfunc=numpy.sum)
<ipython-input-64-c704905fca9d>:1: FutureWarning: The operation <function sum at 0x7f1ba2d8edd0> failed on a column. If any error is raised, this will raise an exception in a future version of pandas. Drop these columns to avoid this warning.
  df_empty.pivot_table(values="count", columns="phase", index="user_id", aggfunc=numpy.sum)

Empty DataFrame
Columns: []
Index: []

```


# 対策
`count`列の型をobjectからint64に変更したら、警告は出なくなりました。なぜ列の型を変更したら、警告が出なくなったのかは分かりません。。。列の型の指定は間違っていないので、問題はないでしょう。

```
>>> df_empty2 = df_empty.astype({"count":"int64"})

>>> df_empty2.dtypes
count       int64
phase      object
user_id    object
dtype: object


>>> df_empty2.pivot_table(values="count", columns="phase", index="user_id", aggfunc=numpy.sum)
Empty DataFrame
Columns: []
Index: []
```
CSSの display: grid; で、 rowspanを含む 2x3 のテーブルの繰り返しを作りたい

エクセルやスプレッドシートで悪手と言われているセル結合。しかし表の見せ方としてはやはり重要度の高い表現でもあり、HTML/CSS上でもその表現は用いたいときもある。
また、表というは本来データの繰り返しを2軸で表すことで、俯瞰的に情報の確認をしやすくするものであり、その繰り返しこそに真価があると思う。

例えば下記のような表を作りたいとする。
3人のなにかの点数が表として並べれている。点数が記録されているものは「国語」と「算数」の２つで、この２つが3人分繰り返されているのだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55145/3f561d8d-c442-73cb-0ff8-268790d875f2.png)

# 昔ながらの手法（テーブルレイアウト）
これをたとえば昔なつかしのテーブルでレイアウトすると下記のようになる。
余談だが、 **これは表として用いているので、Tableタグを使うこと自体は何も間違いではない。**

```slim
// slim tempalte
table
  tr
    th(rowspan="2")
      |Aさん
    td 国語
    td 80点
  tr
    td 算数
    td 72点
  tr
    th(rowspan="2")
      |Bさん
    td 国語
    td 42点
  tr
    td 算数
    td 60点
  tr
    th(rowspan="2")
      |Cさん
    td 国語
    td 9999点
  tr
    td 算数
    td 0点
```
あとはこれをCSSでデコレーションしてあげれば完成である。
完成ではあるのだが、これはちょっとした問題が含まれている。
それはレイアウトの変更に弱いという点。昨今のマルチデバイス対応を考えると、具体的には大きな表をスマホで表示させたい際には勝手が悪いのだ。
できることなら、ulやdlタグを用いてCSSでレイアウトしたい。そこで用いられるのが ```display: grid;``` である

# gridレイアウトでの表現方法

```display: grid;``` は、スプレッドシートのような整列したセル内に配置するように、子要素を配置できるとても画期的なレイアウトシステムである。
これにより、昔Tableタグで行われていたレイアウトシステムを、HTML側でのドキュメントの構造を崩すことなく利用できるようになった。
ただ、 ```display: grid;``` は、行単位もしくは列単位での繰り返しに用いるためのプロパティは用意されているのだが、繰り返しパターンを設定してそれを繰り返すみたいな、上記の「国語と算数の点数を持つ表を人毎に繰り返したい」とするためのプロパティは用意されていない。下記のHTMLをそのまま rowspanを含む 2x3 のテーブルの繰り返しにする方法がないのである。やはりレイアウトのためのCSSであって、表組みには用いるのは無理なのか…
と、思ったのだが、ちょっとしたパズルを解く感覚で```display: grid;```の設定を調整すると、無事実現できることがわかった。
それが下記である。

```slim
dl.grid
  .group
    dt.name Aさん
    dd.subject 国語
    dd.point 80点
    dd.subject 算数
    dd.point 72点
  .group
    dt.name Bさん
    dd.subject 国語
    dd.point 42点
    dd.subject 算数
    dd.point 60点
  .group
    dt.name Cさん
    dd.subject 国語
    dd.point 9999点
    dd.subject 算数
    dd.point 0点
```

```sass
.grid
  display: grid
  grid-tempate-columns: 1fr 1fr 1fr
  grid-tempalte-rows: 1fr 1fr
.group
  // ↓ 読みやすさのために包んでいるだけなので、 gridレイアウトの対象からはずす
  display: contents
.name
  grid-column: 1
  grid-row: auto / span 2
  // ↑ grid-row のスタートを auto にして自動流し込み位置に依存させることで、
  border: 1px solid #333
.subject
  border: 1px solid #333
  margin: 0
.point
  border: 1px solid #333
  margin: 0
```

大事なのは、 `.name` の `grid-row` を `auto / span 2` にすることだけである。
`span 2` は、「縦に2マス、セル結合してください」という意味になるのだが、MDNなどを確認しても「指定された開始番号の位置から、2マス結合します」みたいな使用例しかなく、流し込み位置から縦2マス結合する方法がわからなかったのだが、普通に`auto`でそれが実現できた。
上記コードを実装し、ブラウザで表示したものが下記になる。
あとはテーブルのときと同様に、CSSを追加してデコレーションしてあげれば良い。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55145/6ff6d7f0-1515-4708-7cd1-f791494483ed.png)
【Astro】Google Analyticsを導入する

## はじめに
Astroで作ったWebサイトにGoogle Analyticsを導入したときのメモです。
Google Analyticsを使うとアクセス数やユーザ情報が分かるので便利です。

## 手順
### Google Analyticsのトラッキングコードを取得する
Google Analyticsの登録方法についての解説は省略します。
UAは2023年7月に廃止となるので、GA4がよいでしょう。

https://support.google.com/analytics/answer/1009694?hl=ja

https://ferret-one.com/blog/google-analytics-setting

登録ができたら、トラッキングコードを取得します。
トラッキングコードは以下のような形式です。
```html
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'GA_MEASUREMENT_ID');
</script>
```

### ライブラリインストール
ここからは[Astroのメンテナの方が書いた記事](https://www.kevinzunigacuellar.com/blog/google-analytics-in-astro/) の通りに設定しました。

Partytown をインストールします。
```powershell
npm install -D @astrojs/partytown
```

### 設定ファイル追記
`astro.config.mjs`にPartytownの設定を追加します。

```javascript
import { defineConfig } from "astro/config";
import partytown from "@astrojs/partytown";

export default defineConfig({
  integrations: [
    partytown({
      // Adds dataLayer.push as a forwarding-event.
      config: {
        forward: ["dataLayer.push"],
      },
    }),
  ],
});
```

### headタグに追加
レイアウト用のファイルにGoogle Analyticsのトラッキングコードを埋め込みます。
そのまま張り付けると動かないので、少し修正して使います。

- `GA_MEASUREMENT_ID` は自身のトラッキングIDに置き換えます。
- scriptタグ に`type=text/partytown` を追加します。

```html
<!DOCTYPE html>
<html lang="ja">
    <head prefix="og: https://ogp.me/ns#">
        <!-- Google tag (gtag.js) -->
        <script type="text/partytown" src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
        <script type="text/partytown">
            window.dataLayer = window.dataLayer || [];
            function gtag() {
                dataLayer.push(arguments);
            }
            gtag('js', new Date());
            gtag('config', 'GA_MEASUREMENT_ID');
        </script>
        (略)
    </head>
    <body>
        <slot />
    </body>
</html>
(略)
```

これでAstro製WebサイトでGoogle Analyticsを使ったアクセス解析が可能になりました。

## 参考文献
https://www.kevinzunigacuellar.com/blog/google-analytics-in-astro/
GitHub Pages でコミュニティサイトを作り、DiscordLog を公開してみる

「コミュニティの Discord サーバのログをHTMLで取得する」
https://qiita.com/nanbuwks/items/3f7ddf369bd0ddbd5cc5

では、Google Sites でログを公開してみましたが、 GitHub Pages を使ってみます。

# GitHub Pages の制限

- 静的ページのみ
- URL は以下のパターン
- 
  -  https://[ユーザー名].github.io 
   - https://[ユーザー名].github.io/[リポジトリ名] 


となるので、ユーザ名をコミュニティ名で取ることになります。

# GitHub Pages を創る


https://pages.github.com/ の 「User or organization site」 の通りにやってみます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/306fc0bb-78c8-ce85-eebb-e0298cefa720.png)



まずは  GitHub  で [ユーザー名].github.io というレポジトリを作ります。
先にユーザ名をコミュニティ名でと書きましたが、まずはテストのために僕のプライベートユーザー名[nanbuwks]で作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8cb5e13a-691c-6c6f-1e84-9bfc816f6f4c.png)

index.html を作って登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7034686d-3e47-d5dd-2333-c82c797c9fe4.png)

この時点で、「http://nanbuwks.github.io」 にアクセスするとページが公開されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/010b0ffe-5f2a-d393-c5a3-f687c765878b.png)

# Discord のページを公開してみる
「ミニマムな HTML5 ファイルを 「HTML Standard」を見ながら書く」
https://qiita.com/nanbuwks/items/19e7a5fafd6061efb909

を元に、以下のようにしてみました。
```
<!DOCTYPE HTML>
<HTML><HEAD><META CHARSET=UTF-8><TITLE></TITLE></HEAD>
<BODY>
<H1>秋葉原ロボット部(試験サイト)</H1>
</BODY>
</HTML>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3be87999-844e-c3b2-2b68-c36c6542e8f2.png)

URL に `?a` がついているのはキャッシュ避けです。

# Discord のログを公開してみる

```
$ mkdir DiscordLog

```
として、ここに

「コミュニティの Discord サーバのログをHTMLで取得する」
https://qiita.com/nanbuwks/items/3f7ddf369bd0ddbd5cc5

を元に作ったログ


```
'OpenHardTerrace - AKBROBOT - atomrobot [1044812755569496114].html'
'OpenHardTerrace - AKBROBOT - general [1043748064910913546].html'
'OpenHardTerrace - AKBROBOT - イベント [1043748408629940266].html'
'OpenHardTerrace - AKBROBOT - 遠征 [1043748374291173527].html'
'OpenHardTerrace - AKBROBOT - 雑談 [1043748184964477009].html'
'OpenHardTerrace - AKBROBOT - 読書会 [1043748472521756693].html'
'OpenHardTerrace - インフォメーション - 挨拶と規則 [997293495687585833].html'
'OpenHardTerrace - テキストチャンネル - 雑談 [997293495687585839].html'
```

を レポジトリに加え、公開してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/38f0ff03-7ba2-f63a-014e-d0cdf6403e50.png)

ちゃんと見えますね!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/da244d84-4715-1b52-20b8-884d66727a1e.png)

しばらくこれで公開して、SEO などを測定しようと思います。

# GitHub Pages のメリット

Google Sites は GUI で操作しないといけないので自動化できませんでした。 GitHub Pages は git が使えるので楽ですね。

現在、ログを月ごとに取得しページ移動できるようにしたいですが、月ごとにログを更新してアップするなどの自動化を行っていきたいです。
Go 1.20で気をつけたいアップデート内容

## はじめに
2月1日に公開されたGo1.20
こちらのアップデート内容で、動作などに影響を及ぼす、注意すべき内容を書いていきます。

## 注意したいアップデート

### 1. Darwin and iOS
>Go 1.20 is the last release that will run on macOS 10.13 High Sierra or 10.14 Mojave. Go 1.21 will require macOS 10.15 Catalina or later.

MacのOSはCatalina以降でないと動作しないよという内容です。
Catalinaは2019年くらいに公開されたOSなので、アップデートしてない人はほぼいないと思いますが、一応注意したいところ。

### 2. Go command

>The directory $GOROOT/pkg no longer stores pre-compiled package archives for the standard library

GOROOT/pkg ディレクトリには、標準ライブラリのプリコンパイルされたパッケージアーカイブが保存されなくなるとのこと。必要に応じてビルドされるとか。ということは自分でライブラリをコンパイルする機会が増加するかもしれません。ライブラリのアップグレードやバージョンの切り替えに手間がかかるかも。

>The implementation of go test -json has been improved to make it more robust. Programs that run go test -json do not need any updates. Programs that invoke go tool test2json directly should now run the test binary with -v=test2json (for example, go test -v=test2json or ./pkg.test -test.v=test2json) instead of plain -v.

test2jsonを直接呼び出すプログラムは-vの代わりに-v=test2json を指定して (たとえば go test -v=test2json や ./pkg.test -test.v=test2json) テストバイナリを実行しなければならなくなるとのこと。
test2jsonはテストコマンドの結果をjsonにしてくれるオプションのよう。https://pkg.go.dev/cmd/test2json
今まで -v だけで呼び出していた人は気をつけたいところ。

>When the main module is located within GOPATH/src, go install no longer installs libraries for non-main packages to GOPATH/pkg, and go list no longer reports a Target field for such packages. 

非メインパッケージのコンパイル済みアーカイブがGOPATH/pkgに保存されなくなったので依存関係に問題が発生するかも。おとなしくモジュールモードにしておけってことですね。1.13からデフォルトがモジュールモードなので、あまり気にしなくてもいいかもしれませんが。
ちなみに go env GOMOD でモジュールモードかどうかはわかります。

### 3. rand.Seed()が再現性のない値を返すようになった
rand.Seed()にお世話になっている人は多いと思います。今までrand.Seedは一度生成した乱数の値は固定だったのですが、今回からseedの値によらず完全に生成値はランダムになりました。
そのため、再現性のある乱数生成を要求する場合は rand.New(rand.NewSource(seed))を使用しなければなりません。
>The math/rand package now automatically seeds the global random number generator (used by top-level functions like Float64 and Int) with a random value, and the top-level Seed function has been deprecated. Programs that need a reproducible sequence of random numbers should prefer to allocate their own random source, using rand.New(rand.NewSource(seed)).


## 参考文献
公式サイト : 
https://go.dev/doc/go1.20
QLab AppleScript: ExportQLab4<WorkSpaceの書き出し> ＊編集中＊

# 編集中
現在、日本語版の記事を作成中です。
今しばらくお待ちください。


**2023/3/15**
一部公開していた記事は編集作業のために非公開とさせていただきました。
neosでlogix その117

# 概要
neosでlogixやってみる。
練習問題、やってみた。

# 練習問題
触ると、パーティクルが出る箱を作れ。

# 俺コード

```
{a, _, b, _, _, _, _, _, _, _} = ButtonEvents TouchButton
{c, _, _} = BooleanLatch a b
CircleEmitter.Enabled = c
```

# 手順書

- ファイルブラウザを開く
- 手順書をダブルクリック
- DevToolTipを装着
- 新規作成
- パーティクルシステムをクリック
- 新規作成
- 3Dモデル>Boxをクリック
- インスペクターを開く
- ParticleSystemをBoxの下に入れる。
- Transform>Interaction>Touch Buttonを追加
- LogixToolTipを装着。
- そのインターフェースを取り出す
- Particle SystemのSphereEmitterのインターフェースを取り出す
- ノードブラウザを表示
- Interaction>Button Eventsをスポーン
- Flow>Boolean Latchをスポーン
- つなぐ
- ★を押してBox-childを作る
- 名前をLogixに書き換える。
- コンテキストメニューを開く。
- Set Packing Rootにする。
- ノードをグラブして、ｒキーを押して、パッキング
- boxをグラブして、ctrl+sでセーブ

# 写真
![2023-02-19 07.14.49.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a540c4c1-b6eb-a415-dc42-b7f0e00adc1a.jpeg)


以上。
ReactにdaisyUIを導入するまで

# [daisyUI](https://daisyui.com/?lang=jp "daisyUI")とは何か
Tailwind CSSをベースとしたコンポーネントライブラリで、わかりやすく言うとTailwind CSSを更に使いやすくするためのもの

### [Tailwind CSS](https://tailwindcss.com/ "Tailwind CSS")とは
ユーティリティファーストのCSSフレームワークのこと


# プロジェクト作成
```zsh
$ npx create-react-app tailwindcss-tutorial --template typescript
```

# Tailwind CSS導入
daisyUIを使用するにあたってTailwind CSSが導入されていることが大前提なので導入をする
以下公式サイトの導入手順を参考に行う
[Install Tailwind CSS with Create React App](https://tailwindcss.com/docs/guides/create-react-app "Install Tailwind CSS with Create React App")

### Tailwind CSSインストール
```zsh
$ npm install -D tailwindcss
```
#### tailwind.config.js作成
```zsh
$ npx tailwindcss init
```

### tailwind.config.jsを書き換える
`content`に`"./src/**/*.{js,jsx,ts,tsx}"`を足す
```tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

### index.cssを書き換える
```./src/index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

### App.tsxでTailwind CSSが有効か確認
```App.tsx
import React from 'react';
import './App.css';

const App: React.FC = () => {
  return (
    <div className="App">
      <h1 className="text-3xl font-bold underline">Hello World</h1>
    </div>
  );
};

export default App;
```
以下の画像の通りになれば有効になっている。
![スクリーンショット 2023-02-19 16.23.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2860566/8e143932-dc0b-8520-cc2d-d3b18e5529ba.png)

# daisyUI導入
以下公式サイトの手順を参考に導入する
[Install daisyUI as a Tailwind CSS plugin](https://daisyui.com/docs/install/?lang=jp "Install daisyUI as a Tailwind CSS plugin")

### daisyUIをインストール
```zsh
$ npm i daisyui
```

### tailwind.config.jsに`daisyUI`を追加
```tailwind.config.js
module.exports = {
  //...
  plugins: [require("daisyui")],
}
```

# 完成系
daisyUIが有効になっているか確認するため`App.tsx`にボタンを作成

```App.tsx
import React from 'react';
import './App.css';

const App: React.FC = () => {
  return (
    <div className="App">
      <h1 className="text-3xl font-bold underline">Hello World</h1>
      <button className="btn btn-primary">Button</button>
    </div>
  );
};

export default App;
```
おしゃれなボタンが作成された。
![スクリーンショット 2023-02-19 16.38.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2860566/68bc061b-03e0-4fcb-5b16-40c3d18fb89f.png)
【Git】カレントブランチの派生元確認方法・派生元を間違えていた場合のrebaseコマンドによる対応方法などなど

# 概要
* 先日Gitを使っていて「あれ、今いるブランチってどのブランチから派生して作ったんだっけ！？」「あ、派生元間違えていた...」となったことがあったので、その際の確認方法と付帯作業について備忘録を残します。

# 確認事項
* カレントブランチがどこから派生したか
* ローカルに新規ブランチを作成するコマンド
* 派生元を間違えたときはどうすべきか
* ローカルブランチを削除するコマンド

## カレントブランチがどこから派生したか
* カレントブランチがどこから派生したかは、以下コマンドで確認ができます。

```terminal
$ git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -1 | awk -F'[]~^[]' '{print $2}'
```

## ローカルに新規ブランチを作成するコマンド
* 以下コマンドで親にするブランチ名を指定して作成します。

```terminal
git checkout -b {作成するローカルブランチ名} origin/{親にするリモートブランチ名}
```

* parentブランチからchildブランチを作成する場合は、以下のようになります。

```terminal
git checkout -b child origin/parent
```

* ただし、上記を実行する前に、`git fetch`を行なってリモートにある最新情報をローカルに取り込んだ方が良いでしょう。
    * fetch＋merger=pullというのは覚えておくとわかりやすいです。fetchはあくまで最新情報だけ取得するもの。mergeまで行いません。

```terminal
git fetch origin
```

* 補足1：originとは「リモートリポジトリのアクセス先に対してGitがデフォルトでつける名前」です。複数リポジトリを設定している場合は上記のように指定してあげた方が良いかもしれないので、以下コマンドでoriginかどうか確認しましょう。

```terminal
git remote -v
```

* 補足2：親にするリモートブランチが存在するかどうか、もしくは改めて確認したい場合は、以下コマンドでリモートブランチを一覧表示できます。

```
git branch -a
```

## 派生元を間違えたときはどうすべきか

* 以下コマンドにより、派生元のブランチを切り替えることができます。

```terminal
# git rebase --onto {本来親にしたかったブランチ} {間違って親にしてしまったブランチ名} {親を変更する作業ブランチ名}
```

* 具体的には以下のようなコマンドになります。
```terminal
git rebase --onto origin/parent feature/fakeparent feature/child
```

* ただしrebaseコマンドは、コミットの改変なので、すでにpush済みだった場合は、-fオプションで強制的にpushさせるか、以下記事にある他の方法を実行した方が良いです。
    * 参考：[Gitでブランチの派生元を間違えたときの解決方法](https://www.granfairs.com/blog/staff/git-mistake-parent-branch)

## ローカルブランチを削除するコマンド
* 不要なローカルブランチがある場合は、以下コマンドで削除できます。以下どちらでも同じです。

```terminal
git branch --delete {削除したいブランチ名}
git branch -d {削除したいブランチ名}
```

* ちなみに、現在削除予定のブランチにいる場合、以下のメッセージが表示されます。
 
```terminal
Cannot delete branch '削除したいブランチ名' checked out at...
```

* その場合は、checkoutコマンドで別のブランチに移動しましょう。
 
```terminal
git checkout main
git branch --delete {削除したいブランチ名}
```

* なので、削除を実行する場合は、`git branch`で現在のブランチを確認すると良いです。

## 参考文献
* [Gitで今のブランチの派生元ブランチを特定する](https://qiita.com/upinetree/items/0b74b08b64442f0a89b9)
* [【git】リモートブランチをローカルブランチに作成＆チェックアウト](https://obataka.com/git-remote-local-create-checkout/)
* [Gitでブランチの派生元を間違えたときの解決方法](https://www.granfairs.com/blog/staff/git-mistake-parent-branch)
* [Gitでローカルブランチを削除する](https://qiita.com/hogeta_/items/33d2334c9b1919bd5120)
integral_0^(π/4) cos(t) log(cos(t)) dt「(抜粋)2022東京大理系第1問」をwolframalphaとsympyでやってみたい。

wolframalphaでグラフがでます。(2024/02/12)
sympyでグラフがでます。
オリジナル

https://www.youtube.com/watch?v=ukpDKUjbX5s&t=57s

上と同じです。大学入試数学問題集成＞テキスト

https://mathexamtest.web.fc2.com/2022/202210261/2022102610100mj.html#top-0105

# wolframで、やってみました。(2024/02/12)
wolframを3回、続けて実行しました。
・数学入力

https://www.wolframalpha.com/input?i2d=true&i=Integrate%5BCos%5Bt%5DLog%5BCos%5Bt%5D%5D%2C%7Bt%2C%EF%BC%90%2CDivide%5B%CF%80%2C4%5D%7D%5D&lang=ja

・自然言語

https://www.wolframalpha.com/input?i=log%281+%2B+tan%28%CF%80%2F8%29%29+-+log%281+-+tan%28%CF%80%2F8%29%29&lang=ja

・自然言語

https://www.wolframalpha.com/input?i=log%282%29%2F2+-+log%282+-+sqrt%282%29%29&lang=ja

別の形
1/2 log(3 + 2 sqrt(2))

# wolframで、できませんでした。(投稿日 2023年02月19日)

標準の計算時間制限を超えました...

https://www.wolframalpha.com/input?i=integrate%28cos%28t%29*Log%28cos%28t%29%29%2C%28t%2C0%2Cx%29%29&lang=ja

①私の貧弱?な環境のせいかもしれません。
②mathematicaなら、できるかもしれません。

# sympyで(手計算)
猛勉強中!　
＞手を動かしましょう。...まず、logといえば、部分積分。...(PASSLABO様より)　
sympyで部分積分の勉強が必要でした。

# sympyで(正しい方法は専門家の方へ)
教えて下さい。
➀[1]にしています。
➁最小値の多項式の方法を教えて下さい。
```python
from sympy import *
var('x t')
y=cos(x)*log(cos(x))-cos(x)+integrate(cos(t)*log(cos(t)),(t,0,x))
ans=solve(diff(y).simplify())[1]
print("#",      ans ,      y.subs({x:ans}).simplify() )
print("#",float(ans),float(y.subs({x:ans}).simplify()))
#
plot(y,(x,0,pi/2))
plot(diff(y),(x,0,pi/2))
plot(diff(y),(x,0,1.0))
# pi/4 -sqrt(2) - sqrt(2)*log(2)/2 + log(2)/2 - log(2 - sqrt(2))
# 0.7853981633974483 -1.0229690470878257
```
plotコマンドは、縦横比？異なります。y軸の目盛りもよろしくありません。
最小値45°？中点?そんなふうに見えませんね。

![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/f48ca53c-1ab5-694e-846b-fd8dbe969266.png)

以下。私はしつこいです。
勾配図?

![Figure_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/e2c9575c-f078-811b-1b60-b1fae48674b7.png)

勾配図?の拡大図。下がって、変曲点？、π/4で最小値

![Figure_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/eb2c289f-3b73-82f4-2326-26439799a365.png)
【Astro】OGP画像を設定する

## はじめに
Astroで作ったWebサイトにOGP画像を設定したときのメモです。
OGP画像は画像ソースのURLに相対パスではなく絶対パスを指定する必要があったので、少し調べて設定しました。

## 手順
### OGP画像配置
public フォルダに`ogp.png` を配置しました。（faviconと同じ場所）

### URL作成
レイアウト用のファイルに追記します。
まずはOGP画像用のURLを作成します。

```javascript
const canonicalURL = new URL(Astro.url.pathname, '本番環境のWebサイトURL');
const ogpImageURL = new URL('/ogp.png', canonicalURL);
```

これで、本番環境のWebサイトURL/ogp.png にアクセスすると、OGP画像が表示されるようになります。

#### 余談
ちなみに、[公式ドキュメント](https://docs.astro.build/ja/reference/api-reference/#astrourl) には新しいURLの作成についてのサンプルコードが載っています。

```javascript
// Example: Construct a canonical URL using your production domain
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
// Example: Construct a URL for SEO meta tags using your current domain
const socialImageURL = new URL('/images/preview.png', Astro.url);
```

`Astro.site` はローカル環境でundefined になってしまいエラーになるので、イケてないですがサイトのURLをべた書きしました。
`new URL('/images/preview.png', Astro.url)` を使うと、本番環境でローカル環境のURLが生成されてしまったので使いませんでした。

### headタグに追加
上と同じレイアウト用のファイルに追記します。

```html
<!DOCTYPE html>
<html lang="ja">
    <head prefix="og: https://ogp.me/ns#">
        (略)
        <meta property="og:image" content={ogpImageURL} />
        (略)
    </head>
    <body>
        <slot />
    </body>
</html>
(略)
```

これでOGP画像を設定することができました！
設定確認は以下のサイトを使うと便利です。

https://rakko.tools/tools/9/

## 参考文献
https://docs.astro.build/ja/reference/api-reference/#astrourl
bokeh 3.0.3: string型の列を持つ`pandas.DataFrame`を使うと、グラフの描画に失敗する

:::note
この記事に書いた現象は、bokeh3.1では発生しません。
:::

# 環境
* Python 3.10.2
* bokeh 3.0.3
* pandas 1.5.3

# 背景
string型の列を持つ`pandas.DataFrame`を使って、bokehでグラフを描画したいです。



```python:sample.py
from bokeh.plotting import ColumnDataSource, figure, output_file, show
import pandas

output_file("toolbar.html")
data = dict(
    x=[1, 2, 3, 4, 5],
    y=[2, 5, 8, 2, 7],
    desc=["A", "b", "C", "d", "E"],
)
df = pandas.DataFrame(data)
# `desc`列のdtypeをobjectからstringに変換
df["desc"] = df["desc"].astype("string")

source = ColumnDataSource(data=df)
TOOLTIPS = [
    ("desc", "@desc"),
]
p = figure(tooltips=TOOLTIPS)
p.circle("x", "y", size=20, source=source)
show(p)
```

# 起きたこと
bokeh 3.0.3で以下のコードを実行すると、`SerializationError`エラーが発生しました。


```
Traceback (most recent call last):
  File "/home/vagrant/Documents/study/20230219/sample.py", line 24, in <module>
    show(p)
...
  File "/home/vagrant/Documents/study/20230219/.venv/lib/python3.10/site-packages/bokeh/core/serialization.py", line 461, in error
    raise SerializationError(message)
bokeh.core.serialization.SerializationError: can't serialize <class 'pandas.core.arrays.string_.StringArray'>
```

ただし bokeh 2.4.3で実行するとエラーは発生せずに、グラフは期待通り描画されました。

# 原因
原因は分かりませんでした。

[bokehのMigration Guides](https://github.com/bokeh/bokeh/wiki/Migration-Guides#dependencies-)によると、3.0.0からpanadsに依存するようになったようです。もしかしたら、これに関係しているのかもしれません。

>Bokeh now requires pandas.


[Githubにissue](https://github.com/bokeh/bokeh/issues/12821)を作ったので、返信待ちです。

## 追記
PullRequestがマージされました。bokeh3.1で解決されました。
https://github.com/bokeh/bokeh/pull/12841

# 補足
## `pandas.NA`を含むDataFrameも描画できない

```py
output_file("toolbar.html")
data = dict(
    x=[1, 2, 3, 4, 5],
    y=[2, 5, 8, 2, 7],
    desc=["A", "b", "C", "d", "E"],
)
df = pandas.DataFrame(data)
df["desc"][4] = pandas.NA
print(df["desc"])
# 0       A
# 1       b
# 2       C
# 3       d
# 4    <NA>
# Name: desc, dtype: object

source = ColumnDataSource(data=df)
TOOLTIPS = [
    ("desc", "@desc"),
]
p = figure(tooltips=TOOLTIPS)
p.circle("x", "y", size=20, source=source)
show(p)
```

`desc`列のdtypeが`object`でも`pandas.NA`を含むと、`SerializationError`が発生します。

```
bokeh.core.serialization.SerializationError: can't serialize <class 'pandas._libs.missing.NAType'>
```



## `Int64`型の列を含むDataFrameも描画できない


```python
output_file("sample.html")

x = pandas.Series([1, 2, 3, 4, 5], dtype="Int64")
y = pandas.Series([2, 5, 8, 2, 3], dtype="Int64")
df = pandas.DataFrame({"x": x, "y": y})

print(df)
#    x  y
# 0  1  2
# 1  2  5
# 2  3  8
# 3  4  2
# 4  5  3

source = ColumnDataSource(data=df)
p = figure()
p.circle("x", "y", size=20, source=source)
show(p)
```

`SerializationError`が発生します。要は[nullable](https://pandas.pydata.org/docs/user_guide/integer_na.html)なdtypeは、bokeh3.0では対応していません。

```

bokeh.core.serialization.SerializationError: can't serialize <class 'pandas.core.arrays.integer.IntegerArray'>
```
SwiftUI URLからページタイトルを取得



SwiftUI URLからページタイトルを取得

```
import Combine
import Foundation

class GetTitleForLink: ObservableObject {
    @Published var url: String = ""

    @Published var title: String = ""

     var cancellables = Set<AnyCancellable>()

    init() {
        $url.sink { [weak self] _ in
            guard let self else { return }
            self.fetchURLTitle()
        }
        .store(in: &cancellables)
    }

    func fetchURLTitle() {
        guard let url = URL(string: url) else { return }
        URLSession.shared.dataTaskPublisher(for: url)
            .map { data, _ in String(data: data, encoding: .utf8) }
            .compactMap { $0 }
            .replaceError(with: "")
            .receive(on: DispatchQueue.global())
            .map { html in
                guard let range = html.range(of: "<title>.*?</title>", options: .regularExpression, range: nil, locale: nil) else { return "" }
                return html[range].replacingOccurrences(of: "</?title>", with: "", options: .regularExpression, range: nil)
            }
            .receive(on: DispatchQueue.main)
            .sink { [weak self] title in
                guard let self else { return }
                self.title = title
            }
            .store(in: &cancellables)
    }
}

```
@EnvironmentObject で受け取って使用できる。
WindowsServerのOpenSSH設定のコツ

Windows Server 2019以降はOpenSSH ServerがOSの機能として搭載されるようになりました。

AWS EC2上のWindows Serverに接続するときに軽くはまったので、設定のコツをメモとして残すことにします。

# 環境
・サーバー：Windows Server 2019 Base（AWS EC2）
・sshクライアント：RLogin 2.27.2

# 基本の設定
インストール、公開鍵の設定などは以下の記事を参考にしました。

https://dev.classmethod.jp/articles/rdp-over-ssh-without-linux-bastion/

# sshd_config
上の記事でも触れられていますが、sshd_configの以下2行をコメントアウトしないと接続できません。
（Web上でも様々なところで「無効化すべし」と書かれています。）

```
#Match Group administrators
#       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
```

`C:\ProgramData\ssh\administrators_authorized_keys` にファイルを置けば
良さそうな気もしますが、確かに接続できません。

```
PS C:\Windows\system32> Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key -OutFile C:\ProgramData\ssh\administrators_authorized_keys
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919396/4746b3bc-f7f5-e581-3a99-aca3e9b3d160.png)

# なぜコメントアウトが必要か
設定の意味としては「Administratorグループの時は、administrators_authorized_keysを参照する」なので
特に問題はなさそうです。
（「administratorsが有効なのは英語版Windowsだけ！その他の言語だと`S-1-5-32-544`に変換されちゃう」
　といった[Webサイト](https://stackoverflow.com/questions/69811778/ssh-config-commenting-out-match-group-administrators)もありましたが、「Match Group S-1-5-32-544」にしても変わらず）

答えはMicrosoftのページに書いてありました。
administrators_authorized_keysファイルのアクセス権を修正する必要があるそうです。

https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_server_configuration#authorizedkeysfile

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919396/948b0686-7fe3-d77b-d0f9-3ba1237d3d94.png)

# 実際にやってみる
コメントアウトを外してから以下のコマンドたちを実行していきます。
```
【変更前の権限確認】
PS C:\Windows\system32> icacls "C:\ProgramData\ssh\administrators_authorized_keys"
C:\ProgramData\ssh\administrators_authorized_keys NT AUTHORITY\SYSTEM:(I)(F)
                                                  BUILTIN\Administrators:(I)(F)
                                                  NT AUTHORITY\Authenticated Users:(I)(RX)

1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした

【権限変更】
PS C:\Windows\system32> icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
処理ファイル: C:\ProgramData\ssh\administrators_authorized_keys
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした

【変更後の権限確認】
PS C:\Windows\system32> icacls "C:\ProgramData\ssh\administrators_authorized_keys"
C:\ProgramData\ssh\administrators_authorized_keys NT AUTHORITY\SYSTEM:(F)
                                                  BUILTIN\Administrators:(F)

1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした

【サービス再起動】
Restart-Service sshd
```

　
アクセス権修正後、接続することができました！

```
Microsoft Windows [Version 10.0.17763.4010] 
(c) 2018 Microsoft Corporation. All rights reserved.  

administrator@EC2AMAZ-G7LO20S C:\Users\Administrator> 
```

　
理由が分からないままコメントアウトが嫌だったので調べてみましたが、
デフォルトのまま接続できるようになったので、スッキリしました。

嫌らしいことにこのアクセス権については、日本語ページには書いてないんですよね。。。
（Microsoftあるあるですが）

https://learn.microsoft.com/ja-jp/windows-server/administration/openssh/openssh_server_configuration#authorizedkeysfile

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919396/733e7116-8b57-1b1c-0c10-b1a9200d89f2.png)
コードレビューの観点

コードレビューを半年以上行っているので、自分なりのコードレビューの観点をまとめておく。

大枠は[IPAセキュア・プログラミング講座](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c103.html)の第2章 脆弱性回避策とソフトウェア開発工程のソースコードレビューの章を参考にしている。

## レビューは4回に分けて行う
##### ソースコードレビューは次の4つの段階に分けて行う。
4回というのはレビュワーとレビュイー間のやりとりを4回行うという意味ではなく、単に4つの観点からレビューを行うというもの。

時間はかかるが、最初のうちは何をレビューすればいいか分からず指摘しやすいコーディング規約に関する指摘しかされないケースが多いので以下の4つ観点に沿ってレビューを行う。

<table>
  <tr>
    <th>1回目</th>
    <th>修正内容の確認</th>
    <th>修正内容の確認を行い修正箇所を把握</th>
  </tr>
  <tr>
    <th>2回目</th>
    <th>コードの品質</th>
    <th>コーディング規約に沿っているか</th>
  </tr>
  <tr>
    <th>3回目</th>
    <th>機能性</th>
    <th>機能としての要件を満たしているか</th>
  </tr>
  <tr>
    <th>4回目</th>
    <th>パフォーマンス・セキュリティ</th>
    <th>パフォーマンスやセキュリティに問題はないか</th>
  </tr>
</table>

## 1回目： 修正内容の確認
最初に方針の確認と修正範囲の把握を行う。

#### 方針の確認
- まずはチケットを確認して何の機能/不具合に対する実装をおこなったのか確認する
- 本来であればチケットやプルリクに実装方針が書かれているのでそれを見るが、ルール化されておらず記載がなければ実装者に確認する

### 修正範囲の把握
- 修正されたコードがあるファイルやメソッドの構成を見てそれらがどの機能のどの部分なのか把握する
- 各モジュールの参照関係、影響範囲を確認する
- どのようなデータ構造を扱っているか確認する

## 2回目：コードの品質
リーダブルコードに載っているようなコーディングルールに沿っているかを確認する。

#### 先に不要なコードはないか確認
- console.logは全て削除されているか
- debuggerが残っていないか
- デッドコードがないか

#### 見るべき観点（抜粋）
- 変数・メソッド・クラス名の命名規則が適したものになっているか
- モジュールの分割がなされているか、1つのメソッドの行数が多すぎないか
- 例外処理がなされていること
- 再起処理が無限ループしないか
- 外部から入力されるデータには全てバリデーションをかけているか
- コメントは適切に書かれているか

#### 参考にしているサイト
自分の場合はフロントエンドでjsをメインで書いているので、下記をよく参考にしている

- 命名規則
    - [https://ics.media/entry/220915/](https://ics.media/entry/220915/)
- jsの書き方
    - [https://github.com/mitsuruog/clean-code-javascript/](https://github.com/mitsuruog/clean-code-javascript/)


## 3回目：機能性
書かれたコードが要件に沿って動作するかを確認する。
レビュワーが動作確認まで行うのは手間なので、基本はレビュイーに動作確認をしてもらう。

影響範囲によってはどこの機能を重点的に確認してもらうかをレビュイーに伝えて動確させる。

フロントだとUIの修正の場合、画面上で確認する必要があるので

## 4回目： パフォーマンス・セキュリティなど
自分の場合は最終的なパフォーマンスチェックはQAで計測を行ってくれるので、実装面で問題がないかを確認する。

- GETのリクエストを送る際はキャッシュを利用したものになっているか、もしくは利用を検討したか
- ライブラリのインポート時にライブラリ全体をインポートしていないか
- 並列処理を行なっているか


### 参考資料

- [https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c103.html](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c103.html)
- [https://qiita.com/gakuri/items/f4970aea8de5fa9bf016](https://qiita.com/gakuri/items/f4970aea8de5fa9bf016)
Power Query で列名を指定せずにテーブルを結合する方法

# はじめに
Excelブックで、下記のように複数のテーブルが同じ列名を持っているようなときに、これらを一つのテーブルに結合させる方法を考えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/88ed19d4-0be8-d513-f8d4-5e946a48e9a5.png)

# Power Query エディタでクエリを作成する場合
「データの取得」を使って対象のExcelファイルを開き、ナビゲーターではシートを選ばずにブックを選択した状態で「データの変換」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/edf24010-cc4d-9eaa-8d21-daaa5b2ee91e.png)

ブックの中から目的のTableのみでフィルターした後、Data列の展開を実施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/ae3e2716-ce1a-4218-5735-f3420164cea3.png)

このようにすると`Table.ExpandTableColumn`によってData列にあるテーブルからデータを展開・結合させることができますが、引数に列名が埋め込まれてしまうため、入力テーブルの列名が変更されてしまうとクエリを修正する必要があります。

```
let
    ソース = Excel.Workbook(File.Contents("D:\都道府県.xlsx"), null, true),
    フィルターされた行 = Table.SelectRows(ソース, each ([Kind] = "Table")),
    #"展開された Data" = Table.ExpandTableColumn(フィルターされた行, "Data", {"地方", "ISO  JIS番号", "都道府県", "読み", "都道府県庁所在地", "最大都市", "旗", "地方.1", "人口 (人)", "面積 (km2)", "人口密度 (人/km2)", "市町村数", "国会定数 衆 / 参"}, {"地方", "ISO  JIS番号", "都道府県", "読み", "都道府県庁所在地", "最大都市", "旗", "地方.1", "人口 (人)", "面積 (km2)", "人口密度 (人/km2)", "市町村数", "国会定数 衆 / 参"})
in
    #"展開された Data"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/a7475c97-77b4-7483-1182-a6077d9908ee.png)

# `Table.Combine` で結合する方法

元のName列などを残す必要が無いのであれば、`Table.Combine`を使って結合するのが一番単純な方法です。

``` 
let
    ソース = Excel.Workbook(File.Contents("D:\都道府県.xlsx"), null, true),
    フィルターされた行 = Table.SelectRows(ソース, each ([Kind] = "Table")),
    #"展開された Data" = Table.Combine(フィルターされた行[Data])
in
    #"展開された Data"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/ce29a3ee-f41f-dd90-9d4d-46d484eb0f63.png)


# `Table.ColumnNames` で列名を指定する方法

`Table.ExpandTableColumn` と同じ結果を得たい場合は、下記のように一度`Table.Combine`で結合した後に`Table.ColumnNames`で列名のリストを取得する方法を利用できます。

```
let
    ソース = Excel.Workbook(File.Contents("D:\都道府県.xlsx"), null, true),
    フィルターされた行 = Table.SelectRows(ソース, each ([Kind] = "Table")),
    #"展開された Data" = Table.ExpandTableColumn(フィルターされた行, "Data", Table.ColumnNames(Table.Combine(フィルターされた行[Data])))
in
    #"展開された Data"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/0f839918-f285-fa99-25fb-0e105ce78ac2.png)
GCPメモ

Compute Engine

Compute Engineとは、CGPで実行されるVMを提供するサービスです。実行中のVMは通常インスタンス呼ばれる
インスタンスを作成する時、LinuxとWindowsのパブリックイメージを利用できるし、サードパーティベンダーが
提供するほかのパブリックイメージも利用できます。
また、パブリックイメージでは、ニーズを満たせない場合、カスタマイメージも作成できます。

１、ローカルにカスタマイメージがある場合、Googleが提供する仮想ディスクインポートツールを使用してインポートできます。

２、VMのインスタンスを作成する時、Region⇒Zoneの指定が必要で、RegionとZoneを選択する時、以下複数の要因を考慮する
　　　　・コスト（Regionにより違う場合あり）
　　　　・データのローカリティに関する規制
　　　　・高可用性（複数インスタンスを実行している場合、異なるZone、場合により、異なるRegionに配置すること、
　　　　・レイテンシ

３、プロジェクトレベルでユーザに権限が付与されると、これらの権限はプロジェクトの全てのリソースに適用される。
　　例えば、Compute　Engine管理者の権限が付与される場合、そのユーザはプロジェクトの全てCompute　Engineのインスタンスを管理できます。
　　
　　　権限付与する別の方法として。IAMポリシーをリリースに直接追加することにより、プロジェクトの全てリソースではなく、特定のリソースを合わせて権限を調整できます。
　　　
４、プリエンプティブル VM インスタンス
　　プリエンプティブル VM インスタンスは、標準 VM の料金よりもはるかに低価格（60～91% 割引）で利用できます。ただし、他の VM に割り当てるためにコンピューティング容量を再利用する必要がある場合、Compute Engine はこのインスタンスを停止（プリエンプト）する可能性があります。
　　　但し、高可用性ではない場合、コスト面を含めて適切活用できる場面が多く存在する。
　　　

５、カスタム　マシンタイプ
　Compute　Engineには、２５を超える事前定義ｓれるマシンタイプが存在する。　
　特に、ＣＰＵの数とメモリの量は異なり
　
６、Compute　Engineを使用すると、次のことができます。
　　・インスタンスで実行する特定のイメージを選択する。
　　・ソフトウェアパッケージまたはカスタムライブラリをインストールする。
　　・とのユーザがインスタンスに対する権限をもつかをきめ細かく制御する
　　・インスタンスのSSL証明書とファイアウォールルールを制御する