OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu 20.04 LTSでThinkpad A275のトラックポイント設定

# はじめに
手持ちのThinkPadにUbuntuを入れたところ、初期設定ではトラックポイントが思うように動かず苦戦しました。
色々と調べて修正したので備忘録として残します。これから同様の試みをする方の役に立てば幸いです。

- 環境
    - Lenovo ThinkPad A275
    - Ubuntu 20.04 LTS
設定
# サマリ(修正後の挙動)
- トラックポイントでポインタ操作
- タッチパッドはオフ
- 中ボタン＋トラックポイントでスクロール
- 中ボタン単独で押下してもテキスト貼り付けしない

# 問題点と対策方法

|#|問題点|対策|対策詳細|
|---|---|---|---|
|1|トラックポイントが動かない|Ubuntuの設定変更|GRUB設定ファイルを修正|
|2|タッチパッドをOFFにできない|BIOSの設定変更|Configの設定を変更|
|3|各種ボタンの長押し操作が効かない|Ubuntuの設定変更|GRUB設定ファイルを修正|
|4|中ボタン押下で貼り付け操作が起きる|Ubuntuの設定変更|xinput設定を修正|

# やったこと
## Ubuntuの設定変更
### GRUB設定の設定変更(問題点1,3)
- GRUB設定ファイルを開き、GRUB_CMDLINE_LINUX_DEFAULTに以下を追記。
    - "i8042.reset"
    - "psmouse.proto=bare"
    - "psmouse.synaptics_intertouch=1"
 
```terminal:terminal
$ sudo vim /etc/default/grub
```

```terminal:grub設定ファイル
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash i8042.reset 
psmouse.proto=bare psmouse.synaptics_intertouch=1"
```

- GRUB設定ファイルを保存して閉じたあと、GRUBを更新する。

```terminal:terminal
$ sudo update-grub
```

- 再起動する。

```terminal:terminal
$ reboot
```

### xinputの設定変更(問題点4)
- まずxinputでトラックポイントに該当する入力デバイス名を調べる。

```terminal:terminal
$ xinput list
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ PS/2 Generic Mouse                        id=11   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Power Button                              id=8    [slave  keyboard (3)]
    ↳ Sleep Button                              id=9    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=10   [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                    id=12   [slave  keyboard (3)]
```

- PS/2 Generic Mouseがトラックポイントに該当するデバイス名なので、このボタンマップを取得する。

```terminal:terminal
$ xinput get-button-map "PS/2 Generic Mouse"
1 2 3 4 5 6 7
```

- "2"が中ボタンを単独で押したときに該当するようなので、これを"0"へ変更する。

```terminal:terminal
xinput set-button-map "PS/2 Generic Mouse" 1 0 3 4 5 6 7
```

- ~/.profileの末尾へ設定を追加する。

```terminal:~/.profile
xinput set-button-map "PS/2 Generic Mouse" 1 0 3 4 5 6 7
```


- 再起動する。

```terminal:terminal
$ reboot
```

## BIOSの設定変更
### Configの設定変更(問題点2)
- BIOSからConfig→Keyboard/Mouseを開き、Trackpadを"Disabled"へ変更。

これで完了です。

# 参考
[https://qiita.com/NOEU/items/36d60fb80122da581c20](https://qiita.com/NOEU/items/36d60fb80122da581c20)
[https://blog.tmtms.net/entry/201901/thinkpad-psmouse](https://blog.tmtms.net/entry/201901/thinkpad-psmouse)
[http://mibuntuthe2nd.blog.fc2.com/blog-date-202010.html](http://mibuntuthe2nd.blog.fc2.com/blog-date-202010.html)
[https://virment.com/thinkpad-ubuntu-how-to-disable-middle-button-paste/](https://virment.com/thinkpad-ubuntu-how-to-disable-middle-button-paste/)
venvを使ってみる【Python】

# やりたいこと
- Pythonで仮想環境を作るためのvenvを使ってみる。
- venvで作成した仮想環境に、とりあえずpytestをインストールするところまでやってみる。

# 環境
- macOS monterey 12.2.1
※macとwinで結構コマンドが違うようなので、winの方はこの記事は参考にしないでください。

# venvとは
- Pythonの仮想環境を作り出すツール。
- 仮想環境作成は元来「virtualenv」がその役割を担っていたが、Python3.3より、公式でこのツールが提供された。

# 手順
- 前準備
    - 仮想環境を使用したいプロジェクトに移動しておく。
    - 「仮想環境のPythonバージョン＝ローカルのPythonバージョン」となるので、特定のPythonバージョンを仮想環境にて使用したい場合、ローカルのPythonのバージョンをそちらのバージョンに切り替えておく。（pyenvなどで）
        - 仮想環境作成後にPythonのバージョンを切り替えたいときは[こちら](https://dev.classmethod.jp/articles/change-venv-python-version/)の記事が参考になります

- 仮想環境を作成する
```bash
python -m venv sample-env
```
プロジェクトのフォルダに「sample-env」ディレクトリが作成されます。

- 仮想環境を有効にする
```bash
source sample-env/bin/activate

# ~/Documents/my-project/sample-env
# sample-env $
```

- 仮想環境にパッケージをインストールする
```bash
sample-env $ pip install pytest
```

- インストールしたパッケージを表示する
```bash
sample-env $ pip freeze
pytest==7.0.1
tomli==2.0.1
...
```

- 「requirements.txt」を作成する
```bash
sample-env $ pip freeze > requirements.txt
```
別の仮想環境で、今の仮想環境と同じパッケージ環境としたい場合、この「requirements.txt」を使用し、以下を実行します。
```bash
pip install -r requirements.txt
```


- 仮想環境を無効化する
```bash
sample-env $ deactivate
$
```


# 参考
- [公式ドキュメント venv --- 仮想環境の作成](https://docs.python.org/ja/3/library/venv.html)
- [venvで作成した仮想環境内のPythonバージョンを変更したい](https://dev.classmethod.jp/articles/change-venv-python-version/)
- [venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)
- [Pythonにおける仮想環境「venv」について](https://qiita.com/overflowfl/items/1db8746b9831bb15e9b5)
SpringFox導入時のNullPointerException回避

個人的にAPI自動生成を試してみたく、SpringFoxを導入してみました。
その際にちょっとだけ詰まったので備忘。

## 前提
この記事を参考にSpringFox導入しました。
ありがとうございます！

https://qiita.com/nooboolean/items/ee794ec4b30d9e93bf9f

## 問題のエラー

```
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.toString()" because the return value of "springfox.documentation.spi.service.contexts.Orderings.patternsCondition(springfox.documentation.RequestHandler)" is null
    at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:112) ~[springfox-spi-2.9.2.jar:null]
    at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:109) ~[springfox-spi-2.9.2.jar:null]
    at com.google.common.collect.ComparatorOrdering.compare(ComparatorOrdering.java:37) ~[guava-20.0.jar:na]
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:na]
```

## 対処法

application.ymlに下記設定を追加しましょう。
エンドポイント(URL)のパターンマッチングに使われてるような気がします（中身はよくみてない）


```application.yml
spting:
  mvc:
    pathmatch:
      matching-strategy: ant-path-matcher
```

```Config.java
    @Bean
    public Docket swaggerPlugin() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any()) 
                .paths(paths())　　//ここのパスマッチングで使われてそう
                .build()
                .apiInfo(apiInfo());
    }

    private Predicate<String> paths() {
        // ドキュメント生成の対象とするAPIのURLを指定
        // この場合、「/user」で始まるAPIがドキュメント生成対象となる
        return Predicates.or(Predicates.containsPattern("/user"));
    }
```
VBAで正規表現を使用する

# VBAで正規表現を利用する

VBAでも正規表現は利用することができる。
標準の機能としては取り込まれていないが**Microsoft VBScript Regular Expressions 5.5**に機能があるのでこれを利用する。

**Microsoft VBScript Regular Expressions 5.5**を利用するには静的バインドと動的バインドがある。
どちらを使用しても問題ないが静的バインドを使うとVBAの入力支援が受けられるというメリットがある。
静的バインドのためにはあらかじめ参照設定をしておかなくてはならない

## 静的バインドの設定

VBAIDEのメニューから/ツール/参照設定 を選択し
**Microsoft VBScript Regular Expressions 5.5**をチェックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169982/0a7127a2-acd8-0bd0-6abf-f75bdf5bf1b7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169982/3e824a76-35e9-5318-4dc9-3948506dfacb.png)

## 静的バインド
~~~Visual basic
Dim re As New RegExp
~~~

## 動的バイト
~~~Visual basic
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
~~~


# VBAの正規表現オブジェクト

VBAの正規表現オブジェクトは以下の4つで構成される

* RegExp (正規表現文字列を表す）
* MatchCollection (ヒット文字列の集合）
* Match （個々のヒット文字列）
* SubMatches （部分文字列）

MatchCollection はグローバル指定したときの複数のヒット文字列を表す。
Matchは個々のヒット文字列を表す。
SubMatches は（）で囲まれた部分文字列を表す。

# RegExp のメソッド

* Execute (検索実行）
* Replace (置換実行)
* Test (一致テスト)

Testは検索文字列が存在するかどうかをテストする簡易版。

## Testの使用例
~~~Visual Basic
Sub test()
    'Microsoft VBScript Regular Expressions 5.5
    Dim re As New regexp
    
    re.Global = True
    re.IgnoreCase = True
    re.Pattern = "c.ndy"
    r
    For i = 1 To 5
        If re.test(Cells(i, 1)) Then
            Debug.Print "ok"
        Else
            Debug.Print "ng"
        End If
    Next
End Sub
~~~

## Replaceの使用例
~~~Visual Basic
Sub replace()
    'Microsoft VBScript Regular Expressions 5.5
    Dim re As New regexp
    
    re.Global = True
    re.IgnoreCase = True
    re.Pattern = "candy"
    
    For i = 1 To 5
        Debug.Print re.replace(Cells(i, 1), "aaa")
    Next
End Sub
~~~

## execute/Matchの使用例
~~~Visual Basic
Sub execute_match()
    'Microsoft VBScript Regular Expressions 5.5
    Dim re As New regexp
    
    re.Global = True
    re.IgnoreCase = True
    re.Pattern = "(c..)(dy)"
    
    For i = 1 To 1
        Dim mc As MatchCollection
        Set mc = re.Execute("Candyxxcandyxxxxcandy")
        
        Dim m As match
        For Each m In mc
            Debug.Print m.FirstIndex
            Debug.Print m.Length
'            Debug.Print m.SubMatches
            Debug.Print m.Value
        Next
    Next
End Sub
~~~

## execute/Submatchの使用例
~~~Visual Basic
Sub execute_match_submatch()
    'Microsoft VBScript Regular Expressions 5.5
    Dim re As New regexp
    
    re.Global = True
    re.IgnoreCase = True
    re.Pattern = "(c..)(dy)"
    
    For i = 1 To 1
        Dim mc As MatchCollection
        Set mc = re.Execute("Candyxxcandyxxxxcandy")
        
        Dim m As match
        For Each m In mc
            Debug.Print m.FirstIndex
            Debug.Print m.Length
            Debug.Print m.SubMatches.Count
            For j = 0 To m.SubMatches.Count - 1
                Debug.Print m.SubMatches(j)
            Next
            Debug.Print m.Value
        Next
    Next
End Sub
~~~
"Line Notify"を利用してPythonでLineに通知を送る

<h2>はじめに</h2>

仮想通貨自動取引botの取引状況をスマホに通知する際に利用させて頂いてます。  
botを作成するたびに過去のコードからコピペしていたので、今回備忘録としてこちらにまとめました。

<h2>実装する前に</h2>

こちらでトークンを発行して下さい。  

https://notify-bot.line.me/ja/

また今回はrequestsを利用してるので、インストールされてない場合は以下より。

```
pip install requests
```

<h2>テキストで通知</h2>

```python
import requests

url = 'https://notify-api.line.me/api/notify'

token = '発行したトークン'
message = '通知したいメッセージ'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}

requests.post(url, headers=headers, params=params)
```

<h2>テキスト + イメージを通知</h2>

※イメージは3MB以内

```python
import requests

url = 'https://notify-api.line.me/api/notify'

token = '発行したトークン'
message = '通知したいテキスト'
image_file_path = 'イメージファイルパス'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}
files = {'imageFile': open(image_file_path, 'rb')}

res = requests.post(url, headers=headers, params=params, files=files)
```

<h2>テキストを改行したい場合</h2>

```
message = 'ここで改行\n改行後のテキスト'
```
AndroidStudioでエミュレーターのスクリーンショットの撮り方

今までADBなどを使用してスクリーンショットを撮っていましたが、androidStudioでスクリーンショットが撮れるのでやり方を書いておこうと思います。

# Logcatを開く
AndroidStudioの下の方にあるLogCatを開きます。
そうすると左側にカメラアイコンがあるのでそれをクリックします。
![スクリーンショット 2022-03-06 21.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/7f64acdc-3af5-b38a-8ff6-8e38e27a55c0.png)

# ScreenCapture
こちらのような画面が表示されると思います。
![スクリーンショット 2022-03-06 21.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/88975065-dc85-4169-9483-db65356d5c27.png)

右下のSaveをクリックすると保存ができます。
保存したい画面のキャプチャーを変更したい場合は、左上のReCaptureをクリックすると表示している画面が変わります。

簡単にスクリーンショットを撮れますね！
Zoomのビデオキャプチャ画面にタイマーを表示させる方法（Windows）

# はじめに

　卒業研究発表会などで、司会と共にタイマー係がビデオキャプチャ画面にストップウォッチを表示させることがあります。
　ですが、ストップウォッチを表示させるにはZoom以外のソフトが必要で少しややこしく、私の研究室では毎年やり方が分からず困ることが続いていました。ここでは、やり方がわからず困ることが無いよう、簡単にやり方を載せておきます。

# 用意するもの
1. Zoom：https://zoom.us/download
2. OBS（動画配信ツール）：https://obsproject.com/ja/download
3. TimerKeeper：http://maruta.github.io/timekeeper

1と2は必須。3は、時間を設定しておけば勝手にベルが鳴る便利なWebアプリ。使って損はない。

# 画面表示方法
1. 用意するものの1~3をすべて立ち上げる（ZoomはミーティングのURLにアクセス）
2. OBSの下側にある「ソース」に「ウィンドウキャプチャ」を追加し、「Time Keeper」のウィンドウを選択する
3. OBSの右下にある「仮想カメラ開始」をクリック
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253991/7bee4210-a429-ace5-aafc-4d4fe3a90e90.png)
4. Zoom側のビデオ設定で「OBS Virtual Camera」を選択すると、画面共有せずにタイマーが表示される
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253991/29a481f4-1a2e-3624-db33-4275ce215723.png)

# 音声共有方法
ベルの音を自動的に流せるように設定します。そして、その音声共有には新たにソフトウェアを入れる必要があるという記事がありますが、どうもWindowsでは標準の設定でなんとかなるっぽいので、その方法を載せておきます。

1.【Win11の場合※】Windowsの設定→サウンド→サウンドの詳細設定を開く（Windows10でも同じ？）
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253991/511dc2df-aec4-c746-5b80-0a9431a7e3b7.png)
2. 「録画」タブにある「ステレオミキサー」を有効化し、既定デバイスに設定する
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253991/9098d550-e3f6-19cd-2cae-e974a9d3cab1.png)
3.Zoom側の音声設定で「ステレオミキサー」を設定しマイクをオンにすると、ベル音が共有される
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253991/562def0b-4c35-2e31-6236-53309c406d89.png)

【注意】音声の設定をすると、Slackの通知などもすべて共有されるため、予めPC側の通知は着ることをおすすめする

おわり。
Notionのタスク管理とGoogle Calendarを相互連携してみた。(Google ToDoを使っています)

## はじめに
Notionでタスク管理はしているけど、スケジュール管理はGoogle Calendarで実現したい。

このような要望を実現できるプログラムをGoogle Apps Scriptで実装しました。

## できること
Google ToDoや周辺のAPIを利用することにより、Notion上で作成したタスクをGoogle Calendarの画面内で編集することができます。
しかも、その反映内容をNotion上に同期することができます。

イメージはこんな感じです。
https://twitter.com/namiki969/status/1498084910330163202?s=20&t=ehew6sZn-vpZQPFVttVvOg



## 詳細はこちら
Zennの本として、詳細を説明しておりますのでぜひご確認ください！
https://zenn.dev/namiki_i/books/5eaffd68e10000
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/881152/cbc5c07f-e77c-e03f-5476-5ebe8ae685b4.png)


### ソースコード
実装に必要なソースコードを公開しております。
https://github.com/namiki97/Notion2GoogleToDo
### Notionテンプレート
この実装で想定している仕様のNotionデータベースのテンプレートも公開しています。
https://storm-headlight-d0a.notion.site/0305a36b11c04727b321171e152e85b5?v=3bbaab8907704661a3a32be257be74c4
トランザクションブロック ってなに？

## 勉強前イメージ

ブロックいうから、なんか止めるんか？

## 調査

### そもそもトランザクションとは

複数のSQLによって行われる、データ更新の処理を
一つの処理にまとめてDBへ反映させることを指します。
言葉にすればややこしいですが、

PostgreSQLでは BEGIN or START TRANSACTION でトランザクションが開始、 COMMIT で終了になります。
その間の INSERT や UPDATE などは打ったときには保留され、 COMMITされた後まとめてDBへ反映されます。
これがトランザクションです。
DBの種類によっては自動的にトランザクションが開始される仕様になってることもあります。

### トランザクションブロック とは

BEGIN と COMMIT で囲まれた文のグループのことを指します。
イメージとしては以下がブロックになるということです。

```
BEGIN;

UPDATE class SET name = 'May' where number = 1;
INSERT INTO class VALUES (10, 'Mike');

COMMIT;
```

## 勉強後イメージ

止めることじゃなくて、塊ってことか・・・勘違いしてたw

## 参考

- [3.4. トランザクション](https://www.postgresql.jp/document/8.4/html/tutorial-transactions.html)
- [トランザクションの管理](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/stored-procedure-transaction-management.html)
google app scriptで週次報告ドラフト作成

```js
function Main() {
  BuildWeeklyReportDraft();
}

const CONFIG = {
  name: "テスト",
  from: "test@test.com",
  fromAs: "テスト",
  to: "to@test.com",
  signature: `────────────────────────────────────────
署名欄
────────────────────────────────────────`
};

function BuildWeeklyReportDraft(){
  let subject = BulidSubject(CONFIG.name)
  let body = BuildBody(CONFIG.signature);

  GmailApp.createDraft(CONFIG.to, subject, body, {from: CONFIG.from, name: CONFIG.fromAs})
}

function BulidSubject(name="Who are you?") {
  // このスクリプトが実行されるのが日曜なのでその日の日付をそのまま使っていい。
  let date = new Date();
  let startDate = Utilities.formatDate(date, 'Asia/Tokyo', 'MM/dd');

  date.setDate(date.getDate() + 6); // 初日を含むので7ではなく6日後になっていることに注意
  let endDate = Utilities.formatDate(date, 'Asia/Tokyo', 'MM/dd');

  return `週報_${name}_${startDate}～${endDate}`;
}

function BuildBody(signature) {
  let weekDays = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
  let dates = (() => {
    let date = new Date();
    let dates = {};
    for (let i = 0; i <= 7; i++) {
      dates[weekDays[i]] = Utilities.formatDate(date, 'Asia/Tokyo', 'MM/dd');
      date.setDate(date.getDate() + 1);
    }
    return dates;
  })();
  let start;
  let end;
  let jpDates = (() => {
    let date = new Date();
    start = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy年MM月dd日');
    let dates = {};
    for (let i = 0; i <= 7; i++) {
      dates[weekDays[i]] = Utilities.formatDate(date, 'Asia/Tokyo', 'MM月dd日');
      date.setDate(date.getDate() + 1);
    }
    date.setDate(date.getDate() - 2);
    end = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy年MM月dd日');
    return dates;
  })();

  let startTime = "09:00";
  let endTime = "18:00";

  return `
本文

${signature}
`;
}
```
Jetbrains ToolboxでAndroid StudioのBeta版やCanary版などをインストールする手順

できるだけJetbrains ToolboxでIntelliJ系のIDEは管理しておきたいものですが、 (M1 Macなどで買い換える機会があれば試してみてください)
ちょっと深いところに設定があって毎回諦めそうになるのでメモしておきます。

https://www.jetbrains.com/ja-jp/toolbox-app/

(豆知識なんですが、このアプリ、確かCompose Desktopで作られているらしいですね。)

本題なんですが、この右側の `︙` からSettingsを開き、

<img width=300 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/fa5e1e9d-add1-cf7c-54ab-c427d43bf4c7.png />

Other versionsを開きます。 


すると一覧が出てきます。

<img width=300 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/3dc7b4e1-7798-c4f4-6c72-5f11d2671d87.png />

すごく簡単だと思うんですが、自分はちょっと見つけられず、😂 別のやり方で開いていたのですが、指摘いただいて、修正しました。 🙏 

https://twitter.com/craf0/status/1500445500503642115
Markdown Sandbox

Markdown Sample

Normal Text
Normal Text2
...

見出し
# 見出し1
## 見出し2
### 見出し3

箇条書き (unordered list)

- list1
- list2
- list3

* list1
* list2
* list2

* list 1
    * nest1
    * nest2
        * third1
        * thirt2
            * fourth1
            * fourth2
                * fifth1
                * fifth2
* list2

箇条書き (ordered list)

1. list1
1. list2
1. list3
    1. nest1
    1. nest2
1. list4

引用

> quote1
> quote2
> quote3

引用2

> quote1
>> double quote
>> double quote2
> quote2

pre (no format)
    * list
    * dsfsdfsf
    > sdasdaad

コード (gray background)
this is `code segment` that's all.

強調 (italic)
this is it *this is it* that's all
this is it _this is it_ that's all

強調2
this is **that is it** it
this is __that is it__ it

強調3
this is ***that is it*** it
this is ___that is it___ it

horizontal line
---
___
***

http link
[display letter](https://www.google.co.jp)

定義参照リンク (リンクをまとめる）

[this is google][google]
[that is google][google]

[google]:https://www.google.co.jp

GitHub Flavored Markdown(GFM)
https://www.google.co.jp

strike
~~this is it~~

~~~
pre by gfm
~~~

```
pre by gfm2
pre by gfm2

```

syntax high light
~~~java
class Foo
    public void bar(int a){
    }
}
~~~

table
|header1|header2|header3|
|:--|--:|:--:|
|a|b|c|
|a|b|c|
|a|b|c|

link inner page
* [to header1](#header1)
* [to header1](#header2)

[return to menu](#menu)

[参考](https://qiita.com/tbpgr/items/989c6badefff69377da7)
40 代おっさんLambdaを使ってみる

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## lambdaを使う

lambdaの作成画面に行ってください。

作成を押してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/85ca853c-5b13-9ada-3d44-f0b5f629862b.png)

左から

・一からの作成

・設計図の使用
あらかじめAWSで設計されているもの使用できる

・コンテナイメージ

・Serverless Application Repository

### 設計図の使用を選ぶ

hello-world-pythonと入れる

テンプレートが表示されるのでチェックボックスにチェックを入れて、左下の設定をクリック

### 関数名に名前を入れる

関数名をhello-pythonにしました（わかる名前であれば何でもよい）

### 実行ロールを選ぶ

・基本的な Lambda アクセス権限で新しいロールを作成
Lambda は、Amazon CloudWatch Logs にログをアップロードするアクセス権限を持つ、myFunctionName-role-cce1n10s という名前の実行ロールを作成します。
・既存のロールを使用する
あらかじめ作られているロールを使用できる
・AWS ポリシーテンプレートから新しいロールを作成
ロール名を決めて
ポリシーテンプレート・オプションを指定して作ることができます。

今回は基本的な Lambda アクセス権限で新しいロールを作成
を選びます。

下にLambda関数のコードが出ていますがここからは編集できません。

関数の作成を選ぶ

### 関数の概要画面に行く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/7fd506af-24c0-4164-f995-6f0eae31b56b.png)

下のほうをみるとコードソースが見れると思います。

テストを実行してみます。
オレンジのTestをクリック

### テストイベントを設定の画面に行きます

新しいテストイベントの作成にチェックが入っているか確認

イベント名を入れてください（何でも良いです）

下にあるのがLambdaに渡されるJSONのコードになります。

下のほうにある作成をクリック

テストイベントが作成されます。

Testの横に▼あるので見ると自分が作ったイベントがあることが確認できると思います。

Testをクリックすると

### Execution resultsが表示される

Execution resultsが表示されたと思います。

Response
"value1"が返ってきている
return event['key1'] となっているため

Version: $LATEST
バージョンは最新である

Duration: 1.62 ms
実行時間

Billed Duration: 2 ms
課金対象の時間

### モニタリングをクリック

モニタリングにはさまざまなデータを見ることが出来る

#### ログをクリック

CloudWatchのログを表示をクリックすると

CloudWatchのログに画面遷移されます。

ロググループが
/aws/lambda/自分の決めた名前
に自動で決定しいます。

ログストリームにログの情報があるのでクリックしてみてください

実行したログを確認することが出来ます。

### 意図的にコードを変えてエラーを出す

Lambdaにもどり、コードソースに戻ります

```python
#return event['key1']  # Echo back the first key value
raise Exception('Something went wrong')
```

このように書き換えてください

変えた後
Deployの横が
Changes not deployed
になっていますので
Deployをクリック

これで変更が更新されました

#### テストボタンを押す

Execution resultsでエラーの表示が出たと思います。

```python
  File "/var/task/lambda_function.py", line 12, in lambda_handler
    raise Exception('Something went wrong')
```

CloudWatchのログを確認

```python
[ERROR] Exception: Something went wrong Traceback (most recent call last):   File "/var/task/lambda_function.py", line 12, in 
```

とエラーログを確認できます。

このように呼び出しのたびにログが保存されます

### ハンドラの情報

下のほうのランタイム設定を見るとハンドラとあります。
Infoをクリックすると

「関数の設定でハンドラーパラメーターを設定することで、呼び出すハンドラーメソッドをLambdaランタイムに指示できます。

Pythonで関数を構成する場合、ハンドラー設定の値は、ドットで区切られたファイル名とハンドラーモジュールの名前です。たとえば、main.Handlerは、main.pyで定義されたHandlerメソッドを呼び出します。」

説明文がでます

ファイル名とそのメソッドの名前が一致しないとエラーになるので注意

### AMIの権限を見る

設定を開く

アクセス権限を選ぶと

logs:CreateLogGroup
hello-pythonを実行したらCloudWatchにロググループを作った権限
logs:CreateLogStream
LogStreamを作る権限
logs:PutLogEvents
logの情報を吐き出すことが出来る権限

## 最後に

またこの記事は AWS 初学者を導く体系的な動画学習サービス「AWS CloudTech」の課題カリキュラムで作成しました。
<https://kws-cloud-tech.com/>
OCSP とは

## 勉強前イメージ

最後がPだからなんかのプロトコルなんだと思う

## 調査

### OCSP とは

Online Certificate Status Protocol の略で、
デジタル証明書の有効・失効状態を確認するためのプロトコルになります。
有効性はのチェックは2つの方法で確認ができます。

### 証明書の有効性チェックの種類

- CRL

Certificate Revocation List の略で、
有効期限よりも前に失効させたデジタル証明書の一覧です。
CSLファイルをダウンロードしてサーバ証明書のシリアル番号とCRLに登録されたシリアル番号を確認して有効性を見ることができます。
保存したCRLファイルが最新とは限らないので、リアルタイム性は欠けます。

- OCSP

こちらがタイトルのプロトコルで、デジタル証明書の有効性をリアルタイムで確認できます。
OCSPクライアントがOCSPサーバに対して有効性を確認します。
OCSPサーバはVA(Validation Authority)から提供されるシステムで、検証機能に特化しています。

## 勉強後イメージ

証明書の有効を確認するためだけのプロトコルってあるんや・・・
コレ使えば、有効かどうかってすぐわかるね。

## 参考

- [OCSPレスポンダ〜OpenCA OCSPD〜](https://www.designet.co.jp/ossinfo/openxpki/opencaocspd/)
- [CRL or OCSP](https://www.infraexpert.com/study/sslserver13.html)
OpenWrtでRA受信時のsuffixを固定する個人的メモ

OpenWrtのインターフェースで"DHCPv6クライアント"を指定してRAを受信したときにSuffixを指定したものに固定する方法。

以下のものを指定する。
```
option ifaceid '::1'
```

ちなみに、DHCPv6-PDで受信したものを他のインターフェースに割り当てた際にSuffixを固定する場合にはip6ifaceidを使うらしい。LuCIにあるのはこっち。
ExcelからPower BIデータセットへの接続でエラーがでた場合の対処

# はじめに
　Excelから共有されているPower BIデータセットに接続できます。

https://docs.microsoft.com/ja-jp/power-bi/collaborate-share/service-connect-excel-power-bi-datasets?WT.mc_id=DP-MVP-5004418

　何らかの接続環境の問題でエラーがでる場合がありました。その解決方法をサポートの方と確認しました。

## 利用方法

　Excelの「データ」タブ、「データの取得」/「Power BI（テナント名）から」を選択し、データセットに接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/7f6cdff1-f61f-d6fb-1081-a3c269b59f46.png)


## エラーになる場合

接続にいく手前で、このようなフクロウのエラーメッセージとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/75abf529-007b-de23-0bb8-576ab03868c1.png)

> お探しのページが見つかりませんでした。
>
>技術的な詳細 
> 不明なエラーが発生しました。このエラーが解決しない場合、サポートを依頼する際に以下の情報をご提供ください。
>
> 日付と時刻: : 2022-03-05 22:50:55Z
>
> アクティビティ ID: e85c3290-61fd-4692-b50f-....

## エラーの対処方法
　何らかの原因で、Excelアドインのキャッシュが不正になっているようです。なので、以下のフォルダにある**キャッシュの削除**を行います。

> **%localappdata%\Microsoft\Office\SolutionPackages**
>
> **%localappdata%\Microsoft\Office\16.0\Wef**
>
> 例
> C:\Users\ユーザー名\AppData\Local\Microsoft\Office\SolutionPackages
> C:\Users\ユーザー名\AppData\Local\Microsoft\Office\16.0\Wef　


フォルダのキャッシュファイルはこのような形で残っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/08282df7-e95b-41bd-7052-2b11ee8b33bf.png)

削除してもExcelの動作上は問題ありません。

## 正常に動作したケース

キャッシュの削除後は、このような形で正常につながります！よかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/c8dcf92d-0af0-fcd7-fe72-8ac26bb39f7b.png)




# おわりに
　日本マイクロソフトPower BIサポートチームの皆さんには、通常動くはずが動かないというレアケースで困ったときに助けていただき大変ありがたいです。この場を借りてお礼を申し上げます。
モンテカルロシミュレーションで出したπの評価

# やること
古典的なモンテカルロシミュレーションの訓練である、円と乱数を使ったシミュレーションでπを出して、評価する。

## モンテカルロシミュレーションとは
確率を用いて、値を推定する方法。推定とは言っても、十分に信頼できる値を手軽に出せることから、モンテカルロ法の有用性は高い。現在でも金融商品のリスク計算や統計学における数値計算などで用いられている。

## πを出す方法（条件・式）
0~1の乱数を元に、0~1のxy平面にランダムに点を打つ。**円内の点の数Pと全体の点の数Nの比**が、**円S1と平面全体S2の面積比**に対応している。
![無1題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303459/a4683035-528b-1f3e-ed49-e5682fc143f1.png)
ランダムな点が円の中に入っている様子が分かる。図の単位円は1/4されているので、面積比はS1/S2=π/4である。円内の点の検出には原点からの距離を用いた。距離が1以下の場合は変数pに1を加算する。距離は円の領域x^2+y^2<=1により求まる。プログラム言語はPythonを用いた。

## コード
```python:MCsim
import random
def main():
  sta,order=map(int,input("start order").split()) #何個の点を打つか決める。
  for order in range(order):
    N=sta*10**order #orderは指数
    p=0
    for n in range(N):
      x=make_r()
      y=make_r()
      if x**2+y**2<=1:
        p+=1
    pi=4*p/N
    print("pi=",pi,"N=",N)

#0以上1以下の乱数作り関数
def make_r():
  while True:
    r=(random.random())*2
    if r>1:
      continue
    else:
      break
  return r
  
if __name__=="__main__":
  main()
```
## 結果
結果は以下のグラフのようになった。
![T_KT_L1999_mcsE6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303459/236f25c5-6b17-2ce5-f2a5-95fce7a93b6b.png)
点の数が増えるにつれてpi(π)の値に近づいている。1000万の点を打った時、πは3.1409824になった。
## 評価
ランダムに打つ点の数が1万を超えたあたりから小数点第二位までの精度で見れるようになった。1000万の点の場合、四捨五入すると小数点第三位まで一致している。
## 考察
十分なサンプルの点があれば、モンテカルロシミュレーションでは十分に精度高く値を推定することができる。乱数の生成を組み込み関数に頼ってしまったため、次は乱数にもこだわりたい。
流行りのwebflowとやらを触ってみるよ

<h2>webflowとは</h2>
webの構築からホスティングまでできるオンラインのホームページビルダー。

競合だとWix（イスラエル） STUDIO(日本)などがある。

https://webflow.com/

使用感がプロユーズ向けでHTMLとCSSの知識が割と前提らしい。


<h2>料金について</h2>

料金はアカウントプランとサイトプランの2種類
アカウントプランにはフリー（無料）があるので今回はこちらを試してみる。

お客さん向けにリリースしたりコーディングした後にソースコードをエクスポートしたりホスティングするにはサイトプラン（VPS的な感じ？）の枠を有料サブスクで購入すると出来るようになる模様。

https://nocodedb.world/archives/1657

<h2>はじめかた</h2>

いたって普通にログインアカウントを用意する。

「create here」でページ最初のログインをすると自動的にアカウントプランのスターター（無料枠）の状態になっている。

いろいろ試したら追記しよう。。
ACDLを提唱します。その2

# 概要

ACDLとは、アプリは、クラウド、大切なデータは、ローカルです。
plunkerで、jsonを書き込み、読み込みしてみた。

# サンプルコード

```
var line = {
  "maker": { 
     "name": "on" 
  },
  "genkin": {     
  }
};
var json = JSON.stringify(line); 
var blob = new Blob([json], { 
  type: "text/json" 
});
var url = URL.createObjectURL(blob);
document.getElementById("export").href = url;
var uploadFile;
document.getElementById('jsonFile').addEventListener("change", function() {
    var reader = new FileReader();
    reader.onload = function(e) {
      alert(e.target.result);        
      var data = JSON.parse(e.target.result);
      alert(data.maker.name);        
    };
    uploadFile = this.files[0];
    reader.readAsText(uploadFile);
}, true);
//alert("ok");




```

# 成果物

https://embed.plnkr.co/plunk/F9rmEqB26Vck2RTX

以上。
バージョン管理、ライブラリインストール、仮想環境に関するツールの整理【Python】

# やりたいこと
Pythonで仮想環境を構築する方法、およびそれに付随する機能がいろいろあるので、それらを整理する。

# 

ライブラリ名 | 役割 | 補足
--- | --- | ---
pip | Pythonライブラリをインストールするコマンド | 
pyenv | Python自体のバージョン管理 | パッケージ管理もできるようだが、専らPythonバージョン管理のために使われているようだ。
venv | 仮想環境作成 | 旧称は「pyvenv」。サードパーティ製のvirtualenvが、Python3.3より標準機能として実装されたもの。両者の使い方はほぼ一緒。（ただしvirtualenvは、仮想環境作成機能に加え、Pythonバージョン切替の機能も備わっている）
conda | （Anaconda環境下での）パッケージ管理、仮想環境作成、Pythonバージョン管理
pipenv | pip + venv | 「Pipfile」を使用する
poetry | pip + venv | 「pyproject.toml」を使用する


- まず、Anaconda環境を使うか使わないかを決める。
    - Anaconda環境ではpipを使用することができない。Anaconda環境にてpipを使用してライブラリをインストールすると、運が悪いと(?)Anaconda環境がぶっこわれる。
    - 非Anaconda環境における「pip」≒ Anaconda環境における「conda」
    - pipではインストールできるが、condaではインストールできないライブラリもあったりする。そういう時筆者は、Anaconda環境が壊れる可能性を承知でpipでぶちこんでいた。。
    - Anacondaを使用するなら、今後Anacondaにすべてを委ねると腹をくくらなければならない。
***
- （以下、Anaconda環境を使わないと決めた場合）
- Pythonのバージョンの切り替えを行いたい
    - →　pyenvを使う。Windowsだと「pyenv-win」が使える（昔はWindowsでpyenvを使うことができなかったらしい）
- 仮想環境を作りたい
    - Python3.3以降　
        - →　venvを使う。virtualenvも使えるが、公式でvenvが出ているのでvenvを使うのが無難らしい。あとvirtualenvは使いにくいらしい。
    - Python3.3以前（3.3を含まない）　
        - →　virtualenvを使う。


# 参考
- [pyenv、pyenv-virtualenv、venv、Anaconda、Pipenv。私はPipenvを使う。](https://qiita.com/KRiver1/items/c1788e616b77a9bad4dd)
- [Pythonと環境の備忘録](https://note.com/9_23/n/n4ea7a3c76a66)
- [Python:venv + pyenvでの環境構築](https://messefor.hatenablog.com/entry/2020/08/22/181519)
- [Pythonにおける仮想環境「venv」について](https://qiita.com/overflowfl/items/1db8746b9831bb15e9b5)
Reactについて簡単なまとめ

## ■Reactとは
・Facebook社(現Meta社)が開発したJavaScriptライブラリ(フレームワークではない)
・Reactが利用されているサービスには「Facebook」「Instagram」「Yahoo!」「Netflix」などがある

## ■Reactの特徴
・JSX記法(JavaScriptの中にHTMLのような記法で記述可能)である

・仮想DOM(Virtual Document Object Model)というレンダリング機構が備わっているため高速動作可能
　→従来のDOM構築 …ページ内の変更が一部でもDOM全体を再構築し画面描画する
　→仮想DOMを利用したDOM構築 …ページ変更前後を仮想DOMで比較し変更差分だけDOMに反映する

・コンポーネント指向である
　→ReactではHTMLの一部を切り取って部品として定義することで、その内容を簡単な記述だけで呼び出すことが可能
　→部品として定義することで再利用が可能となり、コードの記述が簡素化されメンテナンスコストを下げることに繋がる

## ■Reactのデメリット
・先進的な機能を導入したり発展途上のため、学習コストが高く日本での活用事例が少ないらしい
・ニュースサイトなどの記事を読むだけのサイトなど動的でないサイトには不向きである
　→上記特徴が活かされないため
lambdaをローカルで動かしてみよう

今回はlambda上に実装したアプリケーションをローカルで動かす方法を紹介します。
言語はpython3.8です。

## この記事の流れ
1. AWS SAM CLI のインストール
2. アプリの作成(lambda)
3. ローカルで挙動確認

## 1. AWS SAM CLI のインストール
下記、リンクを参考にインストールを行なってください。
[AWS SAM CLI のインストール](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)


## 2. アプリの作成(lambda)
ターミナルを立ち上げ、lambdaのプロジェクトファイルを作成するディレクトリに移動して下記コマンドを実行してください。

```zsh
sam init
```

　SAMテンプレートの作成が始まり、いくつか選択を要求されますので、下記を選択をしてください。
　・ 1 - AWS Quick Start Templates
　・ 1 - Zip (artifact is a zip uploaded to S3)
　・ 9 - python3.8 
　・ 1 - Hello World Example

## 3. ローカルで挙動確認
下記コマンドを実行し、ローカルでlambdaを実行可能な状態にする。
```zsh
sam local start-api
```
この状態で、http://127.0.0.1:3000/hello を叩き、下記表示が確認できれば動作確認完了。
```
{"message": "hello world"} 
```

ちなみに、中身の処理を変更したい場合は app.py のlambda_handler の中身を変更してください。
sam-app/hello_world/app.py

## 次回予告
次回は実際にAWSにデプロイし、他の人も実行できるようする方法を紹介したいと思います。
【Laravel】@forelse を @foreach 以上にお勧めしたい理由

## `@foreach` ディレクティブの使い方

Laravel で Blade ファイルを編集するときにお世話になる `@foreach ディレクティブ`。コントローラから、記事情報を受け取って、Blade ファイル内で記事情報の展開をする際などに使用されます。例えば、以下のようなコードです。

```php:article.blade.php
<div class="article-box">
    @foreach( $articles as $article )
        <div class="card">
            <h3>{{ $article->title }}</h3>
            <p>{{ $article->content }}</p>
            <small>{{ $article->author }}</small>
        </div>
    @endforeach
</div>
```

このように、`@foreach` は コントローラから受け取った記事情報 `$articles` を反復処理して使用できるように、1記事あたりの情報を、`$article` としてループさせています。

とても便利な `@foreach` ディレクティブですが、少々弱点もあります。<font color=red>**例えば、コントローラから受け取った $articles 内に、何も記事情報がなかった場合はどうでしょうか？**</font> その場合、`@foreach` 内にネストされたコードは実行されません（記事情報がないのですから当たり前と言ってしまえば当たり前です）。

記事情報が出力されない場合（$articles に記事情報がなかった場合）に備えて、`@foreach` ディレクティブを使用する際は、一緒に `@if` ディレクティブを使用することをお勧めします。例えば、上記のコードを参考にするのであれば、記事情報がない場合に備えて以下のようにコードを記述します。

```php:article.blade.php
<div class="article-box">

    // 記事情報があった場合
    @foreach( $articles as $article )
        <div class="card">
            <h3>{{ $article->title }}</h3>
            <p>{{ $article->content }}</p>
            <small>{{ $article->author }}</small>
        </div>
    @endforeach

    // 記事情報がなかった場合
    @if( $articles->isEmpty() )
        <p>No articles</p>
    @endif
</div>
```

このように、`$articles` に記事情報がない場合でも、`@if`の判定により、`<p>No articles</p>` とブラウザに出力され、Webサイトの利用者は、「記事がないんだな」と理解することができますね。

## `@forelse` ディレクティブをお勧めする理由

・・・という感じで、`@foreach` の使い方について説明してきましたが、この `@foreach と @if の組み合わせ` を更に簡単、便利にした `@forelse` ディレクティブがあるのでご紹介したいと思います。使い方は簡単で、例として以下のコードをご覧ください。

```php:article.blade.php
<div class="article-box">
    @forelse( $articles as $article )
        <div class="card">
            <h3>{{ $article->title }}</h3>
            <p>{{ $article->content }}</p>
            <small>{{ $article->author }}</small>
        </div>
    @empty
        <p>No articles</p>
    @endforelse
</div>
```

この `@forelse` ディレクティブは、もしも `$articles` の情報がない場合に備えて、`@empty` ディレクティブ以下に、記事情報がない場合に表示されるコードを記述できます。今回の例では、`@empty` と `@endforelse` の間の `<p>No articles</p>` が記事情報のない場合に出力されます。

このように、`@forelse` と `@foreach` を比較してみると、`@forelse` のほうがスッキリして見えてきませんでしょうか？

本記事で解説した例のコードでは、`@foreach` でも `@forelse` でも、出力される内容は変わりません。しかし、コードが見やすくする目的で `@forelse` を使用することをお勧めできれば良いなと思います。
【Kotlin】オフラインリアルタイムどう書くF04（正八角形の分割）

問題: [正八角形の分割 2017.4.19 問題](http://nabetani.sakura.ne.jp/hena/ordf04octsp/)

Kotlin での解答:

```Kotlin
/**
 * [正八角形の分割 2017.4.19 問題](http://nabetani.sakura.ne.jp/hena/ordf04octsp/) を解き、
 * 出力文字列を返す。
 *
 * @param input 入力文字列。
 * @param baseRegularPolygon 基本となる正多角形の頂点の数。
 * @return 出力文字列。
 */
fun resolve(input: String, baseRegularPolygon: Int = 8): String =
    @Suppress("ComplexRedundantLet")
    input.toUInt()
        .let { resolve(it, baseRegularPolygon) }
        .joinToString("")

/**
 * [正八角形の分割 2017.4.19 問題](http://nabetani.sakura.ne.jp/hena/ordf04octsp/) を解く。
 *
 * @param apexBits 線分で結ぶ頂点群をビットで表したもの。
 * @param baseRegularPolygon 基本となる正多角形の頂点の数。
 * @return 出来上がる多角形の頂点数を昇順にならべたもの。
 */
private fun resolve(apexBits: UInt, baseRegularPolygon: Int = 8): List<Int> {
    require(apexBits in 0U until (1U shl baseRegularPolygon))

    // apexBits を baseRegularPolygon ビットの整数と考えて、
    // 最上位ビットが 1 になるよう左シフトした値。
    val shiftedApexBits: UInt = run shiftedApexBits@{
        val mostSignificantBit = (1U shl baseRegularPolygon - 1)
        var bits = apexBits
        while (bits and mostSignificantBit != mostSignificantBit) {
            bits = bits shl 1
        }
        return@shiftedApexBits bits
    }

    // 出来上がった多角形（の頂点の数）のリスト。
    val polygons: List<Int> = buildList {
        var polygon = 3 // 出来上がった多角形（の頂点の数）
        var bits = shiftedApexBits
        while (bits > 0U) {
            if (bits and 1U == 1U) {
                // 基本となる正多角形の中点を通る2つの線分がまっすぐつながる場合
                if (baseRegularPolygon % 2 == 0
                    && polygon - 2 == baseRegularPolygon / 2
                ) {
                    polygon -= 1
                }

                add(polygon)
                polygon = 3
            } else {
                polygon += 1
            }

            bits = bits shr 1
        }
    }

    return polygons.sorted()
}
```

／以上
WordPress メディアライブラリのゴミ箱機能には大きな罠がある

WordPress でメディアライブラリに入っている画像やファイルは [完全に削除] しかありません。
記事や固定ページにはゴミ箱機能があり、一旦削除したものがゴミ箱に入るのに、なぜメディアライブラリにはゴミ箱機能ないのでしょう？

実はメディアライブラリにもゴミ箱機能はあるのですが、標準で OFF になっているのです。
では、ON にするとどのような動作をするのか検証してみました。

## そもそも調査と検討を始めた理由

※ここは重要ではないので、読み飛ばしてもらって OK です。

WordPress のユーザーを削除すると、ユーザー所有のコンテンツもまとめて削除する機能があります。
いや、これはむしろ罠かと思う機能で、操作方法を知らないユーザーがコンテンツをまとめて削除する事故が発生したりしています。

このような悲しい事故が発生したときでも、メディアライブラリのゴミ箱機能を有効にしていれば、比較的容易に復旧できそうということが検証でわかりました。

## メディアライブラリのゴミ箱有効化

`wp-config.php` に設定を追加するだけです。

```php
define( 'MEDIA_TRASH', true );
```

でも、わざわざ有効化にしないといけないのには理由がありそうです。
はじめは過去の互換性のために OFF にしていると思っていましたが、どうやら違いそうです。

## メディアライブラリのゴミ箱はなにが罠なのか？

問題が発生する手順を簡単にまとめます。

1. メディアライブラリに `test.jpg`  にアップロードします。
内部的には `wp-contents/uploads/2022/03/test.jpg` にアップロードされました。
2. 記事 A にメディアライブラリから `test.jpg` を貼り付けて更新します。
記事 A を Web ページとして確認し、 `test.jpg` が表示されていることを確認できます。
3. メディアライブラリから `test.jpg` をゴミ箱に移動します。
4. **`test.jpg` をゴミ箱に移動したのに、相変わらず記事 A には `test.jpg` が表示されている**ことを確認できます。
当然、内部的には `wp-contents/uploads/2022/03/test.jpg` はまだ存在しますので表示されています。
ただし、WordPress のメディアライブラリを管理しているデータベース内部では `test.jpg` はゴミ箱に入っているフラグが立っています。
( `wp_post` テーブルの `post_status` が `Trash` に設定されます。)
5. **ゴミ箱に入れたメディアは 30 日経過すると自動的に削除されます。
データベース上のレコードと、実際のファイルが削除されるタイミングはここです。**
(※日数は `EMPTY_TRASH_DAYS` で変更できます。)
6. 何もしていないのに突然、記事 A から `test.jpg` が表示されなくなります。
この頃には `test.jpg` をゴミ箱に入れたことなど忘れられているでしょう。
また、この動作はログに記録されるわけではありません。

通常、記事をゴミ箱に入れると、上記の 4. のタイミングで Web 表示されなくなります。
ただし、コンテンツの場合は内部的なパス `wp-contents/uploads/2022/03/test.jpg` のファイル自体を参照するため、ゴミ箱に入れてもファイルはそのまま存在するため Web 表示されたままになってしまうのです。

ここで、記事とコンテンツのゴミ箱動作の差異が発生します。
コンテンツをゴミ箱に入れた瞬間に Web 表示されなくなれば操作した際に誤操作を思い出しやすいのですが、30日経って突然消えてしまう動作をされた場合は原因の調査のしようもありません。
自分以外の誰かが削除していたときには、更に調査は絶望的でしょう。

ですので、WordPress のメディアライブラリのゴミ箱機能は標準で OFF になっているのです。

## まとめ

WordPress のメディアライブラリのゴミ箱機能は、リスクを承知の上で ON にしないと危険です。
このことに触れている記事が検索した限り見当たらなかったので、検証結果として残しておきます。
CSSでよく使う記述まとめ

# border

https://developer.mozilla.org/ja/docs/Web/CSS/border

### 線の太さを指定
```
.border{
    border: 4px solid;
}
```

https://techacademy.jp/magazine/8626

### border-style
https://developer.mozilla.org/ja/docs/Web/CSS/border-style

http://htmlcsshp.blog.fc2.com/blog-entry-28.html

# padding

https://developer.mozilla.org/ja/docs/Web/CSS/padding

# !important
スタイル適用の優先順位を上げることができる宣言。通常CSSでは後から書いたものほど優先されるけど、これを使った部分は記述場所に関係なく優先される。
https://techacademy.jp/magazine/9424
```
p {
  color : red !important;
}
```

CSSのルールではタイプセレクタよりも、HTMLタグに直接指定する方式であるclassセレクタや、idセレクタが優先的に適用されます

# タイプセレクタ
p {color : red}
div {color : red}

# classセレクタ
.font-red{color : red}


# 行間を調節するプロパティ　line-height:
line-height: 行間の値（正確には、フォントサイズと上下の余白合計値）

# 字間の調整　letter-spacing:
https://saruwakakun.com/html-css/reference/letter-spacing

# 背景画像の設定
```
.bg-size{
    background-image: url('画像のurl');
    background-size: cover;
}
```
https://job-support.ne.jp/blog/css/howto-picture-display

# 画像サイズを自動調整する方法(比率維持かつレスポンシブ対応)
width: 100%;ではなく、
max-width: 100%;にすることで、親要素の幅を超えなくなる。
height:autoを指定するとwidthに合わせて画像の元の比率を保ったままheightが変化する。
```
.example img{
    max-width: 100%;
    height: auto;
}
```
https://csshtml.work/img-maxwidth/

https://getbootstrap.jp/docs/4.2/content/images/

# div枠全体をリンクする
親要素.DivLink、子要素.Linkを以下のように記述する。
```
.DivLink{
    position:relative;
}
```

```
.DivLink .Link{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
```
https://www.ipentec.com/document/html-css-link-entire-div-frame

## マウスオーバーした時に白っぽくする

https://kubogen.com/web-programing-214/

# animation

https://recursionist.io/dashboard/course/9/lesson/107

https://recursionist.io/dashboard/course/16/lesson/328

https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode

# flex-shrink

https://developer.mozilla.org/ja/docs/Web/CSS/flex-shrink

https://recursionist.io/dashboard/course/16/lesson/335


# スクロールバー

https://kouhekikyozou.com/css_scrollbar_design
zoomのチャットログの余計な部分を削除して議事録として使いやすくした

### ありそうなのに見つからなかった、zoomチャット自動文章整形プログラムをとっとと作る
本日のzoom会議、良いキーワードや参考URLがチャットで流れていたので、編集して議事録つくったろ！
↓
日時とか名前が邪魔で編集しづらいよ！
↓
余計なところはpythonで削除じゃ！！
![2022-03-06 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565176/721a88ac-1349-5faf-9894-88b51826a7d7.png)


```python:cleaner.py
import re
a = open('export.txt', 'w')
with open('meeting_saved_chat.txt','r+') as f:
  for line in f:
        line=re.sub(r'\d\d:\d\d:\d\d....+$', '', line)
        line=line.lstrip()
        a.write(line)
a.close()
```
GoogleColabならすぐに実行可能。めでたしめでたし。
https://colab.research.google.com/drive/1Frvf56C6SWG9HYnz-Q5p3LppSqyn_hfp?usp=sharing

お好きなフォーマットに変えてお使いください。
[Blender]他の人が作ったBlenderファイルをいつもの使い慣れたUIで扱いたい時

# 概要
他の人が作ったBlenderファイルを開いた時、製作者のUI環境も一緒に読み込まれますので使いづらくなる事ってあると思います。
そんな時、使い慣れた自分用のUIに戻す方法があります。
# 本文
File > Open
右上の歯車ボタンを押すと
![スクリーンショット 2023-02-03 7.24.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/bc72d810-9317-5a1d-9ead-344cc7991f1d.png)

項目が表示されるのでLoad UIのチェックを外すと、いつもの使い慣れたUIのままでファイルを開くことができます:sunny:
![スクリーンショット 2022-03-06 17.57.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/6b19f18a-6fbc-49bf-b465-11ca1e98600b.png)
# 補足 1
自分用UIの状態でファイルを保存しなおせば、次回からはチェックを外す操作が必要なくなります。
# 補足 2
上記の方法はFinderなどからファイルをダブルクリックで開いた場合に適用することができません。
Edit > Preferences
![スクリーンショット 2023-02-03 7.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/31249a32-d05d-0f60-c358-0eb18ca585f9.png)
Save & Loadタブ > Load UIのチェックをOFFにすればファイルをダブルクリックで開いた時も常に自分用UIで読み込めるようになります。
![スクリーンショット 2023-02-03 7.15.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/16140b51-82fa-6126-10f1-8ae9ba4fb8a0.png)
DockerによるNext.jsの環境構築

# はじめに
タイトルにある通り、DockerによるNext.jsの環境構築の手順を記載しています。
様々な方の記事も拝読させていただきましたが、create-next-appをルートに展開している例が見つからなかったため、投稿させていただきました。
ルートに展開した理由としましては、heroku等にデプロイする際にpackage.jsonがルートにないと正常にデプロイが完了しないことや、ツリー構造が分かりづらくなるといった観点からです。
しかしながら、苦し紛れな実装になっているため、お詳しい方はコメントでお知らせください。
# Dockerfileの作成
```dockerfile:Dockerfile
FROM node:17.6.0

WORKDIR /usr/src/app

RUN npm install -g npm@latest && npm install create-next-app
```
上記のDockerfileにより実行されるのは、下記の3点です。
1. 公式のnodeイメージを使用
2. 作業ディレクトリを定義
3. create-next-appをインストール

# docker-compose.ymlの作成
```yml:docker-compose.yml
version: "3.9"
services:
  app:
    build: .
    volumes:
      - .:/usr/src/app
    ports:
      - "3000:3000"
    command: bash -c "npm run dev"
```
docker-compose.ymlでは下記を実行します。
1. 先ほどのDockerfileを参照
2. Next.jsアプリケーションを展開するディレクトリにマウントを作成
3. create-next-appのデフォルトのポートに接続
3. 開発モードでの起動

# 環境構築
初めに、イメージのビルドを行います。
```terminal:terminal
docker-compose build
```
次に、create-next-appによりNext.jsアプリケーションを作成します。
展開用のディレクトリにルートを指定すると、Dockerfileとdocker-compose.ymlによりコンフリクトが発生するため、
ここでは一時的にtmpディレクトリに作成し、ルートへ移動しています。
```terminal:terminal
docker-compose run --rm app npx create-next-app tmp --ts\
&& mv tmp/* . && mv tmp/.* . && rm -r tmp
```
:::note info
補足
--tsはTypescriptでのNext.jsアプリケーションの作成を指定しています。Javascriptでの開発を希望される方は、省略してください。
:::

最後に、コンテナを起動します。
```terminal:terminal
docker-compose up
```
[http://localhost:3000](http://localhost:3000 "Create Next App")が正常に起動していれば成功です。
参考までに、本記事の内容のGithubリポジトリも掲載いたしますので、必要な方はご覧ください。

https://github.com/higemegane1992/tone/tree/BuildANext.jsAppWithDocker
エラーハンドリングをどこで行うか。

エラーハンドリングとはエラーが出ることをあらかじめ<b>予測</b>してエラーへの<b>対処</b>をプログラムする処理である。ここでは例外処理と同じ意味で考える。

phpのtry-catchやpythonのtry-exceptにあたります。

外部のapiを使うなど想定外(例外)のエラーが起きそうなところに書くことが多い。
処理の内容は、エラーに対しての復旧やログ出しを行うことが多い。

一方で、エラーハンドリングを適切に行わなければネストが起こり、ログの重複や可読性の低下などが起こる。

例えばこんな書き方をしたことがある。
```python
# controller
def index(request):
    try:
        hoge = Hoge()
        hoge.main()
        # ...
    except Exception as e:
        # サーバーエラーを返す

# Hoge class
def main(self):
    try:
        # 外部apiを叩く処理
    except Exception as e:
        # Log出しやリトライ
       　　# throw　エラー　
```

そこで、エラーハンドリングの最適解を調べた。

# 結論
結論としてはそもそも<b>エラーハンドリングを行わない。</b>

正直エラーハンドリング難しい、駆け出しとしてはそんな難しいことを考えることより一旦書かない結論の方が良いと思います。
本当にtry-catch必要？考え直すことが重要。

理由は起こりうる全てのエラーがキャッチされてしまうから。つまり、便利すぎるが故に扱いづらいと言った感じ？
>本当に信頼性のあるコードを書く方法は、人の典型的な弱さを考慮に入れるシンプルなツールを使うことであって、副作用のあることや、プログラマの無謬性を前提とする漏れのある抽象化を隠している複雑なツールを使うことではない。

引用：[間違ったコードは間違って見えるようにする](https://web.archive.org/web/20120529025524/http://local.joelonsoftware.com/wiki/%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AF%E9%96%93%E9%81%95%E3%81%A3%E3%81%A6%E8%A6%8B%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B)

そうは言ってもフレームワークの都合上使いたい時は以下のようにするとよさそう。

# Good
### スコープを短くする
上記で言ったように例外の理解は難しい。スコープを短くすることで、どの処理がエラーになったか理解しやすくなる。

### 例外の捕捉を細かくする。
引数エラーとdbのデッドロックエラーを同じ例外として捕捉しない。また、捕捉できるような書き方をしない。

### ログを出す。
エラーの原因によって適切な処理が変わる
|エラー原因|UIへの通知|プログラムの流れ|
|--|--|--|
|ユーザー|修正箇所|再操作|
|内部のプログラム|システムトラブル|ログを出す(リトライ or 安全な終了)|
|外部のプログラム|システムトラブル|ログを出す(リトライ or 安全な終了)|

リトライか終了は状況による。
いずれにせよ例外が生じたままプログラムを走らせてはいけない。

### ログの内容。
どこで。なぜ起きたか。エラー内容。を完結に書く。
＊機種依存を避けるため、英語が好ましい

また、ログのレベルを適切に設定することで、緊急度を分ける。

|level| 詳細 |
|---|---|
| CRITICAL  |プログラム自体が実行を続けられないことを表す重大なエラー。 |
| ERROR  |より重大な問題により、ソフトウェアがある機能を実行できないこと。|
| WARNING |動作への影響はないが、問題が起こりそうな時|
|INFO|処理や利用者の情報を残す|
| DEBUG |トラブルの調査用、調査時のみ出力するような設定|

参考：https://docs.python.org/ja/3/howto/logging.html

# BAD
### 例外の握り潰し
エラーが発生した事実が伝わらず、処理が進んでしまう。
ログが出なくなり、不具合の特定が難しくなる。
```python
try:
    # ...
except Exception as e:
    return
```

### 例外を投げる
エラーハンドリングを使いたくないのでそもそもthrowしないでねということ。
従属する処理を全て確認しないといけないので面倒。
エラー情報を格納したオブジェクトをreturnすると良い。

[googleのc++規約](https://ttsuki.github.io/styleguide/cppguide.ja.html#Exceptions)
[「例外」がないからGo言語はイケてないとかって言ってるヤツが本当にイケてない件](
https://qiita.com/Maki-Daisuke/items/80cbc26ca43cca3de4e4)

# 参考
https://applis.io/posts/how-to-design-exception-handling

https://qiita.com/chika_s_it/items/48897c98c8b9749d66b5

https://gakuzzzz.github.io/slides/error_handling_practice/#5
Magentaによるピアノ自動採譜のやり方

## はじめに

Magentaを使ってピアノ演奏の音声ファイル(wavやmp3)からmidiファイルに変換する方法を調べたので、
備忘録も兼ねて記録しておきます。

※MagentaはGoogleが開発しているアート関連の機械学習プロジェクトです。


## 方法

Magentaに含まれる「Onsets and Frames」という機能を使います。
[Onsets and Frames: Dual-Objective Piano Transcription](https://magenta.tensorflow.org/onsets-frames)

具体的な方法としては、3種類の選択肢があります。
- webアプリ
- Colab版
- ローカル環境で実行

以降、それぞれの使い方を記載します。

#### webアプリ
一番お手軽な方法。
こちらのページにアクセスし、目的の音声ファイルをアップロードするだけでmidiファイルに変換してくれます。
[PIANO SCRIBE](https://piano-scribe.glitch.me/)

#### Colab版
以下のColabページでコードを見ながら変換を実行できます。
[Onsets and Frames.ipynb](
https://colab.research.google.com/notebooks/magenta/onsets_frames_transcription/onsets_frames_transcription.ipynb)

ピアノ曲の場合、Select Modelの所で"MAESTRO (Piano)"を選択します。

※自分が試した時は、wavファイルはOKでしたが、mp3では変換できないようでした…。


#### ローカル環境で実行
複数ファイルを一括で変換したりしたい場合はこれがいいと思います。

ここでは、ubuntu20.04（GPU有）環境で確認した手順を記録します。

まず、magentaをインストール。
```
sudo apt-get install build-essential libasound2-dev libjack-dev portaudio19-dev
conda create -n magenta python=3.7
conda activate magenta
git clone https://github.com/tensorflow/magenta.git
cd magenta
pip install -e .
```

次に、以下からMAESTROのcheckpointをダウンロードして適当な場所に保存します。
[(github) onsets_frames_transcription](
https://github.com/magenta/magenta/tree/main/magenta/models/onsets_frames_transcription)

あとは、次のコマンドでcheckpointのパスと目的の音声ファイルを指定すると変換ができます。

```
MODEL_DIR=<path to directory containing checkpoint>
onsets_frames_transcription_transcribe \
  --model_dir="${CHECKPOINT_DIR}" <piano_recording1.wav, piano_recording2.wav, ...>
```


以上です。
複数選択のチェックボックスは順位付きにしないか？

# 順位・順序って大事でしょ

何かと優先順位を付けたがる割に、チェックボックスには順位がない。なもんで、第一希望・第二希望って質問項目を並べて、長ったらしいアンケートになったりする。
と思って、順位付きチェックボックスを作ってみました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27181/a92bdaed-eeb0-096e-6e63-4da900207c83.png)
```php
<?php
	date_default_timezone_set('Asia/Tokyo');
	ini_set('display_errors',1);
	error_reporting(E_ERROR | E_PARSE);
//	error_reporting(E_ERROR | E_WARNING | E_NOTICE | E_PARSE);

	$optionText=array(
		'低価格・ポイント還元',
		'多機能・高機能',
		'シンプルな操作性',
		'デザイン・配色',
		'高級感・ブランドイメージ',
		'耐久性・長期保証',
		'クチコミなどの評判');

	if($_SERVER['REQUEST_METHOD']=='POST'){
	//	選択結果表示
		asort($_POST['chk']);
		foreach($_POST['chk'] as $k=>$v){
			print"{$v}位:{$optionText[$k]}<br />";
		}
	}else{
	//	初回設定
		$_POST['chk']=array();
		array_pad($_POST['chk'],count($optionText),'');
	}

	$n=1;
	if($_POST['chk']){
	//	選択状況設定
		foreach($_POST['chk'] as $k=>$v){
			$checked[$k]='checked';
			$n++;
		}
	}
?>
<script>
const	select_max=3;
document.addEventListener('DOMContentLoaded',function(event){
	let	chkbox=document.getElementsByClassName('chkbox');
	let	checked=new Array();
//	番号リスト
	for(i=1;i<=select_max;i++){
		checked.push(i);
	}
//	使用済み番号の消込
	for(i=0;i<chkbox.length;i++){
		if(chkbox[i].checked && (chkbox[i].value)){
			let	tmp=parseInt(chkbox[i].value)-1;
			delete checked[tmp];
		}
	}
	for(i=0;i<chkbox.length;i++){
		chkbox[i].addEventListener('click', function(event){

			let	nextNum='';
		//	未使用番号の先頭
			for(var tmp of checked.entries()){
				if(tmp[1]){
					nextNum=tmp[1];
					break;
				}
			}
		//	順位番号の設定
			if(event.srcElement.checked && nextNum<=select_max){
				delete checked[nextNum-1];
			}else{
				event.srcElement.checked=false;
				tmp=parseInt(event.srcElement.value);
				checked[tmp-1]=tmp;
				nextNum='';
			}
			event.srcElement.value=nextNum;
			event.srcElement.nextElementSibling.innerHTML=nextNum;
		}, false);
	}
},false);
</script>

<style>
label.check input[type="checkbox"]{
	display:none;
}
label.check span.checkmark{
	display:inline-block;
	height:20px;
	width:20px;
	text-align:center;
	vertical-align:text-top;
	border:1px solid black;
}
</style>

<form method="post">
	重視する点（3つまで）
	<hr />
<?php
	foreach($optionText as $k=>$v){
print <<< EOD
	<label class="check">
		<input type="checkbox" class="chkbox" name="chk[{$k}]" value="{$_POST['chk'][$k]}" {$checked[$k]} />
		<span class="checkmark">{$_POST['chk'][$k]}</span>
		{$v}
	</label>
	<br />
EOD;
	}
?>
	<hr />
	<input type="submit" value="submit" />
</form>
```
openpyxlでエクセルの値を操作する方法まとめ

初心者pythonユーザーの備忘録です。ツッコミどころがあるかもしれませんが何卒暖かい目で見守ってください。誤り等あれば教えていただけると幸いです。

# この記事が役立つかもしれない状況
- excelの値をコピペする操作をpythonで自動化したい
- プログラムの実行結果をexcelに自動入力したい
- excel上の数字を取ってきて処理を行いたい
- とにかくexcelが操作したい
# 使用するライブラリ
openpyxl



# 作業環境
MacBook Air （m１チップ）
os: Monterey ver.12.2.1
python 3.9.7

# 構文
#### エクセルのワークブックを読み込む
- 下の例で「エクセルファイル.xlsx」がwbに代入される
- パスは相対パスまたは絶対パス
```python
wb = openpyxl.load_workbook("エクセルファイル.xlsxのパス")
```
#### 扱うワークシートの指定
- 同一ワークブック内の複数のワークシートのうち、扱うシートを指定する
- 下の例でwbに代入されているワークブック内の「シート1」というワークシートがwsに代入される
```python
ws = wb["シート１"]
```
#### セルの指定
- 指定したシート内の指定した番地（座標？）のセルの値を取得する
- 下の例ではwsに代入されているワークシート内の第a行第b列の値が取得される(a,bは自然数)
- エクセルでは列番号がアルファベットだがcolumnには数字を使用する（A列ならcolumn=1）
```python
ws.cell(row=a,column=b).value
```
同じ構文を使用してセルに数字を書き込んだり書き換えたりすることができる。その場合は処理後のエクセルファイルを新しい名前で保存する。（元のファイル名と同じ名前で保存すれば上書きされる）
```python
ws.cell(row=a,column=b).value=10                  #数字を入力
wb.save("新しい名前.xlsx")                          #保存
```
# その他知っておくと便利な関数
#### エクセルの列番号のアルファベット表記を数字に変換する
- 例えば、エクセルの列番号「CV」は第何列かを調べたい時は下のようにする
```python
print(openpyxl.utils.column_index_from_string("CV"))
```
↓
実行結果
```
>>１００
```
第100列でした。

#### エクセルの第N列のアルファベット表記を取得する
- 上の逆です
```python
openpyxl.utils.get_column_letter(100)
```
↓
実行結果
```
>>CV
```
第100列は「CV」でした。

# 参考
udemyのこちらのコースを参考にしています。実践例も交えて詳しく解説されていてわかりやすいのでおすすめです
https://www.udemy.com/course/python-kaizen/