OmniAICreator/Qiita-1.07M huggingface dataset:
[Grid system]グリッドで要素を横並びにする

画面をコーディングする時に毎回reloadedしてしまうので書いておく
React+bootstrapを使っています

```js
import React from 'react'

const Main = () => {
    return (
        <div className='container mt-4'> {/* ①containerを作成 */} 
            <div className='row'> {/* ②横並びに配置する行を作成 */}
                <div className='col-5'> {/* ③行の中に列を作成して左側に置きたい要素を定義 */}
                    <select className="form-select form-select-sm">
                        <option className="fs-6" selected>今日のおやつは何にしよう</option>
                        <option className="fs-6" value="chiffon_cake">シフォンケーキ</option>
                        <option className="fs-6" value="apple_pie">アップルパイ</option>
                        <option className="fs-6" value="mini_snack_gold">ミニスナックゴールド</option>
                    </select>
                </div>
                <div className='col-4'> {/* ④もう1つ行と右側に置きたい要素を作成 */}
                    <button type='button' className='btn btn-outline-primary fs-6 py-0 mt-1'>決めた！</button>
                </div>
            </div>
        </div>
    );
}
export default Main;
```

![スクリーンショット 2022-11-30 1.31.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530205/4c82da7f-11e6-0be9-e35f-76101443288e.png)

これでもう忘れないはず！
LDAPで快適Linux環境 #6 sudoの設定

この記事は2020年に今は無き別サービスに投稿した記事を、今更Qiitaに再投稿したものです。

[前回](https://qiita.com/zawanume/items/2327c590b983ad454937)はクライアントからLDAPアカウントでログインするところまでいきました。今回はユーザーをごとの権限を管理するために、sudoとLDAPを連携させていきます。

# サーバーの設定
必要なschemaファイルを取り寄せるため、`sudo-ldap`をインストールします。`sudo`が削除されて置き換えられますが、機能に不足は生じません。schemaファイルさえ手に入ればサーバーに`sudo-ldap`は不要になるので、`sudo`をインストールし直してもよいです。
```bash:
root@server:~# apt install sudo-ldap
```

</br>

`sudo-ldap`をインストールすると、`/usr/share/doc/sudo-ldap/schema.OpenLDAP`が生成されます。このままではわかりにくいので、`/etc/ldap/schema`へコピーし`sudo.schema`にファイル名を変更します。

```bash:
root@server:~# cp /usr/share/doc/sudo-ldap/schema.OpenLDAP /etc/ldap/schema/sudo.schema
```

`sudo.conf`を作成し、以下の内容を記述します。

```conf:sudo.conf
include /etc/ldap/schema/sudo.schema
```

これをldifファイルに変換し、サーバーに読み込ませます。

```root:
root@server:~# slaptest -f sudo.conf -F /etc/ldap/slapd.d
```

autofsのときと同様、所有者を`openldap:openldap`に変更します。

```bash:
root@server:~# chown openldap:openldap /etc/ldap/slapd.d/cn=config/cn=schema/sudo.ldif
```

</br>

`sudoers.ldif`を新規作成し、以下の内容を記述します。

```bash:
root@server:~# vi sudoers.ldif

﻿dn: ou=sudoers,dc=example,dc=local
objectClass: organizationalUnit
ou: sudoers

dn: cn=default,ou=sudoers,dc=example,dc=local
objectClass: top
objectClass: sudorole
cn: default
sudoOption: ignore_local_sudoers
sudoUser: ALL
sudoCommand: /sbin/shutdown
sudoHost: ALL

dn: cn=admin,ou=sudoers,dc=example,dc=local
objectClass: top
objectClass: sudorole
cn: admin
sudoOption: ignore_local_sudoers
sudoUser: %admin
sudoCommand: ALL
sudoHost: ALL
```

sudoの設定を格納するために`dc=example,dc=local`の下に`ou=sudoers`を作成します。`ALL`とすることで全てのユーザー、コマンド、ホストをそれぞれ指定できます。`sudoUser`を`%[グループ名]`とするとグループを指定できます。
`cn=default`では、全てのユーザーが全てのホストで`/sbin/shutdown`を実行できるように許可しています。`cn=admin`では、グループ`admin`に所属するユーザーに全てのコマンドを実行する許可を与えています。工夫がここで活きました。
以下のコマンドでサーバーに適用します。

```
root@server:~# ldapadd -x -D cn=admin,dc=example,dc=local -W -f sudoers.ldif
```

# クライアントの設定
クライアントにも`sudo-ldap`をインストールします。こちらは削除してはいけません。

```bash:
root@client:~# apt install sudo-ldap
```

インストールすると、`/etc/sudo-ldap.conf`が生成されます。コメントアウトを解除しつつ、以下を記述します。

```bash:
root@client:~# vi /etc/sudo-ldap.conf

BASE            dc=example,dc=local
URI             ldap://192.168.x.x
sudoers_base    ou=sudoers,dc=exapmle,dc=local
```

`/etc/nsswitch.conf`の最終行に以下のように追記します。

```bash:
root@client:~# vi /etc/nsswitch.conf

sudoers: files ldap
```

</br></br>
これにて完成です。誰かのお役に立てれば幸いです。
MySQL闇歴史　HTTPプラグイン(その後大きな進化！？)

プラグインが追加できるようになったMySQLサーバーに用意された最強クラスの面白プラグインがHTTPプラグイン。RDBMSとの通信にHTTPが使えるようにという発想自体はRESTful世界を考えればなんら問題ない。

知名度：★☆☆☆☆
闇度　：★☆☆☆☆
SQLインジェクション度：★★★★★

このプラグインが面白プラグイン化した最大の原因はURLにSQL文を直接書くというSQLインジェクションどころではない点。
![MySQLDarknessHTTPPlugin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102878/86aba159-51d0-6678-e564-8457b45c150b.jpeg)

もちろん製品版としてリリースされることは無く、実験場であるMySQL Labsに掲載されていただけ。CRUDなAPIやJSONをPOSTすることも視野には入れられていたが、それにしてもSQL文の直書きを実装した段階で世に送り出せた自由な感じが非常に良い。

ちなみにこのプラグインで下地が作られて現在のMySQLドキュメントストアへと進化している、のかもしれない。
MySQL闇歴史　Drizzle

MySQL 6.0で実現できなかった機能の実装やアーキテクチャの見直しを行ったオープンソースのプロジェクトがDrizzleである。旧MySQL社のアーキテクチャだった人物や ~~当時元気~~ だったmixiのエンジニアなどが立ち上げ、2011年3月に正式リリース。
https://www.publickey1.jp/blog/11/mysqldrizzle_1.html


知名度：★★★☆☆
闇度　：★★★☆☆
霧雨のように消えていった度：★★★★★

マイクロカーネル的なアーキテクチャを採用したり、Web系サービスで必要な機能のみを実装。レガシーな感もあるストアドプロシージャなどを廃したのは分かるが、性能のオーバーヘッドを排除するためにアクセス制御機能を捨てて他の仕組みでデータ保護をしろという大胆すぎる発想だった。レプリケーションのメッセージはGoogleのProtocol Buffersのライブラリを使っていたためMySQLだけでなくApache Cassandraなど対してもレプリケーション可能になる可能性があったとか。

2013年末までには新規開発をしないメンテナンスモードとなり、2016年にプロジェクト終了となった。
MySQL闇歴史　MySQL 5.2, 6.0, 6.x

MySQLが最も迷走していたであろう時期に開発が進められていたメジャーバージョン。どちらも製品版になることはなく消滅。いまでもソースコードはミラーサーバーなどからダウンロードできるようになっている。

知名度：★★★☆☆
闇度　：★★☆☆☆
迷走度：★★★★★

FalconやMyISAM++に加えてサードパーティー製のストレージエンジンが乱立し、また旧MySQL社のチームも創業者と別のアーキテクトがそれぞれ方針を立てたりなど迷走、さらにSunがMySQLチームに送り込んだ役員的な役割の人も混乱に拍車をかけていた時期に複数のメジャーバージョンの開発が並行して走る状態に。当然バージョン間での整合性は取れずリソースも分散する事態に。

5.2の一部は5.4を経て5.5としてリリース、6.0は夢のあるロードマップは描いていたがプロジェクトとしては消えていった。6.0ではMyISAMは物理バックアップして他は論理バックアップを取りつつ、DMLをブロックすることないバックアップ機能が実装されるはずだった。こう書いてるだけでも危険な匂いしかしない。

6.0のGAは2008年10-12月にリリース予定と発表されていたがあえなく消滅。6.xを半年後にリリースしようとしていたが、6.1には全ストレージエンジンの外部キー対応、各種性能改善などが挙げられていた。いまのMySQLで実現しているものとしては6.0で計画されていたオンラインDDLでの列追加、6.xで計画されていたパフォーマンススキーマなどがある。

どうでもいいけど未だにオラクルのサイトでMySQL 6.0のリファレンスマニュアルが公開されているのは意外すぎた。
https://docs.oracle.com/cd/E19957-01/mysql-refman-6.0/index.html
MySQL闇歴史　MySQL Cluster(いまはつよつよな製品)

MySQL Clusterといえばミッションクリティカルなシステムで使われる分散型のデータベースクラスター。全ノードがアクティブで単一障害点がなく、スケールアウト型でサーバーを追加すればほぼリニアに性能が伸びる製品である。通信基盤やガチでミッションクリティカルな軍事防衛システムなどでの採用が多い。

知名度：★★★★☆
闇度　：★☆☆☆☆
あの頃はガチでひどかった度：★★★★★

ところが闇歴史として取り上げるには理由がある。元々はスウェーデンの通信機器メーカーであるエリクソンの子会社で開発されていたNetwork Database(NDB)を2003年に旧MySQL社が買収してMySQLサーバーのストレージエンジンとして組み込み、MySQL Clusterと名付けて製品展開した。MySQL 4.1の頃から利用できることはできたがあまり利用者はいなかったように思われる。

状況が変わったのがSunによるMySQL買収。当時のSunの営業担当者の中には買収したMySQLの製品で一番エディションだから高いからというだけでMySQL Clusterを売ろうとし、実際に売っちゃったけど要件に合わなくてトラブルとなり返金するしないなどの騒動になったことも数多く。。。

独自のバージョン番号が与えられていた時代の6.xぐらいまでは製品の品質が悪くてじゃじゃ馬のような製品だった。観測範囲では日本での最初の採用事例は某大手メディア企業が周年記念事業のWebサイトだが、起動すらままならず何かを修正してもまた別のバグを踏むという地雷原のようなソフトウェアだった、と当時の担当者は振り返る。
その後、日本のとあるお客様での案件で大トラブルとなり、スウェーデンから開発エンジニアが呼び出されて思いっきり怒られたのを契機に、製品テストをガチで大幅に改良したことでいまでは非常に良い製品となっている。
MySQL闇歴史　solidDBストレージエンジン

これを書いている人のお気に入りだったストレージエンジンがsolidDBストレージエンジン。2006年に当時ミッションクリティカルなシステムで利用されていると言われていたSolid Information Technology社のデータベースをMySQLのストレージエンジンとして作り上げたもの。

知名度：★☆☆☆☆
闇度　：★★★☆☆
個人的残念度：★★★★★

トランザクション対応であり、バイナリログを使わすにストレージエンジン独自のレベルでのレプリケーションが可能という画期的なストレージエンジンとして開発が進められていた。GAリリース前の段階でも更新処理性能が結構高く、将来が期待されるストレージエンジンであった。SourceForgeに現在もソースコードが公開(放置)されている。
https://sourceforge.net/projects/soliddb/


solidDBの開発元はサン・マイクロシステムズによる旧MySQL社買収直前の2007年にIBMに買収され、SunによるMySQL買収から程なくしてストレージエンジン開発は中止されてしまった。
MySQL闇歴史　MyISAM++ストレージエンジン

Falconストレージエンジンと時を同じくして始まったプロジェクトがMyISAM++ストレージエンジン。名前の通り軽量高速なMyISAMストレージエンジンを改良してみんなが欲しかった夢のストレージエンジンを作るプロジェクトである。2007年に開発を開始し2009年末にはトランザクションとオンラインバックアップをサポートすると宣伝していた。

知名度：★☆☆☆☆
闇度　：★★★★☆
その後どうなった度：★★★★★

クオーテーション付きで"MyISAM++"でググっても、それMyISAMのことやろ、とグーグルにも言われるレベルでの知名度。ちなみにその後、名称がMariaストレージエンジンになりさらにMが外れてAriaストレージエンジンとして現存。

MyISAM++の開発当初はACIDなトランザクション対応のストレージエンジンにするぜと豪語していたはずが、あっという間に目標がしょぼくなっていって「クラッシュセーフなMyISAM」にすることに落ち着いたらしい。古くからの流れを知る中の人からすればいつものパターンね、という感想しかない。

当時の利用者側からするとFalconとMyISAM++のどちらを将来的に選択すればいいか分からず悩ましかった。InnoDBの開発が継続され、大幅に進化したことでMySQLのトランザクション対応ストレージエンジンはやっぱりInnoDB、という結論に。
[UiPath]Excelの各列を繰り返す

# UiPathでExcelの各列を繰り返したいが適切なアクティビティが見つからない
UiPathを使っているとExcelアクティビティの中に「各行を繰り返す」アクティビティはあるが、各列を処理する専用のアクティビティは存在しない。

## UiPath.Excel.Activities 2.6.1の現状のアクティビティ群
著作時点での最新のExcelアクティビティパックを確認してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707463/7141e78d-2151-ddb2-4d98-f8a887694795.png)

この時点でも「各列」を繰り返すアクティビティはないように見える

## Excelで各列を処理したいケースがある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707463/60a42663-2c4b-56eb-9ed4-7d0c535912be.png)
このようなExcelの各要素を順番に処理したいケース
「繰り返し (Excel の各行)」を使うと　`currentRow("1月").toString` というような書き方で12回書かなくてはならない。また、列名が動的に変わる場合に固定の列名にすると対応できない。

UiPathで順番に繰り返すのは専用アクティビティが存在しない。
もちろんロジックを組めば出来る。今回はこのロジックの一例を示したい。

## 実装例
まずは、対象範囲をdatatable型で読み込む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707463/0e1d0df4-8c7c-6479-a15d-ac66b23da68f.png)

その後、「繰り返し (Excel の各行)」アクティビティと合わせて、「繰り返し（コレクションの各要素）」を利用する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707463/720df18f-02a7-4253-7f66-78a2f2cdb1d1.png)

今回は表示内容を以下のように出力している。
`行(列.ToString).ToString`

「繰り返し（コレクションの各要素）」の`TypeArgument`は以下の通りにする。なお、Windowsレガシーの場合はTypeが違う可能性があるので要注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707463/47f6ff56-94a6-b347-5bd5-c99594760ecc.png)
MySQL闇歴史　Falconストレージエンジン

2005年のInnobase買収でトランザクション対応ストレージエンジン消滅の危機を迎えた旧MySQL社が開発に取りかかったのがFalconストレージエンジン。InterBaseやオープンソースデータベースのFirebirdの生みの親であるJim Sterkeyを旧MySQL社に迎え、新たなトランザクション対応のストレージエンジンを目指した。そう、目指した。

知名度：★★☆☆☆
闇度　：★★★★☆
はずだった度：★★★★☆

InnoDBよりも新しい設計で同時実行性能が高いと宣伝されていた。MVCCをサポートし、InnoDBのようなクラスターインデックスではないので構造的に性能が出る(はず)で、さらにオンラインのDDLサポートなど、みんなの夢の詰まったストレージエンジンとして設計されるはずだった。そう、はずだった。

2008年の6月に設計担当のJimは軽やかにMySQLから去って行った。
http://blog.kimuradb.com/?eid=662231
その後のFalconの開発動向を知る人は少ない。ちなみにJimが設立したNuoDBは2020年にフランスの航空防衛系の製造企業グループ・ダッソーのソフトウェア子会社に買収されたらしい。
MySQL闇歴史　SleepycatとBerkeley DB

2000年8月9日に旧MySQL社とSleepycat Software社が共同でトランザクション対応のRDBMSとして「MaxSQL」の開発を発表。MaxSQLであってMaxDBではない。そのMaxSQLの行く末を知るものは数少ない。

知名度：★★☆☆☆
闇度　：★☆☆☆☆
買収あっさり度：★★★★☆

SleepycatはオープンソースのデータベースBerkeley DB(BDB)の開発元としても知られており、MySQLのストレージエンジンとしてBDBを提供していた。
SleepycatはInnobaseと同様に2006年にオラクルに買収されたが、Innobaseの買収時とは異なり大した騒ぎにならないという悲しい展開。5.1.12にてBDBストレージエンジンのサポートが中止された。当時のMySQL開発チームのアーキテクトにも「BDBのユーザーは片手の指で数えられるほどだろう」とか言い放たれる悲しい流れに。


ちなみにBDBはSendmailやSpamassassinに組み込まれていたほか、いまはオラクルがAGPLと商用ライセンスのデュアルライセンスにて提供中。最新版の18.1.40がリリースされたのが2020年5月と開発動向が気になるところではあるが、2016年に金融情報会社のBloombergがフォークとしてComdb2というDBを作成。SQLパーサーはSQLiteでバックエンドストレージとしてBDBを使っているらしい。
https://bloomberg.github.io/comdb2/overview_home.html
NextCloudのパーミッションエラー回避

こんな感じでNextCloudをk8sにデプロイするとします。

<div class="toc"><details><summary accesskey="c">nextcloud.yaml</summary>

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextcloud
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nextcloud
  template:
    metadata:
      labels:
        app: nextcloud
    spec:
      containers:
        - name: nextcloud
          image: nextcloud
          env:
          - name: NEXTCLOUD_DATA_DIR
            value: /data
          ports:
            - containerPort: 80
              protocol: TCP
          volumeMounts:
          - name: myvolume
            subPath: config
            mountPath: /var/www/html
          - name: myvolume
            subPath: data
            mountPath: /data
      volumes:
        - name: myvolume
          persistentVolumeClaim:
            claimName: myvolume
      securityContext:
        fsGroup: 33
---
apiVersion: v1
kind: Service
metadata:
  name: nextcloud
  namespace: default
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
  selector:
    app: nextcloud
  clusterIP: None
```

</details></div>


すると初回ログイン後に以下のようなエラーが出てきます。

```
データディレクトリ (/data) は他のユーザーも閲覧する事ができます。
ディレクトリが他のユーザーから見えないように、パーミッションを 0770 に変更してください。
```

基盤側の都合でパーミッションを変えられないケースの回避策(無理矢理)を紹介します。


a. `/var/www/html` をPersistentVolume (ex. `/config`) に永続化している場合

PersistentVolume (`hdd1`) を適当なインスタンスにマウントし、以下のファイルをエディタで編集します。

`/config/lib/private/legacy/OC_Util.php`

```php
...
	public static function checkDataDirectoryPermissions($dataDirectory) {
		if (\OC::$server->getConfig()->getSystemValue('check_data_directory_permissions', true) === false) {
			return  [];
		}

		$perms = substr(decoct(@fileperms($dataDirectory)), -3);
-   	if (substr($perms, -1) !== '0') {
+       if (substr($perms, -1) !== '7') {
- 		chmod($dataDirectory, 0770);
+ 		chmod($dataDirectory, 0777);
...
```

b. `/var/www/html` を永続化していない場合

Deploymentのlifecycle.postStartでパッチしてしまいます。

`nextcloud.yaml`

```yaml
...
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "sed -i -e 's/xxx/XXX/g' /var/www/html/lib/private/legacy/OC_Util.php "]
...
```

書いておいてなんですが、全くもっておすすめできる方法ではありません。
MySQL闇歴史　Innobase Oy

MySQLのデフォルトのストレージエンジンといえばInnoDBだが、元々は旧MySQL社(MySQL AB)とは別会社のInnobase Oyというフィンランドの会社が開発していた。2002年2月28日リリースのMySQL 3.23.49からMySQLに同梱される安定版として提供されるようになった。

知名度：★★★☆☆
闇度　：★★☆☆☆
裏話盛り上がり度：★★★★★

MySQLの歴史上の大事件の一つが2005年10月7日にこのInnobaseがオラクルに買収されたこと。

オラクルが買収後にInnoDBの開発停止やMySQLへの提供を取りやめていれば、当時のMySQLは他にまっとうなトランザクション対応のストレージエンジンがなかったためRDBMSとしては死活問題になり得た。なおMySQL ABとInnobase Oyとの間に「複数年契約」が存在していたこともあり数年間は同様の形態での連携が継続は確実だったが、その後のこの「複数年契約」の更新時に契約が打ち切られるかどうかはかなり不安が残っていた。この契約が無事に自動更新された際のお祭り騒ぎについては当時の中の人を飲ませるとめいっぱい語ってくれる、かもしれない。

買収半年後のMySQL User Conference 2006でのInnoDBのプレゼンテーションのテンプレートが当時のオラクル社のテンプレートから右下の会社ロゴ部分を変更しただけのものになっていて、買収を実感させられて衝撃だった。Q&Aのスライドも当時のオラクル社のスライドそのまま。
![MySQLUC2006InnoDB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102878/239dc138-159a-f3b3-64bb-e6f104a8e8a6.png)


ちなみにオラクルになってからのInnobaseのメンバーはInnoDBストレージエンジンを第2世代のプラグイン版に更新してファイルフォーマットもbarracudaを導入するなどそれとなく開発を継続。いつ頃変わったのかは調べきれなかったがMySQL User Conference 2009のInnoDBプレゼンテーションのテンプレートは青基調のInnobase独自のものだった。Q&Aのスライドも色が変わっていた。
![MySQLUC2009InnoDBQA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102878/682d25de-cf2f-2c39-6757-adf4dd2da538.png)


最後のページは”an Oracle Company"の赤字のところが逆に目立つけど。
![MySQLUC2009InnoDB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102878/b9ef1bc9-2c2c-e82b-1e44-80940c9f7fb0.png)
ここにも載っているように知名度ほぼゼロなEmbedded InnoDBなる製品の開発もしていたらしい。2009年にはオラクルがEmbedded InnoDBに関するプレスリリースを打った形跡も。保管していたEmbedded InnoDBのソースコードをGitHubに上げている人もいるようなのでご興味があればぜひ。

2010年にMySQLの開発チームが買収によってオラクルの一部になるまで、オラクルがMySQLのトランザクション対応ストレージエンジンを提供していた形だったのは意外と知れていないのかもしれない。
macfanctldでMacサーバのファン制御

この記事は2020年に今は無き別サービスに投稿したものを、今更Qiitaに再投稿したものです。

SSD換装したり無理やりMojaveにしたりしていたMacサーバは、現在Mojaveでの運用を諦めDebianをインストールしMinecraftのマルチプレイサーバなどに活用している。
コロナ禍での休校期間中、後輩たちが筆者宅のMinecraftマルチプレイサーバーにログインして遊ぶ頻度が上がった。そのサーバーとは例のオンボロMac mini(late 2009)であって、11年前のCore 2 Duoがまだ現役なのである。
そんなことはお構い無しに、後輩たちはネザーを探索し、エンドシティを探し、ゾンビトラップ、ゴーレムトラップまで作って放置プレイをしているのである。トライデント量産トラップまで設置された。そうするとラグが酷い。`top`で覗いてもswapが発生しているわけでもない。しかし気になったのが、CPU使用率がさほど上がっていない点だ。熱を持っていてクロックを上げられないのではという仮説を立てた。サーバーの筐体を触ってみると、ホカホカであった。

# 温度を調べたい
CPU温度を調べるにはパッケージ`lm-sensors`を入れれば良いということだったので導入する。

```bash:
$ sudo apt install lm-sensors
```

</br>
コマンド`sensors`で検出されたセンサーの温度が表示される。どれがどこを指しているのかは分からなかったが、`Core 0`と`Core 1`がCPU温度を示していることは容易に理解できた。Minecraftサーバーを起動して誰もログインしていないときに50℃弱、高負荷時には70℃を超えていた。

一つだけ単位が「RPM」になっている項目があった(他は℃)。Mac miniはファンを一つだけ搭載しているのでこれは間違いなくそのファンの回転数である。問題は、高負荷、高温時にもファンの回転数が上がっていないことである。常に毎分2000回転であった。ファンの回転数をどうにか上げたい。

# fancontrolを試す
いろいろ調べていくと`fancontrol`を使えばいいという情報が目立った。
```bash:
$ sudo apt install fancontrol
```

</br>

`pwmconfig`で温度センサーとファンの関連付けをするとのことだったが、どうもうまくいかない。
他の方法は無いかとMac向けのパッケージが無いか等を調べていたら、`macfanctld`を見つけた。

# macfanctld
`apt search`で出る概説だと、Macbook用のファンコントロールデーモンとのことだったがとりあえず入れてみる。

```bash
$ sudo apt install macfanctld
```

</br>

インストールするとデーモンが起動し、しばらくファンの回転数が上がってうるさくなる。
`/etc`に`macfanctld.conf`という設定ファイルが作られている。最低回転数、回転数が最低・最高になる温度が設定できる。
常に2000回転だと気になるので最低は1500回転にした。Minecraftを起動した際の負荷等条件を変えて検証し、以下の設定に落ち着いた。ログを取るには`log_level`を設定しておく必要がある。

```
# Config file for macfanctl daemon
#
# Note: 0 < temp_X_floor < temp_X_ceiling
#       0 < fan_min < 6200       

fan_min: 1500

temp_avg_floor: 50
temp_avg_ceiling: 60

temp_TC0P_floor: 55
temp_TC0P_ceiling: 70

temp_TG0P_floor: 55
temp_TG0P_ceiling: 70

# Add sensors to be excluded here, separated by space, i.e.
# exclude: 1 7
# will disable reading of sensors temp1_input and temp7_input.

exclude: 8

# log_level values:
#   0: Startup / Exit logging only
#   1: Basic temp / fan logging
#   2: Log all sensors  

log_level: 1
```

</br>
設定を変更したら、デーモンを再起動する。

```bash:
$ sudo systemctl restart macfanctld
```

</br>

センサーの例外処理についてだが、`sensors`を実効したときに常に-128℃を示すセンサーがあり、どうやらこのデーモンはセンサーの平均温度を見ているようで、除外したほうがいいと考えた。
`head`を使い`/var/log/macfanctl.log`の先頭付近をみていくと、`sensors`を実行したときのセンサー名と`macfanctld`での通し番号の対応が分かる。

# 夏を乗り切れるか
最近のMinecraftはちゃんとマルチスレッドに対応しているようだ。同時にネザーやらエンドやらに行かれるとデュアルコアではしんどい。誰かがログインして負荷がかかる作業をするとファンの回転数が上がるのですぐに分かる。4500回転ほどになることもある。ノートPCに比べるとMac miniのファンは結構うるさい。
11年落ちCore 2 Duoなんかよりも最近のラズパイの方がよほど高性能だ。64bit対応し、8GBメモリモデルもある。これからの季節、暑い日に古いCPUを高負荷で使い続けると逝ってしまわないか心配である。新しいサーバーが欲しいが、身分が安定してからにしよう。
MinecraftのチャットとDiscordが連携できるらしい

この記事は2020年に今は無き別サービスに投稿したものを、今更Qiitaに再投稿したものです。

# 「rcon」って何に使うのだろうか
Minecraftのサーバーのバージョンを更新して`server.properties`を見直していた際に、`enable-rcon`という項目を発見した。気になったので、「Minecraft rcon」でググってみた。そこで見つけたのが、**Minecord**だ。もりやませーたさんという方が作り、MITライセンスで公開されている。どうやらNode.js製のサーバーで、そこからMinecraftサーバーのrconを利用してDiscordのチャットを流しているということなのだろうか。

# 早速導入
もりやませーたさんのブログ、「[ModなしでMinecraftサーバーとDiscordを連携するツールを作った](https://s8a.jp/connects-minecraft-and-discord-minecord)」を見て、その通りに進めていく。

進めていく前に、実行には当然ながらNode.jsの環境が必要である。また、Minecordはnpmからインストールする。私が使っている環境はDebianなので、`apt`を使ってパッケージ`nodejs`,`npm`をインストールした。
```
~$ sudo apt install nodejs npm
```
依存関係を満たすために上記の2つ以外に大量のパッケージがインストールされる。こうしてようやく作者さんのブログの通りに進めていく。
Debianにおいてnpmでパッケージをインストールすると、デフォルトでは`/usr/local/bin`にシンボリックリンクができるはずだ。

# デーモン化
ターミナルから実行するのでは不便なので、systemdでデーモン化する。
`/etc/systemd/system`に`minecord.service`を作成し、以下のように記述する。
```
[Unit]
Description=minecord
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/minecord --config /home/hoge/minecraft_server/config.json
WorkingDirectory=/home/hoge/minecraft_server
KillMode=process
Restart=always
User=hoge
Group=hoge

[Install]
WantedBy=multi-user.target
```
`ExecStart`,`WorkingDirectory`はどこに`config.json`を置いたかによって適宜変更する。

```
~$ sudo systemctl start minecord
```
で実行できる。
```
~$ sudo systemctl enable minecord
```
で起動時に自動実行されるようになる。

# 日本語でチャットできる

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370590/667519ec-947b-8a30-f422-0b305d5a90c2.png" width=７5%>

Minecraftに備わっているチャット機能は日本語入力に不向きであったが、これで解決。手元にスマホを置いてそこでチャットしても良し。後輩たちからもとても好評であった。作者に多大なる感謝と敬意を表したい。
MySQL闇歴史　MaxDB

MySQLのMyが創業者の一人の長女の名前から、MariaストレージエンジンのMariaが次女の名前から取られていることは割と知られているが、Maxが長男の名前だというのは忘れられがちなのがMaxDBである。

知名度：★☆☆☆☆
闇度　：★☆☆☆☆
現存してて驚いた度：★★★★★

MySQLに古くから関わっている人たちこそ驚くかもしれないが、MaxDBの最新版として2022年9月にVersion 7.9.10.08がリリースされている。


MaxDBはもともとSAPで(正確にはSAPが買収したSoftware AGで)開発されていたSAP DBが、2003年に当時のMySQL社との提携でMaxDBという名称となりMySQL社製品としてGPLで公開および販売されていた。しかし2007年に再度SAP単独で販売するクローズドソースの商用製品となり現在はSAP MaxDBが正式名称となっている模様。


- MaxDBバージョン情報
https://maxdb.sap.com
- MaxDB日本語ドキュメント
https://help.sap.com/doc/saphelp_nw70/7.0.12/ja-JP/07/595f51b1889b478869e338198171b5/frameset.htm
Ubuntuにてgccgoを使ってアセンブリ

go + nasmを使ってみたかったのでサンプルのhello worldを出力してみました。

参考はこちら（12年前の投稿だけど）：

https://stackoverflow.com/questions/2951028/is-it-possible-to-include-inline-assembly-in-go-code

バージョンがいろいろ狂っているので、ちょっと直したいところです。

```bash
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.7 LTS
Release:	16.04
Codename:	xenial

$ sudo apt-get -y install golang
$ go version
go version go1.6.2 linux/amd64 #古すぎな

$ sudo apt-get -y install nasm
$ nasm -version
NASM version 2.11.08

$ sudo apt-get -y install gccgo
$ gccgo --version
gccgo (Ubuntu 6.0.1-0ubuntu1) 6.0.0 20160414 (experimental) [trunk revision 234994]
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

確認のために肝心のhello()を2回一応呼び出す。

```main.go
package main

func hello();

func main() {
    hello()
    hello()
}

```

こちらはhello worldのサンプルでもあるアセンブリファイル

```hello.asm
; based on hello.asm from nasm

    SECTION .data       ; data section
msg:    db "Hello World",10 ; the string to print, 10=cr
len:    equ $-msg       ; "$" means "here"
                ; len is a value, not an address

    SECTION .text       ; code section

global main.hello        ; make label available to linker (Go)
main.hello:

    ; --- setup stack frame
    push rbp            ; save old base pointer
    mov rbp,rsp   ; use stack pointer as new base pointer

    ; --- print message
    mov edx,len     ; arg3, length of string to print
    mov ecx,msg     ; arg2, pointer to string
    mov ebx,1       ; arg1, where to write, screen
    mov eax,4       ; write sysout command to int 80 hex
    int 0x80        ; interrupt 80 hex, call kernel

    ; --- takedown stack frame
    mov rsp,rbp  ; use base pointer as new stack pointer
    pop rbp      ; get the old base pointer

    ; --- return
    mov rax,0       ; error code 0, normal, no error
    ret         ; return

```

Makefileは以下。

```Makefile
main: main.go hello.o
	gccgo hello.o main.go -o main

hello.o: hello.asm
	nasm -f elf64 -o hello.o hello.asm

```

以下のように出力されるはず。

```
$ make
$ ./main
Hello World
Hello World
```
MySQL闇歴史　「商用利用」向けライセンス(廃止済み)


MySQLの普及にとってマイナス要因だったのが「商用利用」という曖昧な文言。「商用利用」の場合にはライセンス買ってね、というビジネスモデルがその昔はあった。「商用利用」が明確になされていなかったので利用者側が困る場面も多かった。

知名度：★★★★☆
闇度　：★★★★★
迷惑度：★★★★★

2000年6月には独自のライセンスから現状に近いGPLと商用ライセンスのデュアルライセンスに切り替わったが、特に日本ではこのGPLに対する理解の広がりが遅れたことや「GPL汚染」などという言葉が広まったこともあり、変更後のMySQLのデュアルライセンスの正確な定義がなかなか浸透しなかった感がある。っていうか2022年にもなってMySQLを商用利用するならライセンス買わなきゃダメとか書いてるアホなブログや情報サイトがあってうんざりする。

しかしこの話の最大の闇はそこではない。デュアルライセンスに移行した後も当時のMySQL社の営業担当者の中にこの曖昧な「商用利用」の定義をお客様に誤解させるような説明をしてライセンスを売りさばこうとした輩がいたことだ。
営業担当者は法務の専門家ではないのでライセンスの解説を行うことは本来会社としては許されていなかったし、利用者もどのようなソフトウェアライセンスであっても他人に判断を任せず正確に理解をすべきではあるのだが。。。
アドベントカレンダー初参加する

[アドベントカレンダー初参加する人を応援したい、アドベントカレンダーに参加したきっかけ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/sanka-kikkake)
１８日目の記事です。
# 自己紹介
こんにちは。
ある大学の２年生です。今年初参加です。
## 今年参加するカレンダー
[【個人チャレンジ】初心者が25日で強くなる Advent Calendar 2022](https://qiita.com/advent-calendar/2022/aruhitoganbaru)

[クソアプリ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kuso-app)
そして、ここのカレンダー
[アドベントカレンダー初参加する人を応援したい、アドベントカレンダーに参加したきっかけ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/sanka-kikkake)
この３つです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/47e7c1b7-57f5-339c-fffe-f3b8d967df2a.png)
今年初参加なのにカレンダー完走を狙います
## 参加したきっかけ
11月26日ごろ、twitterを見てたらたまたまこのアドベントカレンダーに関する投稿が流れてきたので参加してみました。
私は恥ずかしがり屋で自分の意見も言えないような人だったので、初めは不安でした。
でもせっかくだから参加してみようという好奇心が、自分の内気な性格に勝りました。なのでやってみることにしました。後、完走賞がもらえると聞いたので。

## 記事の投稿
最初（１日目）は、とても緊張しました。
やっぱりやめようと思ったりもしたけど、最終的にはちゃんと投稿できました。
「初心者の書く記事なんて見ないだろう」と思ったけど、たった半日で100viewを超えていて、自分に自信が持てました。今ではもう、恥ずかしい気持ちなく投稿できるようになりました。

# 今後どうしたいか
さらに自信をつけられるようにできる限り記事を投稿していきたいと思います。

これからよろしくお願いします。
不要なワークフローの実行結果をGitHubのActionsタブから永遠に消し去る方法

# この記事で削除するもの
GitHubのActionsタブを開いたときに左側に表示されるワークフローを消します。
ワークフローは実行された記録が1つでも残っていると左側に常に名前が表示されてしまい、もう不要になったワークフローであっても簡単に消すことができません。

今回はGitHub CLIを使って、サクッと削除していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652652/35b17f67-85b4-3fdc-299b-b920da0f1a4b.png)


## 必要なもの
- gh （[GitHub CLI](https://cli.github.com/)をインストール）
- jq （jq インストールとかで検索すると各OSごとのインストール方法が見つかる）

## ワークフローの実行結果を一発で削除する方法
変数を書き換えてコマンドを叩くとワークフロー名がActionsタブから消えます。
多少強引だけど、ワンライナー。
```
OWNER=me
REPO=myRepo
WORKFLOW_FILE_NAME=my_workflow.yml

gh api \
  -H "Accept: application/vnd.github+json" \
  /repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_FILENAME/runs \
| jq '.workflow_runs[].id' \
| xargs -I RUN_ID \
gh api \
  --method DELETE \
  -H "Accept: application/vnd.github+json" \
  /repos/spine-lab/codmon/actions/runs/RUN_ID
```
[参考: List workflow runs for a workflow](https://docs.github.com/ja/rest/actions/workflow-runs#list-workflow-runs-for-a-workflow)
[参考: Delete workflow run logs](https://docs.github.com/ja/rest/actions/workflow-runs#delete-workflow-run-logs)


# 解説

## 準備： 必要な情報をshell変数に入れる
削除するために必要な情報は`OWNER`, `REPO`,`WORKFLOW_FILE_NAME`の3つです。
もしActionsタブから削除したいワークフローが`me/myRepo/.github/workflows/my_workflow.yml`というファイル名だった場合は、下記のような値を入れます。
```
$ OWNER=me
$ REPO=myRepo
$ WORKFLOW_FILE_NAME=my_workflow.yml
```

## ワークフローのRUN_IDを取得する
Actionsタブからワークフローを削除するには、対象のワークフローの実行結果をすべて削除する必要があります。実行結果を削除するにはRUN_IDを指定しなくてはいけません。
まずは、GitHub CLIを使って、RUN_IDを取得していきましょう。
```
$ gh api \
  -H "Accept: application/vnd.github+json" \
  /repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_FILENAME/runs \
```
json形式のレスポンスが得られたら成功です。

しかし、json形式のままだと扱いづらいので必要な情報だけを抽出していきます。
先程と同じコマンドでjsonを取得したあと、パイプ(|)を使ってjqの標準入力にjsonを流し込みます。
```
$ gh api \
  -H "Accept: application/vnd.github+json" \
  /repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_FILENAME/runs \
| jq '.workflow_runs[].id'
```

すると今度はRUN_IDだけが表示されるはずです。

### 実行結果を削除する
まずは安全のために、RUN_IDの部分を任意のIDに書き換えて実行してみます。
GitHubのActionsタブで消したいワークフローを開いておき、コマンド実行後に実行結果が1つ消えることを確認しましょう。
```
gh api \
  --method DELETE \
  -H "Accept: application/vnd.github+json" \
  /repos/spine-lab/codmon/actions/runs/RUN_ID
```

次に、複数の実行結果をまとめて一気に消すにはxargsを使います。
`-I`オプションで適当な名前を決めたら、ghコマンドの一致する部分に標準入力で受け取った値を流し込んでくれる便利なコマンドです。
準備でshell変数を設定していたら、`$OWNER`, `$REPO`, `$WORKFLOW_FILENAME`は勝手に値が入るのでそのまま実行して大丈夫です。
```
$ gh api \
  -H "Accept: application/vnd.github+json" \
  /repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_FILENAME/runs \
| jq '.workflow_runs[].id'
| xargs -I RUN_ID \
gh api \
  --method DELETE \
  -H "Accept: application/vnd.github+json" \
  /repos/spine-lab/codmon/actions/runs/RUN_ID
```

最後にGitHubのActionsタブを見に行きましょう。
左側に表示されるワークフロー名の一覧から消えているはずです。
Azure Firewallの実装手順とDNAT(宛先ネットワークアドレス変換)規則

●Azure Firewallの実装手順
１、ネットワークインフラストラクチャの作成
２、Azure Firewallのデプロイ
３、ルートテーブルの作成とサブネットへの関連付け
４、ファイアウォールポリシーおよび規則の作成

※Azure Firewallの配置先となる仮想ネトワークのサブネット名は「AzureFirewallSubnet」、アドレスプレフィックスは/26以下である必要がある

●DNAT(宛先ネットワークアドレス変換)規則
ファイアウォールのパブリックIPアドレスとパブりｋっクポーとを、特定のプライベートIPアドレスとプライベートポートに変換する。そのため、仮想マシンが使用するIPアドレスを隠蔽しつつ、RDPやSSHを許可したい場合や、HTTP・HTTPS以外を使用するアプリケーションアドをインターネットに公開する場合に役立つ
MySQL闇歴史　プロローグ

MySQLも開発開始から25年以上が経ち、過去の歴史的経緯を知らないユーザも続々と増えている製品となってきている。そこでMySQLの闇の部分の歴史をまとめて供養してみようと思う。

この手の歴史の話だと色で表すことが多い気がするが昨今の情勢を考えるとポリコレ棒でぶん殴られそうなのであえて闇歴史にしてみた。深い意味はない。

各回に独断と偏見で3種類の項目で5段階評価を付けてみる。こちらも深い意味は大してない。

初回は軽めのお話から。

# タイトル：いつの間にか闇に消えていったMySQL Forge

知名度：★★☆☆☆
闇度　：★☆☆☆☆
もったいない度：★★★★☆

MySQL ForgeはMySQLコミュニティ向けのポータルを目指していたサイトで、MySQL周辺のオープンソースプロジェクトやツール類、プレビュー版のソフトウェア、Wiki, Worklogなどが掲載されていた。2006年に当時元気だったSourceForgeのMySQL版のようなポジションを目指していた。
http://forge.mysql.com/ (現在はmysql.comのトップページにリダイレクトされる)


ストレージエンジンだけでも様々なプロジェクトが掲載されていたり、現在のMySQL Routerの前身となったMySQL Proxyも長らくMySQL Forgeに掲載されていたプロジェクト。
https://web.archive.org/web/20060821031718/http://forge.mysql.com/

日本からも野村総合研究所がOLAPツールを掲載してアクセスランキングの最上位にいたことも。
https://xtech.nikkei.com/it/article/NEWS/20060530/239495/

閉鎖の経緯はほとんど残されていないが、GitHubの台頭が背景にありつつ、またWorklogが2011年ごろに収益認識などの関係から作業完了のもののみ公開されるような方針になったこと、公開されていたプロジェクトやWikiのライセンス管理やメンテナンスも万全とは言い切れないことなどがあった模様で、2012年8月1日をもって閉鎖。
入緑(予定)記事🟢

## はじめに
この記事を書いている現在(11/30)は入緑をしておらず、おそらく公開される時にも入緑はしていません！

入緑した(してない)ことよりも、競技プログラミングを通して、アルゴリズムを学ぶことにはとても価値があるということを伝えたいです。

https://atcoder.jp/users/apierce

## 何が嬉しいか
僕が競プロをしていてよかったなと思うことはざっとこんな感じです。
- 楽しい
- 言語に対する理解が深まる
- エスパー力がつく
- ロジカルに考えられるようになる
- コーディングテストに受かりやすくなる

#### 楽しい
まずなんと言っても楽しいです。
解けるか解けないかレベルの問題が```WJ```から```AC```に変わる時の脳汁は半端ないと思います。

#### 言語に対する理解が深まる
僕はRubyで競プロをしているのですが、競プロを始める前に比べるとRubyに対する理解が深まったように感じています。

```
    [ [12, 33], [100, 20], [88, 0], [2, 11], [550, 1] ]
```
上記の2次元配列を```1番目の要素の昇順でソートして、同じものがあれば2番目の要素の降順でソート```する場合、Rubyだと以下のように書くことができます。
```ruby
    arr = [ [12, 33], [100, 20], [88, 0], [88, 11], [550, 1] ]
    puts arr.sort{|a, b| (a[0] <=> b[0]).nonzero? || b[1] <=> a[1]}
```
これを理解するにはComparableモジュールを理解する必要があります。

https://docs.ruby-lang.org/ja/latest/class/Comparable.html#I_--3C

```<=>``` ←これを```UFO演算子```というのですが、UFO演算子では以下のような値が返されます。
>self <=> other は
>- self が other より大きいなら正の整数
>- self と other が等しいなら 0
>- self が other より小さいなら負の整数
>- self と other が比較できない場合は nil
```ruby
    irb(main):001:0> 1 <=> 3
    => -1
    irb(main):002:0> 3 <=> 1
    => 1
    irb(main):003:0> 1 <=> 1
    => 0
    irb(main):004:0> "hello" <=> 1
    => nil
```

これを踏まえると、```sort{|a, b| (a[0] <=> b[0]).nonzero? || b[1] <=> a[1]}```を見ると、1番目の要素を基準にソート```a[0] <=> b[0]```して、等しいものがあった場合(0が返される場合)```.nonzero? || ```2番目の要素を基準に降順ソート```b[1] <=> a[1]```と解釈することができます。

この例のように、言語に対する理解が深まることはあるのかなと思います。

#### エスパー力がつく
エスパーができるようになります。
エスパーというよりは、与えられた条件に対する最適解を導くまでの反射能力みたいなものがつくと思っています。

#### ロジカルに考えられるようになる(気がする)
アルゴリズムを解く時に一発で解けることもありますが、全てがそうではなく、段階的に解いていくことが多いと思います。
現状から目的達成までに何が必要で何をすべきかみたいなところの考え方が洗練されたように感じています。

#### コーディングテスト
Web系の企業では、インターンやエントリーの際にコーディングテストを課すところが多いです。
このコーディングテストでは、だいたいアルゴリズム系の問題が出題されます(たまにjavascriptの問題とかもある)。

実際にいくつか受けてみて、緑コーダーまで行けば、大体のコーディングテストは通るのかなと感じています。
逆に言えば、全くアルゴリズムを知らない状態だとかなり難しいのかなとも思います。
## 素晴らしいサイト達

https://atcoder.jp/

https://yukicoder.me/

https://algo-method.com/

https://onlinejudge.u-aizu.ac.jp/home

https://leetcode.com/

## 終わりに
現在インターンをさせていただいていますが、今があるのは割とマジでAtcoderをやっていたからだと思っているのでめちゃくちゃおすすめです。
まずは1問解いてみましょう！

https://kenkoooo.com/atcoder/#/table/apierce
競プロのためのPythonの便利な機能

## 条件式 (Conditional Expressions)

```python
expression1 if condition else expression2
```
conditionがTrueであればexpression1に評価され、
Falseであればexpression2に評価される。
JavaとC++の三項演算子 condition ? expression1 : expression2 に該当する。

伝統的なIF文で表現する場合：
```python
if n >= 0:
    param = n
else:
    param = -n
```

条件式の場合：
```python
param = n if n >= 0 else -n
```

条件式はソースコードの可読性を向上させる場合のみ使用する。

## 内包表記文法 (Comprehension Syntax)

リスト内包表記：
```python
[expression for value in iterable if condition]
```

使用例：
```python
n = 10
squares = [k * k for k in range(1, n + 1)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
factors = [k for k in range(1, n + 1) if n % k == 0]
# [1, 2, 5, 10]
```

リスト型以外に、集合型、ジェネレータ型、辞書型も内包表記をサポートする。
```python
# list
[k * k for k in range(1, n + 1)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# set
{k * k for k in range(1, n + 1)}
# {64, 1, 4, 36, 100, 9, 16, 49, 81, 25}

# generator
(k * k for k in range(1, n + 1))
# generator object

# dictionary
{k : k * k for k in range(1, n + 1)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}
```

## パッキングとアンパッキング (Packing and Unpacking)

tuple型にパッキングする例：
```python
data = 2, 4, 6, 8
# (2, 4, 6, 8)

return x, y
# (x, y)
```

アンパッキングの例：
```python
# unpacking
a, b, c, d = range(7, 11)

quotient, remainder = divmod(a, b)

for x, y in [ (1, 2), (3, 4), (5, 6) ]:

for k, v in data.items():
```

多重代入 (Simultaneous Assignments)の例：

```python
x, y, z = 3, 4, 5

a, b = b, a + b
```

## 便利なライブラリ

### collections.Counter()

https://docs.python.org/3/library/collections.html#collections.Counter

```python
a = ['a', 'b', 'c', 'd', 'a', 'a', 'b']
c = collections.Counter(a)
# Counter({'a': 3, 'b': 2, 'c': 1, 'd': 1})
```

## 考える価値がある手法

* 番人を立てる
    *　リストの前後に0を追加する
.gitattributesで特定ディレクトリ内のファイルを指定する

## 概要
ファイルごと、ディレクトリごとにgitの振る舞いを制御する方法に`.gitattributes`を使用する方法があります。
このファイルの使い方はネット上に記事がそれなりに存在しますが、特定ディレクトリ内のファイルを指定する方法について[公式ドキュメント](https://git-scm.com/docs/gitattributes)含め情報が少ないです。
ということで、ディレクトリ内のファイルを指定する方法について調べたことをメモしておこうと思います。

## 結論
`.gitignore`の書き方と変わらない

## .gitattributesの使い方
一般にリポジトリのルートディレクトリに配置してgitの振る舞いを制御します。
配置するファイルの記載例は以下です。

```sh:.gitattributes
*           text=auto eol=lf
*.c         text eol=lf
*.h         text eol=lf
*.bat       text eol=crlf
*.sh        text eol=lf
*.jpg       binary
```
ファイルをテキストとして扱ったり、改行コードを指定したり、差分表示するときのエンコードを指定したり、、、などいろいろ設定できます。

## 特定ディレクトリ内のファイルを指定する
早速本題です。
ディレクトリ単位で指定の方法はいろいろあります。

```sh:.gitattributes
# リポジトリルート直下のsrcフォルダ直下のファイルに適用
src/*               eol=crlf

# リポジトリルート直下のsrc/hogeフォルダ直下のファイルに適用
src/hoge/*          eol=crlf

# リポジトリルートから一階層下のmoduleフォルダ直下のファイルに適用
# リポジトリルートのmoduleフォルダは対象外
*/module/*          eol=crlf

# リポジトリ内のどこかにあるすべてのsampleフォルダ直下のすべてのファイルに適用
**/sample/*         eol=crlf

# リポジトリルート直下のtestフォルダ内、サブフォルダ内、すべてのファイルに適用
test/**             eol=crlf

# ディレクトリ問わず、すべてのtestフォルダ直下のcsvファイルに適用
**/test/*.csv       eol=crlf

# リポジトリルート直下のtestフォルダ内、サブディレクトリ内、すべてのcsvファイルに適用
test/**/*.csv       eol=crlf

# リポジトリ内のどこかにあるすべてのtestフォルダ内、サブディレクトリ内、すべてのcsvファイルに適用
**/test/**/*.csv    eol=crlf
```

結構多彩な指定が可能そうです。

## まとめ
拡張子で一律に指定すると場合によっては都合が悪いことがあります。
拡張子が一緒でも、異なるOSで使うファイルだったり、異なるソフトで使用するファイルだったり、といったパターンです。

`.gitignore`と指定方法は一緒なので、[公式ドキュメント](https://git-scm.com/docs/gitattributes)であまり解説しないのはこのためかも。
困ったときは`.gitignore`の情報も調べてみるといいかもしれません。

以上になります。
ここまで読んでいただきありがとうございました。
【サーバ構築】Dockerでspring-bootのサービスを起動する

## はじめに
javaの実行環境用のコンテナをDockerで作成して、warファイルにしたspring-bootのサービスを起動してみました。

### 設定ファイル

```yml:docker-compose.yml
version: '3.6'
services:
  java:
    build: ./docker/java
    ports:
      - 8080:8080
    tty: true
    volumes:
      - .:/usr/src
    command: java -jar /usr/src/WebApp-1.0-SNAPSHOT.war
```

```build: ./docker/java```
⇒Dockerfileの場所を指しています。コンテナを立ち上げる際に、読み込んでそうです。
```command: java -jar /usr/src/WebApp-1.0-SNAPSHOT.war```
⇒コンテナを立ち上げた後に、コマンドを実行してくれます。（今回はwarファイルを起動してくれます。）
　※commandは記載しなくてもコンテナが起動した後に```docker-compose exec サービス名 bash```でコンテナ内に入ってwarファイルが格納されているディレクトリで直接実行してもいけます。
```Dockerfile:Dockerfile
FROM openjdk:18
```
javaのバージョンを指定しています。今回は18にしました。
バージョンによっては起動時にエラーになるので注意してください。

### ディレクトリ構成
```
      /usr/ap
           |
           |-WebApp-1.0-SNAPSHOT.war
           |-docker
           |   |-java
           |      |-Dockerfile
           |-docker-compose.yaml
```
### java
簡易APIを実装しました。
今回はpackageビルドjarファイルではなく、warファイルを生成するようにしました。
pom.xmlで設定できます。デフォルトはjarだと思います。


### 起動方法
docker-compose.yamlが格納されているディレクトリ内で```docker-compose up -d```です。
コンテナが起動しているかは```docker ps```で確認できます。

## 最後に
Dockerのコンテナ内の環境でsystemdとかserviceコマンドは使えなさそうです。
なのでサービスに登録して実行みたいなことができないかもしれません。
ただ、コンテナで立ち上げたサービスはOSもしくはコンテナからログアウト（sshの接続を切る）してもサービスは常駐してくれます。
PCの在庫管理をPower BIで行った話

今回はPower BIを使ってPCの在庫管理をしてみた話です。
ツールを使ってPCを管理していても行方不明のPCが発生します。私が使っているPC管理ツールでは、其々のPCに対して最後にオンラインになった日(スキャンした日[last discovered])を確認することができるのですが、行方不明なPCはしばらく放置すると探すのが大変なので、このデータを使ってPower BIで１か月以上オンラインになっていないPC数（連絡なく使われてなさそうなPC数）を定期的に通知する仕組みを作ってみました。

## 用意するもの
・Power BI
・PC管理ツールからダウンロードしたPC在庫データ

※PCデータの内容（例）
|Asset Tag  |Serial Number  |Manufacture  |...|Install Status|Last Discovered|Last scanned User ID|...|
|---|---|---|---|---|---|---|---|
|AABBCCDD  |1234567  |Dell  |   |In stock|10/5/2022|aaa.aaa@xxx.com|  |
|EEFFGGHH  |2345678  |Dell  |   |In use|30/8/2022|bbb.bbb@xxx.com|  |
|IIJJKKLL  |3456789  |HP  |   |In use|3/11/2022|ccc.ccc@xxx.com|  |

## 処理の流れ
1. Power BIデスクトップにPC在庫データをロード
2. 直近１か月間以上オンラインになっていないPCの数をメジャーを作ってカウント
3. Power BIデスクトップからPower BIレポートを発行
4. カードビジュアルをダッシュボードに追加
5. 数が0以上になっている場合に、メールで通知するように設定

## 手順 
#### 1.Power BIデスクトップにPC在庫データをロード

詳細説明は省きます。

#### 2.直近１か月、オンラインになっていないPCの数をメジャーを作ってカウント

2-1. PCを使用中("In Use")のステータス([Install Status])にも関わらず、最後にスキャンした日([Last Discovered])が30日以上前の日付になっているPCの数をカウントします。

```
UnScanned PC = 
var _30DaysAgo =TODAY()-30
Return
CALCULATE(COUNTROWS(CMDB), CMDB[Install Status]="In Use", CMDB[Last Discovered] < _30DaysAgo)
```

2-2. このメジャーをカードビジュアルに配置して表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/fc59faa3-1a69-2e09-6080-dbe98ca587b6.png)


#### 3. Power BIデスクトップからPower BIレポートを発行

詳細説明は省きます。

#### 4. カードビジュアルをダッシュボードに追加

4-1. Power BIサービス上のPower BIレポートのカードビジュアルに表示されているPinをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/c1b1c4dc-d364-ad4d-828a-7c6aff7d86ac.png)

4-2. 追加先のダッシュボードを確認されるので、既存のダッシュボード、もしくは新規のダッシュボードを設定し、Pinをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/66acd227-5171-c64e-038a-208dfcbea1a9.png)

#### 5. 数が0以上になっている場合に、メールで通知するように設定

5-1. ダッシュボードに追加されたPinの右上の・・・をクリックし、Manage Alertsをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/98e5d4dc-2e3c-6250-3a9b-4bff60793466.png)

5-2. "＋Add alert rule"をクリックし、Condition(条件)とThreshold(閾値)をそれぞれ設定します。今回は１つでもあったら通知がほしいので、Above 0と設定します。
頻度(frequency)の設定もできますが、頻繁な通知は必要ないので、最大24時間毎(At most every 24 hours)に設定します。
※Alerts are only sent if your data changesと記載されているので、例えばこのデータセットが１週間に一度しか更新されないようになっている場合は、多くても１週間に１度通知されることになるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/d2c5ad1f-f512-4a49-2f65-b9a1560c3c78.png)

これで行方不明のPCが少なくなっていくことを切に願います。

以上です。
LIFFでアカウント連携時にLINEプラットフォームにリダイレクトができない

# 背景
自社IDとLINEアカウントを連携したい。公式リファレンスに従い進めてましたが、終盤工程である ```⑨ウェブサーバーが、ユーザーをアカウントを連携するエンドポイントにリダイレクトする。```にて詰まりました。

https://developers.line.biz/ja/docs/messaging-api/linking-accounts/#account-link-sequence

# 事象

linktoken & nonce取得後にユーザを下記エンドポイントへリダイレクトさせる必要がある
```shell
https://access.line.me/dialog/bot/accountLink?linkToken={link token}&nonce={nonce}
```

しかし、**「ログイン中」** と薄っすら画面に何度も表示される現象に陥る。しかもエラー表示もでない。
他の記事にもあるように```access.line.me```にリダイレクトされ続けるループに落ちいる。

https://qiita.com/seya/items/2e8b5f0600bf79a6dcea


#### (参考)処理の内容
Reactにて実装
ホームディレクトリ"/"にて ```linktoken``` を取得
→"/login"に遷移して自社サービスにログインし ```nonce```を取得
→アカウント連携URLへリダイレクトさせる

# 解決策
結論はLIFFブラウザで開くのではなく、外部ブラウザで開くように遷移させたら上手くいった。

#### 改善前

```javascript
window.location.href = "https://access.line.me/dialog/bot/accountLink?linkToken="+ encodeURIComponent(linktoken) +"&nonce="+ encodeURIComponent(nonce);
```

#### 改善後

```javascript
// login.jsx
liff.openWindow({
    url:"https://access.line.me/dialog/bot/accountLink?linkToken="+ encodeURIComponent(linktoken) + "&nonce=" + encodeURIComponent(nonce),
    external: true,
 });
```
https://developers.line.biz/ja/reference/liff/#open-window


# 所感
クエリパラメータでも似たような事象になっている人がいた。
LIFFは情報量が少ないので困った。なかなかLINE DCのコミュニティも活発ではないので、少しでも役に立てば幸いです。
sakuraのレンタルサーバーにあるGitリポジトリにssh公開鍵認証で接続する方法

sakuraのレンタルサーバーにGitリポジトリを作成したのは良いものの、sshで接続するとプル／プッシュの時に毎回パスワードを要求されて困っていた。
Puttygenで秘密鍵・公開鍵を作成しTortoiseGitに登録して～という記事はいくつも見るけど設定していも上手く行かない。（パスワードを要求される）
その場合の対応方法を記載する。


# ◆大まかな手順
>　①sakuraのサーバで秘密鍵・公開鍵を作成する
　②秘密鍵をクライアントにダウンロードする
　③クライアント側にてsshのConfigを記述する

## ①sakuraのサーバで秘密鍵・公開鍵を作成する
- まずPuttyなどでsakuraに接続
- 次に~/.sshに移動
>```
>cd ~/.ssh
>```

　　※.sshフォルダが無い場合は作成してから移動（`mkdir ~/.ssh`）


- `ssh-keygen`にて秘密鍵・公開鍵を作成する
>```
>ssh-keygen -t rsa -f id_rsa_sakura
>```
　　`-t rsa`は暗号方式をRSAにする指定
　　`-f id_rsa_sakura`は、秘密鍵・公開鍵のファイル名を「id_rsa_sakura」にする指定


- 上記を実行すると~/.sshフォルダに以下の2ファイルが作成される
　　　id_rsa_sakura　　　　・・・　秘密鍵
　　　id_rsa_sakura.pub　　・・・　公開鍵


- 公開鍵（id_rsa_sakura.pub）を~/.ssh/authorized_keysに登録する

　　［~/.ssh/authorized_keysが存在しない場合］
>```
>cat ./id_rsa_sakura.pub > ./authorized_keys
>```

　　［~/.ssh/authorized_keysが存在する場合］
>```
>cat ./id_rsa_sakura.pub >> ./authorized_keys
>```

- authorized_keysのパーミッションを変更する
>```
>chmod 600 ./authorized_keys
>```


## ②秘密鍵をクライアントにダウンロードする
- 秘密鍵（`~/.ssh/id_rsa_sakura`）をクライアントにダウンロードしフォルダに保存する
> - Windowsの場合
>    `c:\Users\＜ユーザ＞\.ssh`に保存する
> - Macの場合
    `~/.ssh`に保存する

## ③クライアント側にてsshのConfigを記述する
- .sshのフォルダ（Windowsは`c:\Users\＜ユーザ＞\.ssh`　Macは`~/.ssh`）に
    `config`というテキストファイルを作成する（拡張子なし）
- configファイルに以下の内容を記載する
```windows.
Host xxxxxx.sakura.ne.jp
    HostName xxxxxx.sakura.ne.jp
    User xxxxxx
    IdentityFile c:\Users\＜ユーザ＞\.ssh\id_rsa_sakura
```
```Mac.
Host xxxxxx.sakura.ne.jp
    HostName xxxxxx.sakura.ne.jp
    User xxxxxx
    IdentityFile ~/.ssh/id_rsa_sakura
```
>    xxxxxx　　・・・　sakuraのユーザID
>    ※Hostのところは「xxxxxx.sakura.ne.jp」でなくても良いが、まずは接続することを優先するためにHostNameと同じ値にしている
>      上手く接続できた後に、変えてみるのも良いと思う。

## 設定は以上で完了　ssh公開鍵認証で接続できるか確認する
- ssh公開鍵認証で接続できるか確認する
```
ssh xxxxxx@xxxxxx.sakura.ne.jp 
```
> パスワードの要求なしに接続できれば成功！

- TortoiseGitへの設定は不要
    TortoiseGitに対して`Putty鍵`の設定不要（空欄で良い）

# TortoiseGitもSourcetreeもVSCodeも全部繋がるはず(^^;)
フルトンネルとスプリットトンネルの違い

# フルトンネルとスプリットトンネルの違いを説明しようと思ったきっかけ
アドベントカレンダー9日目です。
VPNの接続形式に関する記事になります。
以前の記事、シリーズで4本書いた**AWS Client VPNとAzure P2Sを比較してみた**からの派生した記事です。
以前の記事はこちら。
[AWS Client VPNとAzure P2S 機能比較 01~AWS Client VPN構築編01~](https://qiita.com/hidekko/items/5dc7de8f3cde645959b2)
[AWS Client VPNとAzure P2S 機能比較 02~AWS Client VPN クライアントPC設定編~](https://qiita.com/hidekko/items/c7e65dbd5985ec260c9f)
[AWS Client VPNとAzure P2S 機能比較 03~Azure P2S構築編~](https://qiita.com/hidekko/items/0ba2fb85b6c89da5fe84)
[AWS Client VPNとAzure P2S 機能比較 04~Azure P2S クライアントPC設定編~](https://qiita.com/hidekko/items/44bb46daf35d3ba91b41)

AWS Clinet VPNはフルトンネル形式もスプリットトンネル形式も選択可能、Azure P2Sは現時点(記事執筆時の2022/11/29)ではスプリットトンネルのみです。

色んな会社、主にVPNを販売する会社でフルトンネルとスプリットトンネルの違いを説明しているサイトはありますが、構成図を使って説明しているサイトが少ない気がしたのでこちらで記載しようと思ったのがきっかけです。
もし私の認識に間違いがあればお手数ですがコメントください。

:::note info
前提条件
自宅にあるClientから会社にあるFirewall機能付きルーターにVPN接続を行う
:::

今回はアイコンはCiscoのものを使っています。
なぜアイコンの色が<font color="Green">緑色</font>かというと、<font color="Green">緑色</font>はStatusがNormalということらしいです。

# 1. フルトンネルとは
VPN接続時に、VPNクライアントのデフォルトゲートウェイがVPN接続先機器になるVPNの接続形式です。
文字で書くとこうなりますが、図にするとこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/05ccbc96-7056-0b26-2a5b-a17ff7380a16.png)
こうなります。
もう少し詳しく説明すると、VPN接続を行ったあと、Clientはデフォルトゲートウェイが前述の説明の通り会社にあるFirewall機能付きルーターになります。
なのでインターネット接続、つまりデフォルトゲートウェイに向かう通信は全て会社にあるFirewall機能付きルーターを経由して行うことになります。
当然会社にあるServerにアクセスする際は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/01e93c69-d45b-3c85-d280-b34cf7bf9fa4.png)
こうなります。
インターネット接続の<font color="Red">**赤太線**</font>の中にVPN接続を示す<font color="Blue">青線</font>が入っているのは、VPN接続がインターネット接続の中を通っているからです。

# 2. スプリットトンネルとは
VPN接続時に、VPNクライアントのデフォルトゲートウェイが元々Clientが持っているデフォルトゲートウェイのままの接続形式です。
文字で書くとこうなりますが、図にするとこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/963e767d-8d0a-87da-8bd2-17da87f8f7ec.png)
いや、これホント自分でもどうかと思ったんですが、こんな図になっちゃいました。
図示するのが難しんですが、こうなります。
余計わかんなくなっちゃいそうですね。
ちょっと時間をおいて図は再考します。
まだ入院してた時のダメージが残ってるみたいで、考えがまとまりません・・・
補足説明を行うと、VPN接続はフルトンネルと同じくインターネット接続の中を通ります。
しかしインターネット接続は自宅のルーターから直接接続します。
こうすることでインターネット接続の速度は保ちつつ、社内のサーバへの接続のみをVPN接続の中を通すことが可能です。
当然会社にあるServerにアクセスする際は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/01e93c69-d45b-3c85-d280-b34cf7bf9fa4.png)
こうなります。
フルトンネルと同じですね。

# 3. フルトンネルとスプリットトンネルのメリットデメリット
フルトンネルは会社のルーター経由ですべての通信が行われます。
メリットとしては通信制御を行いやすいですが、クライアント台数が増えると会社のルーターの負荷が増えて全体の速度が低下するデメリットがあります。
スプリットトンネルは必要な通信のみVPN経由で行われ、インターネットへの通信は自宅のルーター経由で行われます。
メリットとしては最小限の通信のみを会社のルーターで受けるためルーターの負荷は軽く、Clientからのインターネット通信も早いですが、Clientのインターネットへの通信を制御することができません。
通信を制御する、とは、具体的にはAllow ListやBlock Listを用いてClientで閲覧できるWebサイトを制御する、ということです。
ケースバイケースと言えばそれまでですが、よりセキュアなのはどちらか？と言われるとフルトンネルの方がセキュアと言えます。

如何でしょうか？

本日はこれまで。
meson の subproject

わりと癖がある。自前で meson.build を記述する場合は、ある程度理解していないとにっちもさっちもいかない。

# subproject を使う

## dependency() の fallback で発動させる

dependency() が pkg-config などしてみつからなかったときに `fallback` で発動する。

* dependency() の返り値が fallback して subproject であった
* 返り値(dep) を executable や library の dependencies 引数として使った

の条件が成立したときに使われる。

## subproject() で subdir() のように使う

直接参照する。ビルドに含まれる。わかりやすい。

```
libsimple_proj = subproject('libsimple')
libsimple_dep = libsimple_proj.get_variable('libsimple_dep')
```

# subproject(wrap) の動作

だいたい以下のような動きをしているようだ。

* wrap が発動する。
* wrap の記述に基づいて、source を download する
* wrap の記述により download したアーカイブを解凍する
* wrap の記述により download したディレクトリに patch を上書きする
* download_dir/meson.build の処理へ

# subproject の meson.build を自前で用意する例

この手法を使うことで `meson.build` が無いプロジェクトや、あってもうまく動かないプロジェクトに対処することができる。

```
# project files
meson.build
subprojects
  lua.wrap
```

patch_directory を指定します。

```lua.wrap
[wrap-file]
directory = lua-5.4.4
source_url = https://www.lua.org/ftp/lua-5.4.4.tar.gz
source_filename = lua-5.4.4.tar.gz
source_hash = 164c7849653b80ae67bec4b7473b884bf5cc8d2dca05653475ec2ed27b9ebf61
patch_directory = lua # 👈 これ

[provide]
lua = lua_dep
```

`patch_directory` は `subprojects/packagefiles` からの相対パスです。

`subprojects/packagefiles/lua/meson.build` を記述することで `外部のソース` + `自前の meson.build` という構成ができます。

:::note
`subprojects/lua-5.4.4` が展開された後で `subprojects/packagefiles/lua/meson.build` が `subprojects/lua-5.4.4/meson.build` にコピーされます。
:::

:::note warn
patch_directory で指定した meson.build が反映されるタイミングは、 `subprojects/lua` が展開されるタイミング一度だけ

`subprojects/packagefiles/lua/meson.build` を試行錯誤しながら書き換えている場合、
`meson setup build` を実行する前に、`subprojects/lua-5.4.4` を毎回削除する必要があります。
さもないと、同じ内容の `subprojects/lua-5.4.4/meson.build` が使われ続けます。
:::
Power BIでSharePoint フォルダをデータソースにした時のTips

社内ではPower BIでSharePointに保管されているファイル(SharePointフォルダ)をデータソースにすることが多々あるのですが、SharePointサイトに保管される必要なファイルのデータだけ取得する方法について悩んだことがありましたので、自分への備忘録兼ねてTipsを書いてみました。

https://learn.microsoft.com/ja-jp/power-query/connectors/sharepointfolder

## 私が悩んでいたこと
・SharePointフォルダコネクタを使用していると、SharePointサイトに保管されている全てのファイルがみえてくるが、必要なファイルだけをフィルターしたい
・Power BIデスクトップのPower Query EditorのGUIで列をフィルターしようとしても、全てのデータが表示されていないので十分にフィルターできない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/9449eb62-8e52-b46a-8e1c-945766c85e3f.png)


## というわけでTips
Power BIでSharePointフォルダコネクタを利用してデータをもってくると、Power Query Editorにて自動的に以下のようなQuery stepが作成されると思います。
2番目のFiltered Rowsのステップを少し編集するだけで、読み込みたいファイルを柔軟に変更することができそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/f1dcaed3-2200-1ef3-6224-67c6dc3cb958.png)

・特定のフォルダ(下図の例だとdataフォルダ)に保管されているファイルを読み込みたい場合
Table.SelectRows関数を使い、SharePointフォルダに格納されているファイルを読み込んだ時に自動的に作成されたテーブルのフォルダパスの列([Folder Path])に対して特定のSharePointフォルダパスを指定し、このフォルダに保管されているファイルだけに絞り込みます。

```
    = Table.SelectRows(Source, each ([Folder Path] = "https://xxxx.sharepoint.com/sites/xxxx/Shared Documents/xxxx/xxxx/data/"))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/267c6364-1ad6-3668-7794-137c9914d73c.png)

・ファイル名で絞り込みたい場合
SharePointフォルダに格納されているファイルを読み込んだ時に自動的に作成されたテーブルのファイル名の列([Name])に対してText.Contains関数を使い、特定の文字列のファイルだけを絞り込むようにすればよさそうです。
```
    = Table.SelectRows(Source, each Text.Contains([Name], "xxxxx"))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952241/19662c22-cce6-5621-4abd-a678c8206af2.png)

GUIでポチポチ設定するのもいいですが、Power QueryのM関数を知っているとできることが広がるな、と思うきっかけになりました。

https://learn.microsoft.com/en-us/powerquery-m/table-functions

https://learn.microsoft.com/en-us/powerquery-m/text-functions

以上。
Socket.IOを使って、Node.js（client）とPython（Server）の双方向通信

Node.jsとPython間で、Socket.ioでメッセージをやり取りする自分用メモ。
いやぁ、、、Python難しい、、、まじでわけわからん。。

# やりたかったこと
* Pythonが定期的に（やや重たい）演算処理を実行している
* Python側の演算処理が一巡したら、Node.jsへ結果を送りたい
* また必要に応じてNode.js側からPython側へ演算のもとになるデータを送りたい
* Python側がメインのシステム。
　⇒PythonからNode.jsと、Node.jsからPythonへ、双方向でやり取りしたい
　⇒とりあえずメッセージをやりとりするための土台をつくろう！

# 環境
* Windows 10 64bit
* Node.js（v18.0.0）
* Python（3.7.9）


# Python のパッケージ
* cmd > pip install python-socketio
　⇒依存：python-engineio, bidict
* cmd > pip install eventlet
　⇒依存：dnspython, greenlet, six


# Node.js のパッケージ
* cmd > npm install express
* cmd > npm install socket.io-client


# プロジェクトフォルダ構成
folder/
  ├ node_modules/
  ├ socketInterface.py
  ├ app.js
  └ package.json


# Socket.IO Server（Python）
~~~Python:socketInterface.py
import time,signal,threading
import socketio,eventlet

class SocketInterface(socketio.Namespace):
    def on_connect(self, sid, environ):
        print('接続しました')
    def on_disconnect(self, sid):
        print('切断されました')
    def on_client_to_server(self, sid, msg):
        print(msg + '受信しました')
        self.emit('response', msg)

class ThreadServer:
    def __init__(self, namespace):
        self.sio_         = socketio.Server(async_mode='eventlet')
        self.app_         = socketio.WSGIApp(self.sio_)
        self.Namespace    = SocketInterface(namespace)
        self.sio_.register_namespace(self.Namespace)
    def start(self):
        eventlet.wsgi.server(eventlet.listen(('localhost', 8000)), self.app_)
    def run(self):
        p = threading.Thread(target=self.start)
        p.setDaemon(True)
        p.start()

if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    thread_server = ThreadServer('/test')
    thread_server.run()
    while True:
        time.sleep(5)
    #ctr+Cが入力されたら終了
    exit()
~~~


# Socket.IO Client（Node.js）
~~~javascript:app.js
const app = require('express')()
const io = require('socket.io-client')
const socket = io.connect('http://127.0.0.1:8000/test')

app.get('/', (req,res)=>{
    res.sendFile(__dirname + "/index.html")
})

app.listen(3000, ()=>{
    console.log("listening port=3000...")
})

socket.on('connect', () => {
    console.log('socketInterfaceに接続しました');
    socket.emit('client_to_server','メッセージだよ')
  });

socket.on('response',(msg)=>{
    console.log(msg + 'が戻ってきました')
})
~~~

# メモ
* 使い方は、pythonを実行したあとで、Node.js側を実行する
⇒このスクリプトをベースにいろいろいじってみると何となく挙動が見えてきた
（トライ＆エラーで繰り返してたら一応動いた、、というだけ。。）
* あとはPythonのWhileループ中で定周期で演算させればOK！

# 参考
＜python-socketio＞
https://python-socketio.readthedocs.io/en/latest/
⇒公式。ただ、何を言ってるのかさっぱりわからなかった。。

＜ITエンジニアの技術メモ＞
https://ittechnicalmemos.blogspot.com/2019/08/pythonsocketio_17.html
⇒無茶苦茶役に立ちました。。ほんとありがとうございます。。