OmniAICreator/Qiita-1.07M huggingface dataset:
2024/1/5主にITとかセキュリティの記事

ポルノサイト利用に写真付き身分証明を要求　英国の新法に懸念の声(1/3)
https://forbesjapan.com/articles/detail/68005

ハッカーのおもちゃとしてのNostrのススメ(1/3)
https://qiita.com/gpsnmeajp/items/2f95d4adf188276146d8

「地方都市でもサイバーテロはひとごとでない」　京都・福知山でテロ対策ネットワーク(1/3)
https://www.kyoto-np.co.jp/articles/-/1146971

【中央時評】２０２４年の北朝鮮リスクと韓半島（２）(1/3)
https://japanese.joins.com/JArticle/313389?servcode=100&sectcode=120

ServiceNow導入で学ぶ　OOTBを使う3つのメリット(1/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/102700385/122100003/

2024年のIT投資、リーマン・ショック前の勢いを回復(1/4)
https://xtech.nikkei.com/atcl/nxt/column/18/02703/122700001/

盗む側から考えるアカウント管理の危険性、デジタルならロック付きUSBメモリーで(1/4)
https://xtech.nikkei.com/atcl/nxt/column/18/02676/120500001/

「一（いち）」から得られるプロフェッショナルへの示唆
(1/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020900021/122100154/

データ品質管理の課題はコスト　SaaSやAIで経済性を改善(1/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/031700346/122200011/

DX前後も業務マニュアルが大活躍　メリット周知や情報整理に威力(1/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/112700390/122100002/
OverleafとVSCodeを使った論文執筆環境の構築

初めましての方は初めまして．そうでない方はいつもありがとうございます．

私事ではありますが，卒論提出が近づいてきており，そろそろ書き始めなければ間に合わない時期になってきました．今回は，それに関連した記事になっています．

さて，私の所属する研究室では，$\LaTeX$での執筆が必須条件になっており，また，Overleafでの執筆が推奨されています．
ところが，Overleafの無料版を利用していると以下の点が気になりました．（有料版を利用すれば問題ないのは百も承知なのですが，何ぶん苦学生なので，ご容赦いただければ･･････）

- 連続して長時間の編集をしているとコンパイルに制限がかかる（最近になって制限が厳しくなったとか）
- コンパイルが遅い（変更を確認するのに時間がかかる）
- コンパイル実行時にOverleaf以外の回線が途切れる（私の環境だけでしょうか？）

また，可能なら以下の機能も欲しい……

- gitでの管理（今回は見送っています）
- 執筆のサポート

要望が多いのは理解していますが，自分でどうにかできることならやっておきたい！ということで，こうした要望を満たすことができるような環境が無いかを模索してみました．

:::note warn
本記事の内容は，とりあえず書ける環境を構築するという目的で，場当たり的に色々なものを組み合わせたものなので，到底，動作を保証できるものではありません．自分の環境では動作しましたが，同様の手順を実行される場合でもエラーが発生することが予想されます．
:::

|項目|説明|
|:-:|:--|
|OS|Ubuntu 22.04 LTS (WSL)|
|CPU|AMD Ryzen 5 5600X|
|メモリ|16GB|
|エディタ|VSCode|

# 環境構築 
ローカル環境を汚したくなかったので，今回，Dockerを利用しました．コードは以下に記載しておきます．（色々と試していた関係でDocker Composeを利用していますが，それ程複雑でないのでDockerでも十分だと思います．）

```docker: docker-compose.yml
version: '3'

services:
  editor:
    image: pandoc/latex:latest
    container_name: editor
    tty: true
```

# 拡張機能（ローカル）
ローカル側でインストールする拡張機能は以下の通りです．

- Docker
    + `ms-azuretools.vscode-docker`
- [Option] GitHub Copilot
    + `github.copilot`
    + 認証も済ませるようにしておいて下さい

[前章](#環境構築)で掲載しているコンテナが起動できたらDockerの拡張機能で追加されている「実行中のコンテナーにアタッチ」をクリックして下さい．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/f804ff2f-ba99-1240-9cab-be439c43dc27.png)

:::note
Github CopilotはGithubの有料版を利用している方向けです．Github Copilotに執筆作業のサポートをしてもらおうという算段です．
ちなみに，学生は無料で利用できます．（2024年1月現在）
:::

https://qiita.com/SNQ-2001/items/796dc5e794ac3f57a945


# 拡張機能（コンテナ）
コンテナ内でインストールする拡張機能は以下の通りです．

- Overleaf Workshop
    + iamhyc.overleaf-workshop
- LaTeX Workshop
    + james-yu.latex-workshop
- [Option] Github Copilot
    + github.copilot

## Overleafの認証
Overleaf Workshopを利用するためには，Cookiesでログインしなければなりません．これについてはGithubの方でスクショ付きで丁寧に解説されているので，[そちら](https://github.com/iamhyc/Overleaf-Workshop?tab=readme-ov-file#how-to-login-with-cookies)を参考にされて下さい．（英語ですが，操作自体は非常に簡単なので，苦手な方でも大丈夫だと思います！）

# いざ執筆
ここまで来れば後は文章を書いていくだけです．お疲れ様でした．
基本的な使い方や利用可能なコマンドは[Githubの方](https://github.com/iamhyc/Overleaf-Workshop/blob/master/docs/wiki.md#basic-usage)で解説されていますが，コマンドについてはチートシート的に表にまとめておきます．

|コマンド|説明|
|:-:|:--|
|`ctrl` + `Alt` + `B`|コンパイル|
|`ctrl` + `Alt` + `V`|プレビュー|
|`ctrl` + `.`|スペルチェック|
|`Shift` + `Alt` + `F`|文章フォーマット|

## 補足事項
実行時間について．
卒論の内容をそのまま掲載する訳にもいかないので，実測時間のみになりますが，約30ページほどになるプロジェクトをコンパイルしたところ，Overleafで約十数秒，私の環境では約6, 7秒程度と，約半分の時間となりました．（いずれも5回コンパイルしたときの平均時間）
もう少し長い文書で試してみないと何とも言えないかもしれませんが，個人的には急いで執筆する中でこの差は大きいのかなと感じました．

あと，細かいことですが，オートコンパイル機能を使っていてもエラーが発生しない（少なくとも現時点では）のが，個人的には嬉しかったです．Overleafでオートコンパイルを有効にした状態で執筆するとよくエラーを吐くため無効にしており，残念に思っていたので．

最後に，Github Copilotですが，個人的にはあまり役に立っていないような気がします．（結構，間違える……）
そのため，本記事ではあまり触れていません．（あえて，ローカルに環境を構築するメリットの1つにはなり得るかなと思って入れましたが，姑息だったかもしれません．笑）
Glide(Googleスプレッドシート)とZapierを連携してSlackに更新通知が来るようにしたよ！

こんにちは、**ウエハラ　シンペイ**です。

今回、以前Glideで作成したコンテンツ検証用にアプリを作成したんですが、更新時に特に通知がないので見落とす可能性が高く、今回Zapier(ザピアー)を使って更新時の通知が届くようにしました。

# Zapierとは？
ノーコードで外部アプリケーションを連携させることで様々なワークフローの自動化を実現してくれるWEBアプリケーションで、下記のようなことが実現できるようです。

+ 新しいデータ(行)が追加されたら通知メッセージが届く　 【Googleスプレットシート】　→　【Slack】
+ 新しいメッセージ内容をGoogleスプレットシートに自動保存 【Gmail】　→　【Googleスプレットシート】
+ Wordpressの新しい投稿を自動的にツイートする 【WordPress】　→　【X】

などなど。

他にもこちらに使い方事例がわかりやすくまとまってました。

[【できること一覧】ツール連携が可能なZapier(ザピアー)の使い方](https://enpreth.jp/media/zapier-possible/ "【できること一覧】ツール連携が可能なZapier(ザピアー)の使い方")

# 今回やりたいこと
Glideで作成したアプリに**新しい投稿があった際にでSlackに更新通知が届く**ように実装したい思います。


# 今回やったこと

### 1.Zapierアカウントを作成
[Zapier](https://zapier.com/ "Zapier")から新規アカウントを作成
![01 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618353/d7ecf7ff-e4ec-7986-6460-2be50b584a27.png)

### 2.テンプレートを選択
Glideのアプリでは更新があった場合にGoogle Sheetにデータが入る用にしているので、下記のテンプレートを選択しました。(自分で設定するのも簡単にできます)

![スクリーンショット 2024-01-04 23.21.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618353/ee2fd5ab-11b0-9f5d-7517-1be64c5ce5b8.png)

### 3. トリガー、アクションを設定
対象となるシートを選択に新規での行が追加されたことをトリガーにSlackに定型文が送られる用に設定しました。迷うポイントが一切ないくらい簡単です。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618353/662fa773-79d7-5410-887b-c6fb1e98e388.png)

### 4. Slackに通知が届きました！
対象のチャンネルにメッセージが届くようになりました！
![スクリーンショット 2024-01-05 0.18.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618353/1c6abfbc-4cd0-b250-186a-3d137edd7976.png)

# 最後に
どうせなら対象ページのリンクもSlackに届くようにしたかったのですが、Zapierはうまくいったのですが、Glide側での設定ができず断念。またチャレンジします。。
折角自宅サーバーがあるのでハッカーっぽい雰囲気を出す【Pi-hole】

この記事では Pi-hole を使って以下のような感じで自宅のネットワークの状態を確認できるようにします。うん、カッコいい！しかも実用性もちゃんとあります。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/abde77e7-56a6-6613-f681-edaf7d692fc7.png)

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/85fc80e2-6413-751a-4b56-d1601d345af2.png)

# Pi-holeとは？
Pi-hole は広告ブロック機能がついた DNS サーバ兼 DHCP サーバです。自宅ネットワークのルータ等についている既存の DNS サーバや DHCP サーバを置き換える形で設置することで、ネットワーク内のすべての端末に広告ブロック効果をもたらしてくれます。端末ごとに広告ブロッカーを入れなくてもよいわけです。また上の画像ように項目が豊富でイカした管理画面がついており、状況を確認したり設定を変更したりなどの作業が簡単に行えます。

# 注意
- この記事では最初の導入方法しか扱いません。それ以上のことは別の記事を見たり、管理画面からいじってみたりしてください。
- ネットワークの構成を変えることによってネットに繋がらない等のトラブルになる可能性があります。設定後に様子がおかしかったら、手順の最後「既存の DNS サーバ、DHCP サーバの停止」の作業を取り消して復活させ、Pi-hole を停止してください。その際、操作している端末の再起動を行わないまま作業を完了するようにすれば問題なく戻せると思います。

# 導入手順

## 準備
デフォルトゲートウェイと DNS サーバと DHCP サーバの IP アドレスを調べておく必要があります。一般的な家庭のネットワークならそれらはすべてブロードバンドルータが担っているのでルータのアドレスを調べます。わからなければシェルから `ping -t1 -c1 google.com` とかして調べます。

```console
$ ping -t1 -c1 google.com
PING google.com (142.251.42.142) 56(84) bytes of data.
From gateway (192.168.10.1) icmp_seq=1 Time to live exceeded

--- google.com ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
```

上の場合、`192.168.10.1` がルータのアドレスです。

## Docker インストール
ここでは Docker 上に立てるので Docker と Docker Compose をインストールします。Ubuntuなら以下。

```console
$ sudo apt install docker.io docker-compose
```

## 起動ファイル作成
Docker Compose で使う `compose.yaml` ファイルを以下の中身で作成します。7行目の `hogehoge` の部分は好きなパスワードに置き換えます。8行目の `192.168.10.2` の部分はこのファイルを置いているサーバの IP アドレスに置き換えます。

```yaml:compose.yaml
services:
  pihole:
    image: pihole/pihole
    network_mode: host
    environment:
      TZ: 'Asia/Tokyo'
      WEBPASSWORD: hogehoge
      FTLCONF_LOCAL_IPV4: 192.168.10.2
      WEB_PORT: 8100
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    cap_add:
      - NET_ADMIN 
    restart: unless-stopped
```

## 起動

以下のコマンドで起動します。

```console
$ sudo docker-compose up -d
```

ちなみに停止したい時は以下。

```console
$ sudo docker-compose down
```

## 管理画面を開く
Web ブラウザで Pi-hole の管理画面にアクセスします。ポート番号は `compose.yaml` の `WEB_PORT: 8100` で指定した8100番です。気に入らなければそこから変えられますし、その行を消せば標準の80番になります。

```
http://192.168.10.2:8100/
```

ログイン画面が出るので設定したパスワードを入力し、ログインします。

## 管理画面で設定
サイドバーの「Settings」、上部のタブ「DHCP」を順に選び「DHCP server enabled」にチェックを入れます。「Router (gateway) IP address」に最初に調べたルータの IP アドレスを入れます。他は今すぐ必要な設定ではなかったり、よしなに設定されているはずなのでこれで一番下の「Save」ボタンを押します。

## 既存の DNS サーバ、DHCP サーバの停止
ルータのアドレスを Web ブラウザのアドレスバーに打ち込んでルータの管理画面を開きます。

```
http://192.168.10.1/
```

ここからは製品によりますが、管理画面から DNS サーバと DHCP サーバの設定を見つけてそれぞれ停止させてください。

おめでとう！これで君も ｽｰﾊﾟｰﾊｶｰ だ！！！
これだけでわかる Amazon CloudWatch の全貌

# はじめに

みなさん、CloudWatch サービスは普段よく使われていると思います。
しかしながら、そもそもの機能の多さに加え、頻繁な機能強化(メニュー構成すら変更)、類似の機能もあることから、全てを把握するのはなかなか難しいのではないでしょうか？
私も結局どれを使えばよいの？と迷子になることが多々...

# CloudWatch 機能のすべて

というわけで、どのような機能があるのかを整理してみました。

![cloudwatch全貌.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117386/954b5430-a855-7954-1405-0e9b3b571fb5.png)

:::note warn
2024年1月時点の情報となります。re:Invent 2023で発表された、CloudWatch Appication Signals も網羅していますが、現在はプレビューのため、今後GAのタイミングでメニュー構成など変更になる可能性があります。
:::


# 逆引き CloudWatch

|ユースケース|利用するサービス|
|:--|:--|
|<b>ログコントロール||
|ログ出力を保存、集計、分析したい| Metrics Streams <br> Subscription filters|
|ログ出力を長期保存したい| Export data to S3|
|リアルタイムでログを確認したい| Live Tail|
|ログをインタラクティブに検索したい| Logs Insights|
|複数アカウントのログをまとめて管理したい|Cross Access Observability|
|<b>状態検知|
|システムの状態をダッシュボードで一覧表示したい|Dashboard<br>Metrics Explorer|
|異常を通知したい|Alarm|
|状態に応じて他のAWSサービスと連携したい|EventBridge(Event Buses)|
|異常の予測検知をしたい| Anomaly Detection|
|EC2のヘルスチェックをしたい|Resource Health|
|オンプレマシンのヘルスチェックをしたい|Network Monitor|
|Webアクセスによるエンドポイントの死活監視をしたい|Synthetics|
|<b>パフォーマンス分析|
|各種メトリクスからパフォーマンスデータを詳細に分析したい|Container Insights<br>Lambda Insights|
|アプリケーションの性能ボトルネックを特定したい| X-Ray|
|ユーザとAWSリソース間のトラフィックパフォーマンスをモニタリングしたい|Internet Monitor|
|パフォーマンスに影響を及ぼす上位の要素を明らかにしたい|Contributor Insights|
|EC2上で動作するアプリケーション(SAPなど)のモニタリングをしたい|Application Insights|
|ユーザの動きをリアルタイムで収集してパフォーマンス向上をしたい|RUM(Real User Monitoring)|
|システム全体のパフォーマンスを視覚化して分析したい|Service Map|
|システムのService Level Objective(SLO)を測定したい|SLO|
|<b>その他|
|機能をローンチするまえにテストをして問題を特定したい|Evidently|

# まとめ
システムの動作状況を正しく把握し、システム運用においてデータに基づく意思決定するために必要な情報が取得できていることが重要です。

CloudWatchを活用することで、可用性、信頼性、レイテンシー観点の問題を検出、調査、修正し、SLAを維持することが可能となります。これからも進化をし続けるCloudWacthに注目していきたいと思います。

# 参考
[Amazon CloudWatchの概要と基本](https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_AmazonCloudWatch_0330_v1.pdf "AWS Black Belt Online Seminar")
【Python】MojaCoderスペシャルジャッジの書き方！

## はじめに
2024 年 1 月 4 日、 MojaCoder に新しく **スペシャルジャッジ** が導入されました！  
Python でスペシャルジャッジの記述方法の解説がなかったため (yukicoder での解説があったくらい) 、このような記事を作成しました。
新しい機能を使って作問をしてみたい 作問er の方のお役に立てれば幸いです。

## 目次
1. はじめに
1. 目次
1. 仕様
1. 実装例
1. チートシート

## 仕様

スペシャルジャッジの仕様には以下のようなものがあります。
参考：[MojaCoderスペシャルジャッジ仕様](https://www.ochappa.net/posts/mjc-spjudge) (お茶の葉 様)
***
- 正誤判定はジャッジプログラムが正常終了かどうか、すなわち `RE` でないかどうかで判定されます。

これにより、`assert` 文を使って条件を満たさない場合に例外を発生させたり、 `raise` 文を使って例外を発生させたり、内部的に例外を発生させることにより、 `WA` と判定させることになります。  
例外を踏まず、正常終了した場合は `AC` となります。
***
- ジャッジプログラムが `TLE` , `MLE` , `CE` の場合は、 `JTLE` , `JMLE` , `JCE` と判定されます。

一般公開した場合やコンテスト中に `JTLE` , `JMLE` , `JCE` が発生することは好ましくありません。  
そのようなジャッジコードが出ないよう、十分にデバッグを行うよう努めましょう。

ジャッジのバグが発生しないようにするためにも、出力制限に気を付けて作問するべきでしょう。  
文字数も問題の判定の要素の場合は $N+1$ 文字で制限するなどで検討してください。

***

- 第 1 引数にテストケース入力ファイルパス、第 2 引数にテストケース出力ファイルパスが与えられます。

つまり、こう言うことです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779352/94d747b7-42e4-759b-9658-fa7df540fff1.png)
- 標準入力に提出解答の出力が与えられます。

提出プログラムの実行が行われて出力が終わった後に、その出力結果に対して評価を行うことになります。

- 標準出力、標準エラー出力は使用しません。

***

- メモリ制限は $1 \ \mathrm{GiB}$ 、実行時間制限は $3 \ \mathrm{sec}$ です。

問題を解くとき同様、ジャッジプログラムのメモリ制限や実行時間制限にも注意しましょう。

## 実装例 (Python)
次のような問題を実装することを考えます。
[問題リンク (MojaCoder)](https://mojacoder.app/users/loop0919/problems/ABN)
### 問題文
整数 $N$ が与えられます。 $A + B = N$ となる $0$ 以上の整数 $A, B$ を出力してください。

```md:入力
N
```

```md:出力
A B
```

### スペシャルジャッジ実装例
```py:スペシャルジャッジ
import sys

with open(sys.argv[1]) as in_testcase, open(sys.argv[2]) as out_testcase:
    # 入力ファイルから N を読み込む.
    N = int(in_testcase.readline())

    # 提出解答の出力から A, B を読み込む.
    A, B = map(int, input().split())

    # 与えられた A, B が条件を満たすか判定する.
    assert A >= 0 and B >= 0
    assert A + B == N

    # 標準入力が空であることを確認する.
    try:
        input()
        raise AssertionError
    except EOFError:
        pass
```

※ 最後の標準入力が空であることの確認がないと、末尾に不要な文字列がある解答も `AC` と判定されてしまいます。

## チートシート
以下、チートシートです。

```py:入力ファイル・出力ファイルを読み込む
import sys
with open(sys.argv[1]) as in_testcase, open(sys.argv[2]) as out_testcase:
   # ここからジャッジ用のコードを書く
   # ～～～
```

```py:1 行読み込み、変数に代入する
INPUT = in_testcase.readline() # 入力ファイルから
OUTPUT = out_testcase.readline() # 出力ファイルから
SUBMIT = input() # 提出解答から
```

```py:条件を満たすか判定する
assert X == Y # X と Y が等しい場合通過、そうでない場合例外発生 (WA)
```

```py:# 標準入力が空であることを確認する
try:
    input()
    raise AssertionError
except EOFError:
    pass
```
centos7におけるdomain/searchの変更

設定済みのcentosのdomain名の変更を行います。

**設定前**
`cent76.test.local`

**設定後**
`cent76.test2.local`

# host名の変更
`hostnamectl`コマンドを利用して変更を行います。

```text:変更前
# hostname
cent76.test.local

# hostname -A
cent76.test.local

# hostname -s
cent76

# hostname -d
test.local
```
`-A`　すべてのFQDNの表示
`-s`　ホスト名のみ表示(ドメイン除去)
`-d`　ドメイン名を表示


```text:変更実施
# hostnamectl set-hostname cent76.test2.local
```



```text:変更前
# hostname
cent76.test2.local

# hostname -A
cent76.test2.local

# hostname -s
cent76

# hostname -d
test2.local
```

# resolve.confのdomain/searchの変更
resolve.confの設定がある場合はこちらも変更します。

通常、`NetworkManager`を起動していると思いますが、こちらがデフォルトの場合は**いくら`/etc/resolve.conf`ファイルを編集しても`NetworkManager`が編集を書き戻す**ので、resolve.confファイルの編集を書き戻されないような設定から行います。


```text:NetworkManagerのDNS自動更新無効化
# vi /etc/NetworkManager/NetworkManager.conf
---------------------
[main]
#plugins=ifcfg-rh,ibft

↓

[main]
#plugins=ifcfg-rh,ibft
dns=none
---------------------
```


```text:NetworkManagerサービス再起動
# systemctl restart NetworkManager
```

<br>

`/etc/resolve.conf`の修正を行います。
```text:/etc/resolv.conf編集
# vi /etc/resolv.conf
---------------------
search test.local

↓

search test2.local
---------------------
```


```text:networkサービス再起動
# systemctl restart network
```

念のため`/etc/resolve.conf`が書き換わっていないか確認してください。

```text:/etc/resolv.conf確認
# cat /etc/resolv.conf
```

# 参考

https://atmarkit.itmedia.co.jp/ait/articles/1612/21/news033.html

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/networking_guide/sec_configuring_host_names_using_hostnamectl



https://www.unix-power.net/networking/post-896
改行をコントロールするためのカンタン手法

単語ごとに区切る英文と違って日本語の区切りは難しく、要素の端に文章が達したときには単語の途中であっても改行されてしまいます。

英単語はデフォルトでは途中で途切れそうになると自動で改行され、単語は常に一つの塊として表示され続けるので、日本語と織り交ぜても英単語の途中ではみ出しそうになると単語の前で改行されます。

じゃあ日本語を単語ごとに改行させたいというときはどうすればいいのか？ということですが、`<wbr>`+`word-break: keep-all`を組み合わせることで可能になります。

```html
<p>長い人生<wbr>一度や二度は、<wbr>道に迷ったり<wbr>行き先を<wbr>見失ったり<wbr>するもんさ。<wbr>そんな時<wbr>どうすればいいか<wbr>わかるか？</p>
```

```CSS
p {
	word-break: keep-all;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465106/30089d6e-3328-a8b9-f36b-7d42ab8bfae8.png)

超簡単・単純です。(昔ひそかに人気だったロボットアニメのセリフからもってきました）

:::note warn
上記とは別のプロパティーで枠線や要素を可変式にしています
:::

`<span>`+`display: inline-block;`の組み合わせ（`span`でなくて`div`とかでもOK）でも好きな箇所で改行させることはできますが、いかんせんコード量も増えて煩雑になりやすい上読みづらいのがよろしくない。

その分この方法ならhtml上は`wbr`を入れるだけで読みやすさはある程度担保できますし、コード量も節約できます。

ただいくつか問題があって、

- 改行できる最小単位（`<wbr>`の入ってない文節）より要素の幅が小さいと要素からはみ出る
- 単語・文節の長さによって文章がデコボコして読みづらい

というものがあります。
この方法は短い文章に適しているので、見出しやキャッチコピーなどに使うのがいいと思います。

---

ほかには***句読点で改行させる方法***もあります。

これも非常に簡単で、上記のCSSに`overflow-wrap: anywhere`を追加するだけ。

`<wbr>`で改行するのはもちろん、テキストが要素に収まらなかったら句読点で自動的に改行して、はみ出る部分は単語の途中でも改行してくれます。

```html
<p>もしも、もしもだ。宇宙旅行に行くとして好きなモノを、たったひとつ持っていけるとしたら<wbr>何を持っていく？</p>
```

```CSS
p {
	word-break: keep-all;
    overflow-wrap: anywhere;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465106/659170c3-63c9-2333-025f-c3a64d34b9a2.png)

でもこれも問題があって、`word-break: keep-all`の影響で句読点の前でも改行されてしまいます。

---

じゃあどう使い分けるのか？ということですが、強いメッセージ性のある箇所には`<wbr>`+`word-break: keep-all`を、記事など文章の読みやすさを重視する場合には+`overflow-wrap: anywhere`、もしくは何も設定しないがいいんじゃないかな、と思います。
Jetbrains WebStormで"type": "module"指定されたnodejsプロジェクトをtsｰnodeでデバッグする方法

割とはまり込んだので、後刻の備忘録として

# 想定
プロジェクトのフォルダ構成は以下の通り

```
root:
│  package-lock.json
│  package.json
│  tsconfig.json
│
├─.idea
|  ...
│
└─src
        index.ts

```


Package.jsonは以下の通り

```json
{
  "name": "untitled",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ts-node": "^10.9.2",
    "typescript": "^5.3.3"
  }
}
```

普通にtsconfig.jsonをこさえると以下のようになる

```json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

```
これだとmoduleが`commonjs`なので、ここを`node16`か`nodennext`にする。

書き換えた後は以下

```json
{
  "compilerOptions": {
    "target": "es2020",
    "module": "Node16",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

```

# Run/Debug Confの調整

index.tsを実行したいとする場合、

JavaScript fileに`src/index.ts`を指定する。加えてNode parameterに
`--import "data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));"`
を指定する。

こうすることで、Execute/Debugが可能になる。
Kaggle参戦記：上位チームの解法まとめ（1位～3位）

「[AIが書いた文章か人間が書いた文章かを見分けるコンペ](https://www.kaggle.com/competitions/llm-detect-ai-generated-text)」の、上位チームの解法が出そろいつつあります。今日は、そのうち、1位～3位のチームの解法を、(1)データセット、(2)特徴量（トークナイザ＆ベクトル化）、(3)分類モデルの観点で、まとめてみます。不勉強なもので、(2)と(3)の分類がちょっとあやふやなところがあるかもしれません。お気づきの点があればご指摘ください。

### 1位：[1st place short solution summary](https://www.kaggle.com/competitions/llm-detect-ai-generated-text/discussion/470121)
- **順位の変遷**
  - パブリック:9位（0.979）⇒プライベート：1位（0.987）
- **(1) データセット**
  - 合計で16万件の例文。うち人間の文章は4万件
  - 人間の文章：Persuadeコーパス全文＋一般的な文章
  - AIの文章：多様なLLM、プロンプトを使用。Persuadeコーパスにあわせて、プロンプトをチューニング
- **(2) 特徴量**
  - train + testのエッセイを使って訓練したdeberta-v3をトークナイザとして利用
  - deberta-v3-smallでプライベートLB0.943、largeでプライベートLB0.961を達成 
- **(3) 分類モデル**
  - [Ghostbasterアプローチ](https://huggingface.co/papers/2305.15047)を採用
  - LoRA でファインチューニングしたMistralモデル (mistralai/Mistral-7B-v0.1) 
  - 確信度付きの予測を出力し、弱ラベルとして利用


### 2位：[2nd place solution with code and data](https://www.kaggle.com/competitions/llm-detect-ai-generated-text/discussion/470395)
- **順位の変遷**
  - パブリック:17位（0.976）⇒プライベート：2位（0.983）
- **(1) データセット**
  - SlimPajamaデータセットから様々なLLMを使って約50万件の人間とAIの文章のペアを作成
  - Persuadeコーパスに対して言語モデル（LM）の微調整を行い、LLMに学生の文章を模倣したテキストを生成させた
  - DAIGT-V4-TRAIN-DATASET上で3つのモデルをファインチューニングし、アンサンブルに加えた
- **(2) 特徴量**
  - deberta-v3-largeでプライベートLB0.967を達成
- **(3) 分類モデル**
  - 一般的なモデル（詳細は不明）


### 3位：[3rd place solution](https://www.kaggle.com/competitions/llm-detect-ai-generated-text/discussion/470333)
- **順位の変遷**
  - パブリック:15位（0.976）⇒プライベート：3位（0.974）
- **(1) データセット**
  - データ前処理で、15以上のエラーがある文章のみ、deobfuscatorで修正
  - オリジナルのtrainデータに含まれない文字を削除／正規化
  - 1.1万件のリフレーズされた文章に対して、4つのモデルをトレーニング⇒4回のトレーニングごとにLBスコアを算出。数値が悪化したら前のデータセットに戻してまたやり直した。
  - [DAIGT | External Dataset](https://www.kaggle.com/datasets/alejopaullier/daigt-external-dataset)から、少しずつデータを増やしながら、誤分類したデータを人間500件、AI500件ずつ追加してモデルを繰り返しトレーニング
  - pileとslimpajamaデータセットを利用。短すぎる/長すぎるテキスト、コードや数学を含むテキスト、英語以外のテキスト、非文字/文字の比率が高いテキストをフィルタリング
  - パラメータの組み合わせが異なる、～35種類のオープンソースモデルを使用して文章を生成。50万件、100万件、120万件のサンプルを作成。
- **(2) 特徴量**
  - TfIdfパイプライン
- **(3) 分類モデル**
  - catboostとlightgbmの反復回数を250回増やし、VotingClassifierにweights=[0.05, 0.225, 0.225, 0.5]を使用
  - 12個のdeberta-v3-largeモデルを使用
  - 2段階の確率的重み付きアンサンブルを使用
  - 後処理として、各prompt_idのうちサンプルが1000件以上ある場合は、TfIdfの特徴量の次元削減を行い、人間の書いた文章との距離を算出し、予測値をスケーリングした


これら上位3チームは、いずれもパブリックLBが高く、プライベートLBでもさらにshake-upしたチームでした。めちゃくちゃカッコいい勝ち方ですね。彼らの共通点は、
・データの品質と多様性を吟味しつつ、大量のデータセットを構築していた
・deberta-v3の活用
・SlimPajamaデータセットの活用（3チーム中2チーム）
などがありますね。時間と手間をかけてでも、やるべきことをやっていたチームが最後まで生き残ったという感じでしょうか。

個人的には、3位のチームがやっていた「小さなデータセットからはじめて、誤分類したデータを追加していく手法」が、自分の頭からすっぽ抜けていたことが悔やまれます。まさにMLOpsとして、実務でやっていたはずのことなのに、すっかり忘れていました。Out of Memoryエラーに泣かされたときに、このアプローチをとるべきだったなあと思います。

1位のチームが参考にしていた、Ghostbasterアプローチというのも気になりますね。またそのうち論文を読んだら、シェアしようと思います。
How to Convert Outlook Emails in CSV File?

In the realm of email communication, Outlook stands as one of the most widely used platforms. However, extracting valuable data from emails in a structured format is often a challenge. To<a href="https://www.adviksoft.com/blog/how-to-export-outlook-emails-to-excel-with-date-and-time/"> export Outlook emails to CSV with date and time</a> emerges as a solution, allowing users to transform their email data into a versatile and easily manipulable format.

</h2>Reasons for Converting Outlook Emails to CSV</h2>

Database Integration:

CSV files are highly compatible and can be seamlessly integrated into various databases, facilitating efficient data management.
Data Analysis and Reporting:

CSV files provide a structured format, enabling users to perform data analysis, generate reports, and extract valuable insights from email data.
Migration and Backup:

Converting emails to CSV is a prudent approach for migration or creating backups, ensuring data security and easy retrieval.
Bulk Data Manipulation:

CSV files allow for bulk data manipulation, making it easier to update, edit, or organize large sets of email data.
Methods for Converting Outlook Emails to CSV: A Step-by-Step Approach

Using Outlook's Built-in Features:

Open Outlook:

Launch the Outlook application.
Select the Email Folder:

Choose the specific email folder containing the messages you want to convert.
Go to "File" Menu:

Click on the "File" tab.
Choose "Import/Export":

Select "Import/Export" and opt for "Export to a file."
Select "Comma Separated Values":

Choose "Comma Separated Values" as the export file type.
Specify Folder and Save:

Specify the destination folder, provide a file name, and click "Finish" to save the CSV file.
Using Third-Party Tools:

Download and Install:

Explore third-party tools like Advik Outlook to CSV Converter and download/install the software.
Launch the Tool:

Open the tool and connect it to your Outlook account.
Select Emails and Output Format:

Choose the emails or folders for conversion and select CSV as the output format.
Click "Convert":

Initiate the conversion process by clicking the "Convert" button.
Save CSV Files:

Save the converted CSV files to your preferred location.

Conclusion

Converting Outlook emails to CSV files is a strategic move for users seeking enhanced data flexibility. Whether for database integration, analysis, or migration purposes, CSV files offer a structured and easily manipulable format. By following the outlined methods, users can streamline their data management processes, making email data more accessible and adaptable to diverse requirements. Embracing this approach empowers users to unlock the full potential of their email data, fostering a more efficient and organized digital workspace.
Wear OS 搭載スマートウォッチで心拍数を表示する

## はじめに
Wear OS 搭載スマートウォッチに心拍数を表示したい。その方法を調べた

## 方法
調べたところ、以下の３つの方法があるもよう

- Google Fit API
2024年末でサポート終了とのこと

- Health Services 
Google Fit API に代わる方法で Google は今後これを推していきたいように見える

- センサー利用

今回は Health Services を利用して心拍数を表示してみる

## 実装

#### ライブラリ追加
```build.gradle.kts
  implementation "androidx.health:health-services-client:1.1.0-alpha02"
```
まだ alpha 版のもよう

#### 権限追加
```AndroidManifest.xml
    <uses-permission android:name="android.permission.BODY_SENSORS" />
```

#### 権限取得処理
実行時に `android.Manifest.permission.BODY_SENSORS` の権限取得処理必要
（実装例略）

#### HealthServiceClient 取得

```Kotlin
    private val healthClient: HealthServicesClient by lazy { HealthServices.getClient(getApplication()) }
```

#### コールバック処理実装
```Kotlin
    private val heartRateCallback = object : MeasureCallback {
        override fun onAvailabilityChanged(dataType: DeltaDataType<*, *>, availability: Availability) {
            if (availability is DataTypeAvailability) {
                Timber.d("dataType: $dataType, availability: $availability")
            }
        }

        override fun onDataReceived(data: DataPointContainer) {
            val heartRate: Double = (data.sampleDataPoints.firstOrNull()?.value as Double?) ?: 0.0
            // ここで取得した心拍数を利用！！
            Timber.d("heart rate: $heartRate")
        }

        override fun onRegistered() {
            super.onRegistered()
            Timber.d("onRegistered()")
        }

        override fun onRegistrationFailed(throwable: Throwable) {
            super.onRegistrationFailed(throwable)
            Timber.d("onRegistrationFailed throwable: $throwable")
        }
    }
```

#### コールバック登録/解除
```Kotlin
    // 登録
    healthClient.measureClient.registerMeasureCallback(DataType.Companion.HEART_RATE_BPM, heartRateCallback)

    ...
            
    // 解除
    healthClient.measureClient.unregisterMeasureCallbackAsync(DataType.Companion.HEART_RATE_BPM, heartRateCallback)
```
実際はコールバック登録時に `android.Manifest.permission.BODY_SENSORS` の権限チェック＆権限取得処理が必要

## 実行
Pixel Watch を腕に身に付けてアプリを起動したら、心拍数が表示された :ok_woman:

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141937/b6bd9beb-d031-5789-6306-a5fd925ba3f3.png" alt="drawing" width="200"/>

割と頻繁に（数秒毎に）数値が更新されて良い感じ :tada:

## 注意
- Health Services は Wear OS 3（SdkVersion 30）以上でのみのサポートのもよう

## 参考
https://developer.android.com/training/wearables/health-services?hl=ja
formタグの外の要素もリクエストパラメータに渡したい！を解決する方法

## 結論
```
<form action='' id='target'>
（中略）
</form>
```

のように、formにIDを設定しておいて、

```
<input form='target' name='outform'>
```

のように、formタグの外でもform要素にformのIDを入れると、formIDをsubmitした際にパラメータを渡せる。

## 検証コード
https://shimajima-eiji.github.io/Hosting2/for_blog/form_out.html

CodePenで埋め込もうと思ったけどsubmit（遷移）が必要なのでGitHubPagesでホスティングする。

## 発端・参考
https://note.com/kakidamediary/n/n85a5aa43749b

---

## ポエムとか
元々はReactだとオーバースペックすぎる簡単なWebアプリを作ろうとしていて、手頃なWebフレームワークを探していたところRemixに辿り着いたので、その過程でtableタグとformタグを組み合わせたいシーンが出てきた。
で、いつも何も考えずに

```
<form ...>
  <table>
    ...
  </table>
</form>
```

みたいに書いていたのだが、複数のformで値を使い回したいシーンが出てきた。
今回は結局JavaScriptの介入が必要になってしまったのだが、そもそもの話としてformタグの外の要素をformに埋め込むという方法を知らなかったので、凝ったことをしなければ使えそうな気がしたので、formタグの講義資料などでいつか役に立つことを期待する。
経過月数を小数点込みで確認したい（Ruby)

## あらまし
例えば退職された方が、その会社に何か月在籍していたのかを計算する際に「25ヶ月在籍してた」というのはとても簡単に計算出来るけど、日数まで含めて「24.67ヶ月在籍してた」という計算の仕方は意外とサンプルコードが転がっていないようです。

無ければ作れば良いという事で作成したので誰かの何かの役に立てれば。

## 考え方
年と月は簡単です。
上記の例では退職日と入社日の差分を取ったうえで"年"は12をかけて"月"と足すだけです。

"日"をどうやって小数点にするかですが、退職日から入社日の差分を取り、退職月の日数を取得して割り算をしています。(1月の場合は31日で割り、2024年2月の場合は29日で割ります）

これをせず雑に30で割ると、小数点以下が若干おかしな事になってしまいます。

……と思ってコード書いて完成したつもりでしたが見直してたらバグがありました。
2/2入社、2/29退職　0.97ヶ月　→　OK
2/1入社、2/29退職　1.0ヶ月　→　OK
1/31入社、2/29退職　0.93ヶ月　→　NG　（本来1.03になってほしい）

## 修正版　考え方
結構困りました。どうやって直したものかと思案していたのですが、
入社した月の在籍日数と退職した月の在籍日数をまとめて足してしまう事自体が駄目でした。よく考えたら

2024年1月は31日まであるので1日あたり約0.0322なのに対して
2024年2月は29日までなので、1日あたり約0.0344となるわけで、月によって1日の重みが異なるのです。
つまり同じ"日"という単位とはいえ、この2つは異なるものなので重みを考慮せずに足したり割ったりしてはいけませんでした。
最初にバグがあったのは、重みを考慮していなかったので最終的に0.0xズレていたのですね。

というわけで別々に計算する事で回避できました。
計算式
（入社月の末日 - 入社日）+1 /　入社月の末日
（退職月の末日 - 退職日）   /　退職月の末日
このように入社月と、退職した月の在籍日数を重みを考慮したうえでそれぞれ計算した後に、2つの差を取る事で正確な小数点を出すことができました。

ちなみに、この計算では月の途中で入社して月の途中で退職すると直感と合わない数値が出る事があります。

2023年12月16日入社
2024年1月15日退職の場合は1.0ヶ月在籍した事になります。

2024年1月16日入社
2024年2月15日に退職の場合、1.03ヶ月在籍した事になります。

直感的にはどちらも1.0ヶ月な気がしますが、2月という29日までしか無い月に15日まで在籍していたので1.03になるのは正しい結果です。



　

サンプルコードは久しぶりにRubyで書きました。

## コード
```:コード
require "date"

#入社日と退職日を設定
nyuusya = [2024,2, 1]
taisyoku = [2024, 2, 29]

#初期化
nyuusya_dt = DateTime.new(nyuusya[0], nyuusya[1], nyuusya[2])
taisyoku_dt = DateTime.new(taisyoku[0], taisyoku[1], taisyoku[2])

#入社月と退職月が何日まであるのか確認(うるう年を含めると28日～31日までありえる）
nyuusya_month_last_day = Date.new(nyuusya[0], nyuusya[1], -1)
taisyoku_month_last_day = Date.new(taisyoku[0], taisyoku[1], -1)

#整数部分（経過月数）
month =  ((taisyoku_dt.year - nyuusya_dt.year) * 12) + (taisyoku_dt.month - nyuusya_dt.month)

#小数点部分（端数部分）
days1 = ((nyuusya_month_last_day.day - nyuusya_dt.day)+1) / (nyuusya_month_last_day.day).to_f
days2 = (taisyoku_month_last_day.day - taisyoku_dt.day) / (taisyoku_month_last_day.day).to_f
days = days1 - days2

#小数点第2位で四捨五入する
print "この方の在籍月数は" , (month + days).round(2), "ヶ月です\n"

```
## 計算結果のサンプル
```:計算結果サンプル
nyuusya = [1985,4, 1]
taisyoku = [2024, 3, 31]
この方の在籍月数は468.0ヶ月です

nyuusya = [2024,2, 1]
taisyoku = [2024, 2, 29]
→この方の在籍月数は1.0ヶ月です

nyuusya = [2024,1, 1]
taisyoku = [2024,3, 31]
→この方の在籍月数は3.0ヶ月です

nyuusya = [2024,1, 31]
taisyoku = [2024, 2, 29]
→この方の在籍月数は1.03ヶ月です

nyuusya = [2024,1, 16]
taisyoku = [2024, 2, 15]
→この方の在籍月数は1.03ヶ月です
```
※なお、小数点第二位で四捨五入なので絶対大丈夫だと思いますが、浮動小数点の演算で丸め誤差が気になる場合はfloorメソッドを使用せず、bigdecimalという浮動小数点数演算ライブラリを使用してください。
jQueryでのthisの使い方

# thisとは
`this`は、jQuery内で使われる特殊なキーワードで、イベントが起こった要素を取得することができます。記述する際は`$(this)`と書きクォーテーション`("`や`')`は必要ありません。
# 使い方
下記のように、複数のli要素にclickイベントは設定されていた場合、実際にクリックされたli要素にだけ処理を行いたい場合があります。このような場合にthisを用いて、実際にクリックした要素のみイベントを処理することができます。
```html
<ul>
    <li>リスト1</li>
    <li>リスト2</li>
    <li>リスト3</li>
</ul>
```
```js
//どのli要素をクリックしても、クリックイベントが発生
$('li').click(function() {

    //$(this)には実際にクリックされたli要素が入る
    $(this).css('color', 'red');
});
```

また、応用としてclickイベントの中で、クリックされた要素のインデックス番号を取得することができます。下記の`$(this)`にはクリックした要素が入ります。それをindexメソッドの引数に指定することで、クリックした要素のインデックス番号を取得することができます。
```html
<ul>
    <li>インデックス0</li>
    <li>インデックス1</li>
    <li>インデックス2</li>
</ul>
```
```js
$('li').click(function() {

    //クリックしたli要素のインデックス番号が変数indexに代入される
    var index = $('li').index($(this));
});
```
Docker で Palworld の専用サーバの複数管理環境を作ってみる

# モチベーション

1. パルワールド、マルチで遊ぶのも楽し～
2. 遊ぶ相手やDiscord サーバとかで PalServer も分けたいかも
3. Docker でサクッと建てれるようにした


# やったこと

steamcmd 公式 Docker Image ベースで Palworld の Image を作成

```Dockerfile:Dockerfile
FROM cm2network/steamcmd:latest
RUN ./steamcmd.sh +login anonymous +app_update 2394010 validate +quit
WORKDIR /home/steam/Steam/steamapps/common/PalServer
CMD ["./PalServer.sh"]
```

```b
docker build -t pal-world:v0.9 .
```

ディレクトリ構成

```bash
.
├── hoge-server 
│   ├── docker-compose.yml
│   └── Saved               # Save データとか入ってるやつ
├── fuga-server 
│   ├── docker-compose.yml
│   └── Saved
⋮
└── piyo-server
    ├── docker-compose.yml
    └── Saved
```


```yaml:docker-compose.yml
version: "2"
services:
  pal_server:
    image: pal-world:v0.9
    ports:
      - "<外部公開ポート番号>:8211/udp"
    volumes:
      - ./Saved:/home/steam/Steam/steamapps/common/PalServer/Pal/Saved
```

動かしたいディレクトリで `docker-compose up -d`を実行する。

# 課題

- 設定を弄るために ini ファイルを編集する場合、container に入る必要がある
- 特にバックアップスクリプトとか書いてないので書かないと...

# 参考サイト等

- [パルワールド テックガイド](https://pocketpair-redirect-iptracker-dot-pocketpair.an.r.appspot.com/v1/palworld/helpserver?from=ingame)
- [CM2Walki/steamcmd](https://github.com/CM2Walki/steamcmd)
【パルワールド】個人で建てたマルチサーバーにログイン時、無限ロードが発生してしまう不具合の対処方法

参考ページ
[海外兄貴の対処方法](https://www.reddit.com/r/Palworld/comments/19cl66w/so_basically_for_those_with_broken_save_files/)

# 症状
パルワールドの、個人が立ててくれたサーバーに接続時に無限にロードしてしまう。

# 原因（おそらく）
・症状が発生した人がログアウト（オフライン）中、所属しているギルドのメンバーの誰かが脱退する

## 以下対処方法を行うデメリット
・プレイヤーのレベルが１になってしまう

## 対処方法
### 1. 必要なツールを取得する
[セーブデータ解析ツール](https://gist.github.com/cheahjs/300239464dd84fe6902893b6b9250fd0#file-convert-to-json-bat)
上記リンクよりGitHubのページへ行き、ツールをダウンロードする。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319500/4e23ac24-6232-e9d6-ad15-157fc62aed79.png)

zipファイルとexeファイルをダウンロードする。
ダウンロードできたら、zipファイルを適当な場所に解凍する。
そして、解凍したフォルダ内に、ダウンロードしてきたexeファイルを配置する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319500/279d6bc4-bb01-1770-9d2f-1f5c1987ac62.png)

●Pythonのインストール
Python 3 以上のバージョンをインストールする。
[Pythonインストール参考](https://www.python.jp/install/windows/install.html)

### 2. 無限ロードの発生したプレイヤーのセーブデータをバックアップする
該当プレイヤーの特定方法
・最後にログアウトした日付（できれば時間も）
**最後にログアウトした日時 = 該当セーブデータの更新日時**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319500/d5bfc665-b1bd-1d12-c3b3-26dd8f8063cb.png)

バックアップを取ったら、サーバー側のプレイヤーセーブデータを削除する。

### 3. 無限ロード発生者に再度ログインしてもらう
・作業中、無限ロード発生者以外は、ログインしないようにしてもらう。（ファイル操作ミスをしないため）
・新しくキャラクターデータを作成してもらう。
・キャラクターの外見データは、新しく作る方になるため、慎重に作成してもらう。
・キャラクターデータを作成し終えたら、ログアウトしてもらう。
・サーバーを一度落とす。（念のため）

### 4. 壊れたセーブ、新しいセーブそれぞれをjsonに変換する
**壊れたセーブファイルと、新しいセーブファイルの名前が同じ場合があります！間違えないように！**
**それぞれのファイルを、別々のフォルダに入れて作業することをおすすめします**
 3. までの手順で取得した、.sav拡張子のセーブデータを、.json形式に変換をする。
jsonに変換したい.savファイルをドラッグし、1. の手順で準備したツールの「convert-single-sav-to-json.bat」にドロップする。
コマンドプロンプトが開き、「Y/N」と聞かれるので、「Y」を入力する。
変換元の.savファイルと同じフォルダ内に、jsonファイルが生成されます。

### 5. 壊れているほうのデータを、新しいデータに移植する
1. 壊れているほうのjsonファイルをテキストエディタ（メモ帳など）で開く。

2. "PlayerCharacterMakeData" 以下、ファイルの一番下までを選択し、コピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319500/c9ba5b91-1402-1863-d4b0-e85ebc1ec46f.png)

3. 新しいほうのjsonファイルをテキストエディタ（メモ帳など）で開く。
4. "PlayerCharacterMakeData" 同じところに張り付ける。
　※位置がずれないように確認してください。

### 6. 作業を行ったjsonファイルを、.savファイルに変換する
.savに変換したい.jsonファイルをドラッグし、ツールの「convert-single-json-to-sav.bat」にドロップする。
コマンドプロンプトが開き、「Y/N」と聞かれるので、「Y」を入力する。
変換元の.jsonファイルと同じフォルダ内に、.savファイルが生成（上書き）されます。

### 7. サーバー側プレイヤーデータのところに、作業した.savファイルを配置する
PowerAppsとPowerAutomateでメール下書きを保存する

# 背景
メールをいきなり送るのではなくまずは下書きに保存してチェックしてから送信したいケースで、本文にリッチテキスト形式(HTML)を受け渡す際にハマりました。結論からいうと、PowerAppsからPowerAutomateへ本文文字列を受け渡す際、本文(HTML)内のダブルコーテーションをシングルコーテーションに変換してから受け渡せばOKでした。

# 詳細
PowerAppsからPowerAutomateフローへ本文データを受け渡す際、PowerApps側で下記式で文字列変換しておく。
```
Substitute(RichTextEditor.HtmlText,"""","'")
```
文字列として「”」を指定したい時は「""」と書く。

その後PowerAutomateで下記のHTTP要求で下書きが作成される。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670355/5216be9b-0195-0e56-0913-fcdfb634ea37.jpeg)

# 所感
理屈は分かりませんが、解決策が見つかって良かったです。。。
あれこれ試してみるもんだ。
Laravel 業務で使ってるEloquentでデータベースを操作する方法

## Eloquentについて
Laravelフレームワークに組み込まれているデータベースを操作するための便利なツールのようなものです
具体的にはデータベースのテーブルと対応するモデルクラスを使ってデータベースを操作する認識
 - モデルとはテーブルの内容を定義したクラスのこと

 - Eloquentのメリット
     - モデル間の関連性、1対1、1対多、多対多などを簡単に定義し、操作できること

```
例 usersテーブルとfoodsテーブルが1対多の場合、それぞれのモデルクラスに下記を追記
// Userクラス 親
    public function foods()
{
    return $this->hasMany(Food::class);
}

//Foodクラス　　子
    public function user()
    {
        return $this->belongsTo(User::class);
    }
```

##  Eloquentを使ったデータベースを操作する書き方
```
//ローカル環境で実際にphp artisan tinkerを使ってみてみます
// Userのidが1を取得
 $user = User::find(1);
// Userのidが1の人が持ってるfoodsの情報を全部取得する
 $foods = $user->foods;

 //下記のコードでも上記と同じ結果
 // $foods = User::find(1)->foods;
 // $foods = Food::where('user_id', 1)->get();

// Userのidが1の人が持ってるfoodsのinfoのデータが「test」かつlimit_dateが「2023-05-31」のレコードを取得
 $foods = $user->foods->where('info', 'test')
 　　　　　　　　　　　　　　　　　　　　　　　　　　　　->where('limit_date', '2023-05-31');

```

データベースを操作する方法はEloquent以外にもSQLクエリとクエリビルダがあるけど、リレーション周りの紐付けが面倒だと思うので自分はほぼ使ってません。特に複雑な関連構造のだと書くコードも面倒なものになる認識
だけどSQLの書き方を網羅してるとEloquentでもより明確にデータベースを操作できるのでEloquent書きながらでも裏でどんなSQL構文が処理されてるか意識するように習慣づけていきます！
ソケット用の2つのファイルディスクリプタ

# ソケット用の2つのファイルディスクリプタ
UNIXパイプラインを考えてみましょう：

```
     データ生成 | データ処理 | データ消費
```

データ処理プログラムには、データを読み込むためのパイプと、データを書き込むためのパイプの2つがあります。データ生成が終了し、最初のパイプを閉じると、データ処理はEOFを検出し、処理を終了して次のパイプを閉じます。その時点で、データ消費はEOFを検出し、データの消費を終了します。

しかし、このマシン上でデータ処理プログラムを実行する代わりに、別のマシンで実行したい場合はどうでしょうか。問題ありません。リモートマシン上のデータ処理サーバーにTCP接続を作成します。ローカルマシンでは、データ生成がTCP接続にデータを書き込み、データ消費がTCP接続からデータを読み込みます。データ生成がソケットを閉じると、ローカルマシンはTCPを介して`FIN`をリモートマシンに送信します。データ処理は`EOF`を検出し、処理を終了して接続を閉じます。その後、リモートマシンはTCPを介して`FIN`をローカルマシンに送信します。データ消費は`EOF`を検出し、データの消費を終了します。

もしTCP接続がUNIXパイプのように、読み込みディスクリプタと書き込みディスクリプタの2つのUNIXファイルディスクリプタとして表現されていたら、すべてが完璧に機能したでしょう。カーネルは、書き込みディスクリプタが閉じるとTCP接続にFINを送信します。TCP接続でFINを受信すると、読み込みディスクリプタを閉じます。

しかし、BSDソケットの設計者は、2つの明確なファイルディスクリプタを1つの読み書きファイルディスクリプタに統合することにしました。データ生成プログラムが終了しても、データ消費プログラムで同じファイルディスクリプタが開いているため、カーネルはFINを送信すべきだとは認識しません。

BSDソケットの設計者は、TCP接続を介してFINを送信するための`shutdown(fd,1)`システムコールを導入しました。これは、UNIXのファイルディスクリプタが避けるように設計された、デバイス固有の問題です。データ生成プログラムはパイプでは機能しますが、TCP接続では機能しません。
Python 3 エンジニア認定基礎試験対策10 - 標準ライブラリミニツアー

# はじめに
Python3エンジニア認定基礎試験の対策として自分用に執筆しています。

:::note warn
この記事はPython・執筆学びたての初心者が執筆しています。間違いがあるかもしれませんので、ぜひ各項目にある**参考文献**も確認してください。また、誤りがあればコメントで教えていただけると幸いです。
:::

# 標準ライブラリミニツアー

## OSへのインターフェース

`os`モジュールはOSと対話するための関数を提供する

```Python
>>> import os
>>> os.getcwd()
C:\\Python39
>>> os.chdir('/server/accesslogs')
>>> os.system('mkdir today')
0
```
ファイルやディレクトリの管理作業のために使えるモジュール `shutil`

```Python
>>> import shutil
>>> shutil.copyfile('data.db', 'archive.db')
archive.db
>>> shutil.move('/build/executables', 'installdir')
installdir
```

## ファイルのワイルドカード表記

`glob`モジュールは、ディレクトリのワイルドカード検索からファイルのリストを生成するための関数を提供する

```Python
>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']
```


## コマンドライン引数

コマンドライン引数は`sys`モジュールのargv属性にリストとして保存される。今回の例は、コマンドライン上に`python demo.py one two three`と入力した際の実行例

```Python
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']
```

## 文字のパターンマッチング

`re`モジュール。正規表現に使われる。

```Python
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
```

## 数学

`math`モジュール。浮動小数点演算など。

```Python
>>> import math
>>> math.cos(math.pi / 4)
0.70710678118654757
>>> math.log(1024, 2)
10.0
```

`random`モジュールは乱数の生成。

```Python
>>> import random
>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10)   # 0～100の間でランダムの数値
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random()    # 0～1の間でランダムな数値
0.17970987693706186
>>> random.randrange(6)    # range(6)の中でランダムの数値
4
```

`statistics`モジュールは数値データの基礎的な統計的特性を計算（平均、中央値、分散等）

```Python
>>> import statistics
>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
>>> statistics.mean(data)
1.6071428571428572
>>> statistics.median(data)
1.25
>>> statistics.variance(data)
1.3720238095238095
```

## インターネットへのアクセス

`urllib.request`はURLからデータを取得する
`smtplib`はメールを送信する

## 日付と時刻

`datetime`モジュールは日付や時刻を操作する。

```Python
>>> from datetime import date
>>> now = date.today()
datetime.date(2024. 1, 25)
```

## データ圧縮

`zlib`, `gzip`, `bz2`などの複数のモジュールでサポートされる

## パフォーマンスの計測

`timeit`モジュールで相対的なパフォーマンスについて調べることができる。

```Python
>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791
```

## 参考文献

https://docs.python.org/ja/3.9/tutorial/stdlib.html
textメソッドについて

# textメソッドとは？
textメソッドは、jQueryで要素のテキストコンテンツを取得または設定するためのメソッドです。

# 使用方法
jQueryではCSSだけでなくtextメソッドを用いることでHTMLそのものを変更することができます。textメソッドは、`$('セレクタ').text('書き換える文字列');`のように記述します。
また、引数を指定せずに用いることで、要素内の文字列を取得することもできます。
```html
<h1>こんにちは</h1>
<p>Progate</p>
```
```js
//文字列を書き換える場合
$('h1').text('こんばんは');    //h1要素内を引数の文字列で変更

//文字列を取得する場合
var text = $('p').text();   //p要素内の文字列「Progate」を取得
```
Webサイトのアクセシビリティを拡張機能でチェックしてみる

昨年開催されたアクセシビリティカンファレンス福岡に参加してから、きちんとWeb Accesibilityの勉強をしよう！となったので自分の勉強備忘録シリーズとして発信していこうと思います。

https://fukuoka.a11yconf.net/

今回は自分の現在地を知る、ということで、すでに世に送り出したWebサイトたちってアクセシビリティはどれくらい担保できているんだ？という目線で具体的にイメージを掴むための方法についてChromeの便利な拡張機能メモを残します。（ちなみに私はArcをメインブラウザとして使っていますが、現状Arcでも問題なく動いています！）

## ブラウザ上でWebサイト全体を診断してくれる拡張機能

【axe DevTools】

https://chromewebstore.google.com/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd

### 特徴
- 操作がシンプルで分かりやすい（DevTools内で操作できる）
- 実際の画面を見ながらアクセシビリティが担保できていない具体的な箇所について、どこにどのような問題があるのか教えてくれる
- 参照元のガイドラインも併せて提示してくれる
- 具体的な対応方法も教えてくれる

これでWebサイトをチェックすることで、実際にどこに問題があって、それらをどう対処すれば良いのか実践的にイメージがつかめるので、個人的にはとてもよい取っ掛かりだったなと思います。ここからそれらの問題がなぜ問題なのか、等は別途掘り下げて行こうと思います。

解説の動画もめっちゃ分かりやすいので備忘録メモとして書くこともほとんどないのですが、動画で説明されているUIと若干違うようなので、私が使ってみたスクショも置いておくことにします。

（良い感じのサンプルサイトがなかったので、知人の個人開発サイトを許諾を得て拝借してきました。ありがたや！）

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2487729/a05793e5-e13a-7e11-7a9b-0e41416ac461.png)

ちなみにとっても分かりやすい本家の解説動画はこちら↓

https://www.youtube.com/watch?v=iRGB40c_YJc

### 診断結果の解説サイトが便利
たとえば上記の例でいうと、コントラスト比を担保する必要があるよ！という指摘で、more informationに遷移すると下記のような内容が解説されています。

- 修正方法
- なぜ重要なのか
- ユーザーへの影響
- 参照されている規格

下記URLで指摘内容の詳細が確認できます。
https://dequeuniversity.com/rules/axe/4.8/color-contrast?application=axechrome&lang=ja

有料プランにすると検証履歴が保存できたりと、使用できる機能も増えるようです。
引き続き使ってみようと思います！
ActiveRecod では Relation テーブルに相当するモデルを定義せずに many to many relationship を定義できる

# 結論

`has_and_belongs_to_many` を使う。

```rb
class Part < ApplicationRecord
  has_and_belongs_to_many :assemblies
end
```


# `has_and_belongs_to_many` vs `has_many :through`

> Choosing which way to build a many-to-many relationship is not always simple.
> If you need to work with the relationship model as its own entity, use `has_many :through`.
> Use has_and_belongs_to_many when working with legacy schemas or when you never work directly with the relationship itself.

なるほど



# Ref.

https://api.rubyonrails.org/v7.1.3/classes/ActiveRecord/Associations/ClassMethods.html

https://guides.rubyonrails.org/association_basics.html#has-and-belongs-to-many-association-reference
【Stable Diffusion WebUI】エラー「failed assertion `commit command buffer with uncommitted encoder'」の原因

## エラー概要
以前まで普通にStable Diffusion WebUIを使えていたのに、なぜかとある日以下のエラーになった。無事に解決できたので共有します。

```
To create a public link, set `share=True` in `launch()`.
Startup time: 14.1s (launcher: 0.7s, import torch: 5.8s, import gradio: 1.6s, setup paths: 2.0s, other imports: 3.3s, load scripts: 0.3s, create ui: 0.2s).
Creating model from config: /Users/xxx/xxxx/stable-diffusion-webui/repositories/stable-diffusion-stability-ai/configs/stable-diffusion/v2-inference-v.yaml
LatentDiffusion: Running in v-prediction mode
DiffusionWrapper has 865.91 M params.
Applying attention optimization: InvokeAI... done.
-[IOGPUMetalCommandBuffer validate]:200: failed assertion `commit command buffer with uncommitted encoder'
./webui.sh: line 254: 56657 Abort trap: 6           "${python_cmd}" "${LAUNCH_SCRIPT}" "$@"
```


`webui-macos-env.sh`の`COMMANDLINE_ARGS`は以下で実施していました。

```
export COMMANDLINE_ARGS="--skip-torch-cuda-test --upcast-sampling --no-half-vae --no-half --use-cpu interrogate --lowvram"
```

## Mac環境
機種ID：MacBookPro18,3
macOS：Monterey
チップ：Apple M1 Pro
メモリ：16GB

# エラーの原因
エラーメッセージは、GPUのメモリが不足している、GPUのコマンドバッファが適切にコミットされていない、などの理由があると言っているっぽい。

PyTorchが使用するGPUメモリの最大量を制御することでメモリ不足によるエラーを回避することができるらしい。

`MPS backend out of memory`というエラーが出た場合も同様の原因であるらしく、こちらも参考になりました。

[MPS backend out of memory #9133](https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/9133)

# 解決方法

PyTorchが使用するGPUメモリの最大量は`PYTORCH_MPS_HIGH_WATERMARK_RATIO`で設定できます。`1`に近いほどGPUメモリを使用します。デフォルトでは`1`になっている。

ということで、`webui-user.sh`に以下を追加したらエラーがなくなりました。

```sh
# PyTorch settings
export PYTORCH_MPS_HIGH_WATERMARK_RATIO=0.7
```
【SwiftUI】Textの行間スペースを調整する

# はじめに
Textの行間スペースを調整するという内容です。
どこのことだ？と思うかたもいると思うので画像で説明します。

![スクリーンショット 2024-01-24 21.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/bcdf28c3-edae-2154-caa3-a6c79ccede15.png)

改行された文と文の間のスペースを本記事では行間スペースと表現しています。

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2024-01-24 at 21.57.08.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4ba10179-b751-1a03-5847-042ec8c25bff.gif)

# サンプルアプリの実装
```diff_swift
import SwiftUI

struct ContentView: View {
    @State private var lineSpacing: CGFloat = 0.0
    
    var body: some View {
        VStack {
            Text("""
                 あああああああああああああああああ
                 あああああああああああああああああ
                 あああああああああああああああああ
                 あああああああああああああああああ
                 """)
+           .lineSpacing(lineSpacing)
            
            Stepper(value: $lineSpacing) {
                Text("lineSpacing: \(lineSpacing)")
            }
        }
        .padding(20)
        
    }
}
```

# おわり
Textのheightを小さくしたいときに使えそうですね

# 公式ドキュメント
https://developer.apple.com/documentation/swiftui/view/linespacing(_:)
MacやLinuxで圧縮したZipファイルを文字化けせずにらくらく解凍できる【unkozip】を作ってみた

## はじめに
はじめまして。たいです。普段は高校生をしています。
MacやLinuxで圧縮したZipファイルをWindowsで解凍するときどうしてます？
ネットで検索すると7Zipとかのソフトを使う例が多いですが、できればソフトをインストールしたくないケースもあると思います。そんなときインストールせず1ファイルをダウンロードするだけで文字化けを回避しつつ解凍できるソフトを作ってきました。
ソースはGitHubにあります。ライセンスはMITです。

https://github.com/taiseiue/unkozip

## 使用法
基本的にはWindowsの標準機能で解凍してみて、文字化けしたらこのソフトを使ってください。

はじめに、[unkozipのリポジトリ](https://github.com/taiseiue/unkozip/releases)から`unkozip.exe`をダウンロードしてください。

#### 解凍(GUI)
解凍したいファイルを`unkozip.exe`にドラッグアンドドロップするだけで解凍できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935008/2d005cc0-d9e4-9d9d-0d16-8ff45b86598d.png)

#### 解凍(CUI)
パスの通った場所やホームディレクトリ(`%USERPROFILE%`)にソフトをコピーしておけば、コマンドラインからも使用できます。コマンドの構文はこんな感じです。Zipファイル以外は省略できます。

```sh
unkozip Zipファイル -o 解凍先ディレクトリ -c 解凍で使用する文字コード名 --mcp 解凍で使用する文字コードのコードポイント(後述)
```

使用例はこんな感じ。

```sh
: macOSとかで圧縮したテスト.zipを解凍する
unkozip テスト.zip

: テスト.zipをoutputに出力する
unkozip テスト.zip output

: Windowsで圧縮した(Shift-JISで圧縮した)テスト.zipを解凍する
unkozip テスト.zip -c shift_jis

: 上と同じ意味(コードポイントを使用)
unkozip テスト.zip -mcp 932
```

## なぜこんな名前なの？
A. `unzip`に似てるから。
適当ですn(((

## 実装方法とか
内部的には.NETの[ZipFIle.ExtraceToDirecotry](https://learn.microsoft.com/ja-jp/dotnet/api/system.io.compression.zipfile.extracttodirectory?view=netframework-4.6)メソッドを呼んでいるだけです。

コマンドライン引数をいい感じに処理するのにCommandLineParserを使いました。意外と便利ですねこれ。
今度ほかのソフトにも使ってみたいところです。CommandLineParserの使い方はこの記事が参考になりました。

https://qiita.com/kawaidainf/items/0aeace9a49b9770e2545

あと、実行ファイルをひとつにまとめるのはこちらで紹介されているFodyも使いました。

https://marunaka-blog.com/c-sharp-embed-dll-file/2224/
SharePointからファイルをダウンロードしてみた

# 目的
SharePoint Online のライブラリのファイルをPnP.PowerShellで取得してみた。
スクリプトファイルのあるフォルダ配下に以下のフォルダを作成します。

* Logフォルダ：transcript ログを保存する
* Downloadフォルダ：ダウンロードしたファイルを保存する

## サンプル

* 設定する変数
* $siteUrl = "https://tenant.sharepoint.com/sites/name",

<font color='red'>このサンプルでは、SharePointのライブラリ内のサブフォルダは考慮していません。</font>

https://gist.github.com/winsquarejp/8825caf861128552bea8509ba5571178
docker-machine Waiting for ssh to be availableで止まる




環境：windows10

PowerShellで

docker-machine create --driver hyperv machine-name

を実行したところ


...Waiting for ssh to be available

から動きませんでした。

```
docker-machine ls 
```
で状況を確認したところ
```
Unable to query docker version: Get https://123.123.123.123:2376/v1.15/version:x509:certificate has expired or is not yet valid
```

と証明書関係でエラーになっていることがわかった。

###### 試したこと
デバッグをしてみる
```
docker-machine --debug create --driver hyperv machine-name
```
###### 実行結果
```
SSH cmd err, output: exit status 255:
Error getting ssh command 'exit 0' : ssh command error:
command : exit 0
err     : exit status 255
output  :
```
上記がループされていた。原因がよくわからなかった。



###### 試したこと2

証明書を再作成
```
docker-machine regenerate-certs --client-certs
```

###### 結果
変わらなかった。証明書の期限切れではないようだった。

###### 試したこと3

sshログインしてみる
```
ssh -i ./id_rsa docker@123.123.123.123
```


###### 実行結果
```
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
```

これは鍵の権限が400か600でないとダメなのに、ほかのユーザにも権限があるから変えないとダメだそう。

鍵のファイルからプロパティ→セキュリティ→自分のユーザーをフルコントロールにし、その他を削除して再度SSHに接続。入ることができて、docker-machineも無事に作成することができました。




###### 感想
エラーの原因を特定するログを出すのに苦戦してしまいました。。。
Next.js 14にlinariaを入れたらエラー出た話

ふとwebアプリ作ったろって思い立ったのでNext.jsにlinariaの設定して動かしたら、まあなんとも面倒くさそうなエラーが発生。

```
Using the "css" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly.
```

あれ？nextで使えなかったっけ？(以前使えるみたいな記事見かけた気が…)
Babelの設定いじればなんとかなるもんなんですかね。


## なにはともあれ僕の環境まわり

- Ubuntu 22.04(WSL2) 
- node v20.8.0
- next v14.0.4
- linaria v6

### 備考
nodeはnodenvを使用。
nextjsは `npx create-next-app@latest` で設定。


# 結論は最初に言う
代替案あったので諦めた！(ごめん)


## なにをしたのかって話

これで終わったらなんの記録にもならないしつまらないので備忘録的なことを書き連ねる↓

まずは思考放棄でエラー内容でググってそれっぽい記事を総当たり。
5～6件ググって当てはまりそうな感じの見当たらなかったのでlinariaのsetupの項目をひたすら見る。

https://github.com/callstack/linaria?tab=readme-ov-file#setup

ふむふむ。わからん。
babelの設定うんたらの話が出るのかと思いきや見当たんない。

ってかエラー内容的にnext側のエラーっぽいし、nextのドキュメントに書いてあんじゃねって見たらすぐ見つかった。

https://nextjs.org/docs/app/building-your-application/styling/css-in-js

> The following libraries are supported in Client Components in the app directory (alphabetical):

訳: 次のライブラリは、appディレクトリ内のクライアント コンポーネントでサポートされています。

> chakra-ui
>kuma-ui
>@mui/material
>pandacss
>styled-jsx
>styled-components
>style9
>tamagui
>tss-react
>vanilla-extract

なるほど、appディレクトリ使ったルーティングでは一部のcss-in-jsしかサポートしてないのね。
やっぱ公式がいっちゃんわかりやすいって事。
さくっと諦め、、、ん？

https://nextjs.org/docs/app/building-your-application/styling/css-modules

CSSの拡張モジュール！？

あぁ、なんか最初っから入ってた`page.module.css`とかってやつか。
完全にスルーしてた。

なかなかいいじゃん。
ちょっと使ってみた感じ使い勝手も申し分ない。
なにより外部のライブラリ使わなくていいってのは楽。

今は完全に趣味で作っているだけなので一旦はこのまま進めるってことで諦めた。(特にjsから変数渡すとか無いと思う…多分)

入れる方法あったら入れようかなとそれくらいのモチベーション。
ちなみに今作っているアプリの話とかは後日やる。


# 教訓(多分月一で繰り返してる気かする)
まずはドキュメント読もう！
macでzipファイルを解凍するときに使うコマンド

# この記事は何？
mac環境にて zipファイルを解凍するためのコマンドのメモです。
以下の３種類紹介します。

- `unzip`
- `ditto`
- `7z`

# unzip

### 基本形式
```sh
unzip [ファイル名.zip]

# パスワード付きの場合
unzip -P [パスワード] [ファイル名.zip]
```
###  例
```sh
unzip archive.zip
```

パスワード付きの場合
```sh
unzip -P Password archive.zip
```

# ditto

### 基本形式
```sh
ditto -V -x -k --sequesterRsrc --rsrc [ファイル名.zip] [出力先ディレクトリ]

# パスワード付きの場合
ditto -V -x -k --sequesterRsrc --password --rsrc [ファイル名.zip] [出力先ディレクトリ]
```
###  例
```sh
ditto -V -x -k --sequesterRsrc --rsrc archive.zip .
```
パスワード付きの場合: コマンド実行後にパスワードを入力します。
```sh
ditto -V -x -k --sequesterRsrc --password --rsrc archive.zip .
```

# 7z
### インストール

```sh
brew install p7zip
```

### 基本形式
```sh
7z x "[ファイル名.zip]" -o"[出力先ディレクトリ]"

# パスワード付きの場合
7z x -p[パスワード] "[ファイル名.zip]" -o"[出力先ディレクトリ]"
```
###  例
```sh
7z x archive.zip -o"."
```
パスワード付きの場合
```sh
7z x -pPassword archive.zip -o"."
```

# 最後に
unzipだけで十分だと思ったら開けないファイルがあり、結局３種類使い分ける羽目になりました。どれか使えば開けるはず...。