OmniAICreator/Qiita-1.07M huggingface dataset:
axiosでCookieが送信できず困った話

# はじめに
完全に備忘メモになります。自分の苦しんだ時間を忘れないように書いておこうと思いました。
もし同じようにハマっている方がいたら参考なると幸いです。

# 発生したこと
勉強も合わせて、Next.jsで作ったフロントエンドのアプリからGo(echo)のAPIを使おうとした場合にCORSエラーになり、正しく動きませんでした。
発生当時はCookieだとはわかっておらずなんやかんやで1日溶かしました。。

# 使用環境
## フロントエンド
- Next.js : 13.4.5
- React : 18.2.0
- Axios : 1.4.0

## バックエンド
- Go : go1.20.4
- Echo : 3.3.10

# やりたかったこと
フロントエンドからバックエンドにリクエストする際に`csrf`というCookieを付与してリクエストすることで、バックエンドは正常に処理してレスポンスを返却します。
Go側ではローカルと特定の環境は許可するように仕込んでいました。PostmanやCurlでのリクエストで疎通も確認できていました。（以下は抜粋です）
```Go:router/router.go
.
.
.
	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"http://localhost:3000", os.Getenv("FE_URL")},
		AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept,
			echo.HeaderAccessControlAllowHeaders, echo.HeaderXCSRFToken},
		AllowMethods:     []string{"GET", "PUT", "POST", "DELETE"},
		AllowCredentials: true,
	}))
	e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
		CookiePath:     "/",
		CookieDomain:   os.Getenv("API_DOMAIN"),
		CookieHTTPOnly: true,
		CookieSameSite: http.SameSiteNoneMode,
	}))
	e.POST("/hoge", cc.Hogehoge)
.
.
.
```

# 結論
問題はaxiosのリクエスト時にwithCredentialsオプションを設定していなかったことにありました。このオプションが設定されていないと、Cookieが送信されません。
実際に記述した内容は下記のとおりです。
```typescript:utils/Api.ts
    const response = await axios({
      withCredentials: true, // ←これを追加
      method: "POST",
      url: "http://localhost:8080/hoge",
      data: data,
    })
```
ちなみにREADME.mdにも説明が記載されていました。

https://github.com/axios/axios#readme

以下`withCredentials`について抜粋
```
  // `withCredentials` indicates whether or not cross-site Access-Control requests
  // should be made using credentials
  withCredentials: false, // default
```
つまり、CORSを制御するための設定で、デフォルトではfalse（Cookieを送信しない）になっています。

# まとめ
初歩中の初歩ですが、公式をちゃんと読めよというお話でした。
痛みを伴って良い勉強になりました。
Javaで数値を含む文字列をソートする, 文字列と数字が混在している場合のソート

# 数値を含む文字列をソート
たまに以下のような数値を含む文字列がある。
>room1, room2, room100

これを単純にソートするとなぜかこうなってしまう。。。
>room1, room100, room2

ほかにもIDと名前のリストもある
> 1,山田 5,森下 9,佐々木 3,木下 

# 解決法
このコンパレータを試してください。数字以外の文字をすべて削除し、残りの文字を数値として比較します。

```java
Collections.sort(strings, new Comparator<String>() {
    public int compare(String o1, String o2) {
        return extractInt(o1) - extractInt(o2);
    }

    int extractInt(String s) {
        String num = s.replaceAll("\\D", "");
        // return 0 if no digits found
        return num.isEmpty() ? 0 : Integer.parseInt(num);
    }
});
```

# 実行結果
```java
public static void main(String[] args) throws IOException {
    List<String> strings = Arrays.asList("room1", "room5", "foo", "room2", "room100", "room10", "room3");

    Collections.sort(strings, new Comparator<String>() {
        public int compare(String o1, String o2) {
            return extractInt(o1) - extractInt(o2);
        }

        int extractInt(String s) {
            String num = s.replaceAll("\\D", "");
            // return 0 if no digits found
            return num.isEmpty() ? 0 : Integer.parseInt(num);
        }
    });
    System.out.println(strings);
}
//出力：
//[foo, room1, room2, room3, room5, room10, room100]
```
テストネット（Goeriネット）のETH入手方法

## テストネット（Goeriネット）のETH入手方法

ここではAlchemyでの入手方法を説明します。

### 下記サイトに入り、Alchemyへログイン

https://goerlifaucet.com/

### ログイン後、ウォレットアドレスを入力して、「Send Me ETH」を押す。

十数秒〜数分程度で、Goeri用のETHが着金します。

![スクリーンショット 2023-02-21 11.32.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416622/5281acdc-ad68-c29d-695e-daa7bc5b4965.png)


この記事は、著者が運営するメディア「ぬるぺでぃあ」でも読むことができます（記事は[コチラ](https://miuradonuts.com/2023/06/19/nft-goeri/)）
![](https://miuradonuts.com/wp-content/uploads/2023/06/ヘッダーエリア画像作成.png)
【Elasticsearch】フィールド（Field）って何？

## 登場人物
かーくん：だいちの息子、リアルはパパと言ってくれない1歳4ヶ月の男の子。
だいち：かーくんのパパ。パパ歴1年4ヶ月、嫁とかーくんをこよなく愛してる。

## 質問はいつも突然に
ある日、だいちと息子のかーくんはリビングで一緒に過ごしていました。かーくんは最近Elasticsearchについて学び始め、新しい概念について質問を思いつくたびにだいちに聞いていました。

かーくん「ねえ、パパ。Elasticsearchのフィールドって何？」
だいち「フィールドね。それは、Elasticsearchのドキュメントの一部で、データの実際の値を保持する部分だよ。」

かーくん「それってどういうこと？」
だいち「うーん、例えば、図書館の本を想像してみて。本の中にはたくさんの情報があるよね。それぞれの情報がフィールドに相当するんだ。」

かーくん「なるほど、でも、そんなにたくさんのフィールドがあったら、探しているフィールドを見つけるのは大変じゃない？」
だいち「それがElasticsearchのすごいところなんだ。Elasticsearchは各フィールドの内容を解析して、キーワードとその位置を記録しているんだ。だから、特定のキーワードを含むフィールドをすぐに見つけ出すことができるんだよ。」

かーくん「へえ、それなら大量のデータでもすぐに検索できるんだね！」
だいち「その通り。それに、フィールドはマッピングによって定義され、マッピングはフィールド名、データ型、検索時の振る舞いなど、フィールドの特性を指定するんだよ。」

かーくん「マッピングって何？」
だいち「マッピングとは、Elasticsearchがどのようにデータを扱うべきかを定義するための規則のことだよ。例えば、あるフィールドが数値なのか、テキストなのか、日付なのかを指定することができるんだ。」

かーくん「なるほど、だからElasticsearchはデータを効率的に検索できるんだね！」
だいち「その通り！さすが、かーくん。早くも理解が深まってきたね。」

かーくんは満足そうに笑いました。Elasticsearchについての理解が深まり、新しい知識を得ることができたからです。

## パパ、スベる
だいち「でも、フィールドがたくさんあると、みんな野球選手になっちゃうかもね。」
かーくんは無表情でいいました。「パパ、それは違う意味のフィールドだよ！」

だいち「あ、なんかごめんね。」
かーくん「パパありがとね〜」

かーくんはにっこりと笑い、新たに得た知識を消化するためにパソコンに向かいました。
リモートワークとアジャイル開発の転職体験

## はじめに

株式会社ラグザイアに転職して約1年が経ちました。
今回は、転職前との比較を通じて、私の所感を振り返りたいと思います。
転職を考えている方にとって、参考になる情報となれば幸いです。

## 転職のきっかけ
私のエンジニア経験は6年で、これまで3社で働いてきました。
前職ではウォーターフォール型の開発プロセスでパッケージソフトの開発に従事していました。
主にC#と.NET Frameworkを使用し、時折PHPも使っていました。前職の会社の雰囲気やレガシーな開発環境に不満を感じ、転職先を探していました。

## 入社の決め手
私がラグザイアに入社を決めた理由は以下のとおりです。

1. C#でリモートワークが可能な珍しい求人であったこと。
2. 開発環境や会社の雰囲気が私に合っていると感じたこと。
   - モダンな開発環境が整備されていたこと。
3. 面接の際に出会った社員の印象が良かったこと。
   - 年齢が私と比較的近いため、話しやすそうな雰囲気が感じられたこと。

## よかったこと
### アジャイル開発の導入
以前の職場では、顧客とのコミュニケーションは主にメールで行い、頻度も低かったです。また、ウォーターフォール型の開発手法を採用しており、設計が固まってから開発が始まるというスタイルでした。ラグザイアではアジャイル開発を経験することができました。以下の点が特に良かったです。

- ZoomやSlackを活用して頻繁にコミュニケーションを取ることができ、フィードバックを得る機会が多い。
- Google Workspaceを使用してリアルタイムにドキュメントを更新できる。

### 快適な開発環境
ハードウェアとソフトウェアともに最新のものを使用できています。

- Windowsマシン（メモリ32GB）
- Google Workspace
- Slack
- GitHub
- Miro
- etc…

### リモートワークでも効果的なコミュニケーションが可能
入社まではSkypeやZoomはたまに使用していてSlackを使ったことがありませんでした。
リモートワークに対応できるか一抹の不安がありましたが、解消されました。
SlackとZoomを使用することで、テキストベースのコミュニケーションを頻繁に行うことができています。特に、以下の2つの取り組みがうまく機能しています。

#### 1. 朝会の議事メモをGoogleドキュメントで管理する。
毎朝10時にチーム内でZoomを使用して朝会を行っています。
昨日の進捗や今日の予定について情報共有し、必要な場合は質問をし合います。
テキスト形式でタスクや進捗を書き留めておくことで、相手が理解しやすくなりますし、後から振り返りもしやすくなります。

#### 2. Slackの個人チャンネルで仕事の様子を共有する。
チーム内で「times_***」という個人用のSlackチャンネルを作成し、開発の進捗状況などをつぶやいています。(強制ではありません)
仕事の実況中継をするイメージです。
![times_qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3114710/90e33198-e1a9-86cf-cfd3-597f77afb8d4.png)

不明点が生じた場合は、とりあえず書き留めておき、他のメンバーと共有して解決策を見つけることができます。また、たまに褒められることもあります。(けっこうモチベになる)
![times_qiita3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3114710/497726fc-39c3-5747-5497-704b2c349eb6.png)

このようなコミュニケーション手法により、リモートワークでも円滑なコミュニケーションができています。リアルタイムなコミュニケーションよりも効果的ですし、非同期なので無理な割り込みも少なかったのがとてもよいです。

## 今後の課題
技術的負債の解消とウェブアプリケーションの理解です。
新しいフレームワークに移行する際にも、既存の機能を維持しながらスムーズな移行を行う必要があります。
デスクトップアプリケーションばかり開発していたのでウェブサービスへの理解が甘いです。業務のほかにドキュメントを読んだりして自習を進めています。

## さいごに
2022年は、情報のインプットと業務のアウトプットに重点を置いた1年でした。
今後は、定期的に記事を執筆したり勉強会に参加して、知識を整理していきたいです。

一緒に働いてくれるC#エンジニアを募集しています。興味がある方は公式ホームページのリクルートサイトから募集してください！(公式サイトではRubyエンジニアしか募集してないように見えますが…しています)
https://www.luxiar.com/recruit/
shスクリプトを実行する3つの方法

linuxコマンドでshスクリプトを実行する方法は全部で3つあります。

本記事では、それらの紹介と違いについて説明しようと思います。
よろしくお願いします！！！

## shスクリプトの実行方法
shスクリプトは以下3つの方法で実行できます。
カレントディレクトリのhoge.shを実行する例です。

1. `$ ./hoge.sh`
2. `$ bash hoge.sh`
3. `$ source hoge.sh`または`$ . hoge.sh`
※`source`と`.`は同義です

## 1. `$ ./hoge.sh`
shスクリプトを直接実行する方法です。
この方法でshスクリプトを実行する場合は、**ファイルに実行権限が必要**になります。

ちょっと実験してみます。
カレントディレクトリに以下のhoge.shを用意します。

```
echo hi
```

権限はとりあえずフルで与えておきます。
`-rwxrwxrwx`

この状態で`$ ./hoge.sh`を実行すると成功します。
```
$ ./hoge.sh
hi
```

では、実行権限のみを剥奪して再度実行してみます。
```
$ sudo chmod 666 hoge.sh
$ ./hoge.sh
zsh: permission denied: ./hoge.sh
```
するとこんな感じで失敗します。

ちなみに、hoge.shがカレントディレクトリにあるからといって`$ hoge.sh`などとしても動きません。
`zsh: command not found: hoge.sh`

これは、ファイル名のみを指定してスクリプトを実行しようとすると、環境変数PATHに登録されたパスからファイルを検索しようとするためです。
逆に言うと、環境変数PATHに登録されたパス(/binなど)にhoge.shを置くと、`$ hoge.sh`は成功します。

## 2. `$ bash hoge.sh`
インタプリタを指定する方法です。
やってることは`python hoge.py`とかと同じですね。

1の方法ではファイルに実行権限が必要でしたが、この方法の場合は実行権限は必要なく、**read権限のみあれば実行できます**。

実験です。
```
$ sudo chmod 444 hoge.sh
$ bash hoge.sh
hi
```

成功しましたね。

これは、あくまでもユーザが実行しているのはbashというプログラムであり、ファイルそのものを実行しようとしている訳ではないためです。
bashを起動できれば、ファイルの中身に何が書かれているかさえ分かればファイルを実行できるので、read権限だけあれば良いという訳です。

## 3. `$ source hoge.sh`または`$ . hoge.sh`
この方法も2と同じく、インタプリタを指定する方法です。

では2と何が違うのかというと、
2は現在実行中のbashとは別のbashでファイルの中身を実行する
3は現在実行中のbashでファイルの中身を実行する
といった違いがあります。

やっていることは2と変わりません。

## まとめ
個人的に、現在使用中のシェルに反映させたい処理(環境変数とか)がある場合などを除き、2の方法で実行するのが良いと思いました。
Dockerなどを使っていると知らぬ間にファイルのpermissionが変わっていて、スクリプトの起動コマンドが効かなくなってしまうシーンがちょこちょこ発生します。
read権限のみ残っていればスクリプトを実行できる2の方法はコンテナのそうした事情に割と柔軟に対応できるので気に入っています。
VS Code から Bicep で Logic Apps デプロイ

Bicep とは ARM に対して上腕二頭筋らしい。

## VS Code から Bicep を使う準備

[Bicep の開発およびデプロイ環境のセットアップ - Azure Resource Manager | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/install)
[Bicep - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep)
[Bicep ファイルを作成する - Visual Studio Code - Azure Resource Manager | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/quickstart-create-bicep-use-visual-studio-code?tabs=CLI)

上に従いセットアップ。

## 書いてみる
ひとまず書いてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/4bc192e5-868f-490f-84dd-95ab40e0b634.png)

### 視覚化

視覚化できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/6ee02945-12ab-c71f-d889-8be899dd3647.png)

### [デプロイ](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/quickstart-create-bicep-use-visual-studio-code?tabs=CLI#deploy-the-bicep-file)

ひとまずデプロイしてみよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/5d9c0359-df87-f4fa-d118-b0e146052c89.png)

## クイック スタート

以下に従う。

[クイック スタート - Bicep を使用して従量課金ロジック アプリ ワークフローを作成する - Azure Logic Apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/logic-apps/quickstart-create-deploy-bicep?tabs=CLI)

[azure-quickstart-templates/quickstarts/microsoft.logic/logic-app-create/main.bicep at master · Azure/azure-quickstart-templates · GitHub](https://github.com/Azure/azure-quickstart-templates/blob/master/quickstarts/microsoft.logic/logic-app-create/main.bicep)


```main.parameter.json
{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "testUri": {
      "value": "https://azure.status.microsoft/status/"
    },
    "location": {
      "value": "japaneast"
    },
    "logicAppName": {
      "value": "mybiceptest"
    }
  }
}
```
## 逆コンパイル

[ARM テンプレート JSON を Bicep に逆コンパイルする - Azure Resource Manager | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/decompile?tabs=azure-cli)

`az bicep decompile --file logicapps.json`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/ed71ab91-7f8b-7afc-ed2c-2922e22397e4.png)



## 完成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/d5154bb1-65f9-9d43-f67e-38c066f2e0c7.png)

Bicep でデプロイできました。
翻訳でコントリビュートしながら ChatGPT のプロンプティングを学んでいる話

# 活動の経緯
ChatGPT はもはや私にとって仕事や日常生活に欠かせない存在となってしまいました。ChatGPT は何も考えずに質問するだけでかなり良い回答を得られることもありますが、場合によっては全く見当違いの回答をすることもあります。

ChatGPT をより使いこなすために、プロンプティングについて学ぼうと思い、[**Lean Prompting**](https://learnprompting.org/)というサイトを読み始めました。

https://learnprompting.org/

私が読み始めた時点では、一部を除き、ほぼすべて英語で書かれていたので、機械翻訳と原文を行き来しながら読んでいました。やはり母国語ではない言語なので読み進めるのに少し時間がかかります。さらに、後日もう一度読み返そうとしたとき再び翻訳しながら読むハメになりました。

このサイトは OSS として管理されており、多言語対応もしていたので、**読み進めながら翻訳した文章を PR として送ることで、自分を含めたにほんごわしゃの学習者が少しでも楽をできるのではないか**と思い、活動を始めました。

# プロンプティング とは？
ChatGPT などの、テキスト生成 AI に入力するテキストを「プロンプト」といいます。単純な質問のようなプロンプトでも AI はある程度良い回答をしますが、プロンプトを改善することでより自分が欲しい回答に近づけることができます。

工夫したプロンプトを作成したり改善していくことを総称して**プロンプティング**と呼びます。

# Learn Prompting とは

https://learnprompting.org/

AI についての情報を発信している Twitter アカウントなどにも度々紹介されているサイトです。
プロンプティングの基本的な部分から、上級テクニックまで幅広く紹介されています。
一つ一つのセクションが短くまとまっており読みやすいと感じています。

# 翻訳に取り組む中で学んだこと
## Google 翻訳の VSCode 拡張が便利
https://marketplace.visualstudio.com/items?itemName=funkyremi.vscode-google-translate

この拡張を入れておけば、テキストを選択した状態で `Alt + Shift + t` を打つとその部分を翻訳して置き換えてくれます。

コード中のコメントや、変数に使われている単語の意味をサクッと翻訳したいときなどにも使えます。

## Genie AI が便利
https://marketplace.visualstudio.com/items?itemName=genieai.chatgpt-vscode

ChatGPT 4 がリリースした直後に広く使われ、その後すぐに消えてしまった ChatGPT 向けの VSCode 拡張がありましたが、それを更に発展させたような使い心地のものです。

VSCode から直接 ChatGPT と会話できますし、選択中のコードをプロンプトとして投げることができるので非常に便利です。

## ChatGPT は翻訳能力も高い
翻訳作業は、機械翻訳 → 手直し を繰り返して行っていました。最初は Google 翻訳や DeepL を使っていましたが、**最終的には ChatGPT での翻訳にシフトしていきました**。

従来の機械翻訳は、英語の１単語１単語をすべて対応する日本語に置き換えるような翻訳をするのに対し、ChatGPT は単語の対応関係を厳密に守るというよりも、**意訳に近い翻訳をしてくれる**ので、手直しが少なく済んだためです。

一方で、**ChatGPT の出力は毎回同じではない**ということにも留意すべきです。繰り返し同じ文が出てくるような文章を分割して翻訳すると、同じ文が微妙に異なる翻訳として出力されてしまいます。

少なくとも現時点では Google 翻訳は毎回同じ結果を返してくれるので、性質を理解した上で使い分けたほうが良いでしょう。

※ Google 翻訳でも時間が経ってから同じ文を翻訳すると精度の改善などにより結果が変わる可能性があります。

# オススメの翻訳手順
シンプルに**翻訳したい文章全体を ChatGPT に投げて結果を必要に応じて手で修正する**という方法がオススメです。

ChatGPT は markdown 形式のファイルの翻訳でも、元のフォーマットを保ったまま返却してくれます。

しかしながら、**長い文章を投げると、回答が途中で止まることがあり、「Continue Generating」を何度もクリックするのが面倒だった**ので、下記の Chrome 拡張を作って自動化することで解決しました。

https://chrome.google.com/webstore/detail/chatgpt-autocontinuer/plmdeeladmaofbgigihgnnjmfkhkbfhh


# 最後に
翻訳コントリビュートのメリットとして以下を感じました。
- 学習を継続するモチベーションになる
- 比較的簡単なので OSS 活動への心理的ハードルが下がる

これからも活動を続けていこうと思います！
そして、まだまだ [**Lean Prompting**](https://learnprompting.org/) の翻訳は完了していません。一緒に翻訳を進めてくれる方がいると嬉しいです！
static classの存在意義がちょっとわかった

## はじめに
皆さんはstatic使いこなしていますでしょうか？

恥ずかしながら筆者はエンジニアになってからstaticを使った記憶がありません。

ですが最近、弊社プロダクトでマジックナンバーを取り扱うロジックを調査したところ、staticの有用性に気付いたので記事にしてみました。

## static classの調査
#### きっかけ
筆者が作成しているプロダクトでマジックナンバーを使おうとして、既存の処理はどうなっているか調べたところ、下記のようなenum専用のclassを作って管理をしていました


```php:BaseBallBackNumberEnum.php
<?php
namespace App\Enum;

use MyCLabs\Enum\Enum;

class BaseBallBackNumberEnum extends Enum
{
    private const OTANI_SHOHEI = 17;
    private const FUZINAMI_SHINTARO = 11;
}

```

正直「いやなんでconfigっていう機能があるのにわざわざ作り直してるんや」となりました。

それで何かしら理由があるのだろうと思いconfigの欠点を調べてみたところ、configは上書き可能だから危険だそうです。

configではconstとか定義しているのでおそらくstatic classっぽいのに上書き可能なの？？となりさらに調査を進めました。（※ちょっとややこしいのですが、configはstatic functionでした。ただ動きは一緒だと思われるので便宜的にstatic classとして以降は記述をつづます。[参考にさせていただいた記事](https://qiita.com/ktplato/items/31ecfa2735590b0a977d)）

#### 結局static classとは...

筆者はこれまでstatic（静的）というくらいだから**不変**であるのが売りだと思ってきたのですが、これが間違いで、static classというのは**常時インスタンス化されている**classを指すものだったのです。

つまるところ、いつでも使えるというだけでそれ以外は他のclassと何も変わらないので、classの中でpublicな変数を準備すると、どの処理でも使える変数が出来上がるというわけです。

#### static classでできているconfig（具体例）のメリット・デメリット

configが上書き可能であることの何がいいかの例ですが、負荷が高くなった時に各処理で解放しているメモリを上げたいという場面で、いろんな場所で使われるそのメモリの値の変数を使用しておけば、どこかの１つの処理でメモリ数を変更することで一気にシステム全体をコントロールできるようになります。

一方で、通常のマジックナンバーとしてconfigを扱うと、マジックナンバーを使った処理付近の編集の機会が多くなるため、何かの間違いで変数を上書きしてしまいやすいというデメリットも存在します。

ゆえに最初しか触らず編集機会の少ないPCの設定部分で使うのがいいのがconfigなんだろうなと考えられるというわけです。


#### マジックナンバーにあった書き方とは
それじゃあ最初のマジックナンバーどうするのかという話ですが、classの中でprivate関数を使って使いまわせば良いわけです。
加えて常時使うわけではないのでメモリの節約として非静的（動的）なclassで作って毎度インスタンス化するとなおgoodとなるわけですね。

すると[きっかけ](#きっかけ)で書いた弊社プログラムのように落ち着くというわけだったのです。

（とは言いつつマジックナンバーのメモリ使用量は微々たるものなので、あっちこっちでインスタンス化の記述を増やさず、static classでprivate変数を含むものを一個作っておくとより良くなるのかなぁとこの記事を書いていて思いました。）

## 結論（static classの存在意義）
上記の調査から、アプリ開発者にとってstatic classの存在意義とは、

classを使いたいときに毎度インスタンス化の処理が必要ないので、"**常時使う変数**"または"**あっちこっちで使われる変数**"を準備するのに便利であること

だと思われます。


何かのお役に立てていただければと思います。
4 年目フロントエンドエンジニアの転職活動記録

# はじめに
こちらの記事は[転職ドラフト体験談投稿キャンペーン](https://job-draft.jp/articles/251)に参加しています。
とは言っても、この記事の目的はあくまで**自分の転職活動の記録を記録・共有すること**なので、単純に事実と感想を述べて行きたいと思います。少しでも転職活動を考えている人の助けになれば幸いです。

# 経歴
| 期間            | 職種                       | 使用技術                       |
|----------------|--------------------------|--------------------------|
| 2017/4 - 2020/3 | 設備設計会社で社内向けの CAD カスタマイズ開発  | C++ / SQL            |
| 2021/4 - 2023/5 | Web系のアプリケーションエンジニア | TypeScript / Vue.js / Ruby on Rails / AWS |
| 2023/6 - 現在(転職後)    | Web系のアプリケーションエンジニア | TypeScript / Vue.js |

2017 年から新卒で社内 SE として 3 年働いた後、よりモダンな技術に触れたいという思いで Web アプリケーションエンジニアに転職しました。そこで 3 年間フロントエンドを中心に開発した後、現在の[株式会社よりそう](https://qiita.com/organizations/yoriso)に転職しました。

# 転職理由
ざっくりと以下のような感じです。

- エンジニアとしてキャリアアップをしたかったため
- エンドユーザーからフィードバックをもらいながらプロダクトを改善していきたかったため
- フルリモートで働きたかったため
- より社会貢献性の高い事業ドメインに挑戦してみたかったため

# 利用した求人媒体
## 転職ドラフト
**自分の市場価値の相場感を知りたい**という理由で利用してみました。
触れ込み通り、企業からの入札から始まり、選考がスタートするというものでした。
2 回参加して指名は合計 7 件ありました。そのうちカジュアル面談を受けたのは 4 社、選考は 3 社、内定は 1 社でした。

注意すべきだなと思ったのは、**企業からの入札は、あくまでカジュアル面談のきっかけに過ぎないということ**です。「入札」という言葉から、ある程度内定が確約されるというようなイメージがありましたが、入札はあくまで選考のスタートラインに過ぎません。

最終的には転職ドラフト経由で、[株式会社よりそう](https://qiita.com/organizations/yoriso)への転職が決まりました。

https://job-draft.jp/

## LAPRAS
**エンジニアとしての技術力を数値化できる**ということに興味を持ち登録してみたことがきっかけで使い始めました。
経歴ややりたいことを入力すると、企業から興味通知や選考のお誘いのメールが届くので、その中から希望にマッチする企業とカジュアル面談をしました。

4 社カジュアル面談、1 社選考、1 社内定となりました。

**LAPRAS は自分のアウトプットを振り返ることができる点が面白い**です。
転職活動が終わった今もアウトプット可視化のために利用しています。

https://lapras.com/

## 会社の採用ページ
既に知っていて興味のある企業には直接採用ページから応募しました。

2 社カジュアル面談、2 社選考、1 社内定となりました。

# 転職活動記録の管理
スケジュールや面接で話す内容の管理には、Notion を使っていました。

- 転職活動関連のタスクを TODO リストで管理
- カレンダーに面接スケジュールと話したいことや実際に話したことを記入
- 聞かれたことやそれに対する回答をブラッシュアップ
- 履歴書や職務経歴書の管理

などを行っていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/4e077ad3-287f-4dfe-c9f8-7209ab1277a5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/1d7c11b3-db18-545c-3202-d9ead3b44d3e.png)

# 結果
- 転職活動期間は **約 3 ヶ月**
- **10 社** カジュアル面談 → **7 社** 選考 → **3 社** 内定

# 注意すべきポイント
### 面接は静かな個室で受ける
至極当たり前のことですが、ある企業からフィードバックをもらって初めて気づきました。
恥ずかしながら、指摘を受けるまでは、普段の仕事と同じような感覚で、**レンタルオフィスの個室ではない共有スペースで、マスクを付けたまま面接受けていました。**
当然ですが、採用企業はものすごいコストを掛けて採用活動をしていますし、自分自身もかなりの労力を使って面接に挑みます。**短い時間で集中して自分の魅力を伝えるためにも、マスクを外して、集中できる静かな個室で面接を受けましょう。**

### 最初の面接は失敗しやすい
かなり準備して挑んだつもりですが、最初の方の面接では、**自分の中で話したいことはたくさんあるのに、うまく言語化できない**、ということが何度かありました。
紙に書き出すことと、実際に話すのでは大きな差があることを実感しました。

### 自分の経験をとにかく言語化する
自分の場合、何度か面接を経験して言語化が進んできましたが、やや準備は不十分だったなと感じます。
志望度が高い企業の面接の前までには、過去に自分がやってきたことを徹底的に振り返って面接や模擬面接で練習しておくことをおすすめします。

# 感想
転職活動は自分のこれまでのエンジニアリングを言語化するいい機会になりました。
体力的にも精神的にもかなり疲れましたが、良い転職ができたなと思っています。
この記録が誰かの役に立つことを願っています。

もし詳細が知りたいという方がいれば、Twitter アカウントに DM で気軽に質問してください。
https://twitter.com/punksy2

# 今後
[株式会社よりそう](https://qiita.com/organizations/yoriso)でフロントエンドをリードしていきます。
これまでの経験を活かし、開発体験や品質の向上などやフロントエンド技術のモダン化を進めていくつもりです！

以上、読んでいただき、ありがとうございました。
データレイクとDWH（データウェアハウス）の違いとそれぞれの特徴について

# はじめに
現代のビジネス環境では、データがますます重要な役割を果たしています。データを有効に活用するためには、適切なデータ管理と分析が欠かせません。データレイクとDWH（データウェアハウス）は、データ管理のための重要な概念ですが、それぞれ異なるアプローチを取っています。本記事では、データレイクとDWHの違いと、それぞれの特徴について解説します。

# 結論
最初に結論を言っときますと、
・DWHは構造化データ
・データレイクは非構造化データ
を格納できます。
従って、各々の特徴としては、
・DWHはデータの検索性
・データレイクはデータの柔軟性
があります。

# セクション1：データレイクの概要と特徴
データレイクは、様々な種類や形式のデータを大容量で保持するためのストレージシステムです。データレイクは、生のデータをそのまま取り込むことができ、データの構造や形式に対する制約がほとんどありません。以下に、データレイクの特徴をいくつか紹介します。

スキーマオンリーレイク：データレイクでは、データのスキーマ（データの構造や形式）は後から定義することができます。つまり、データの取り込み時にスキーマを事前に設計する必要がありません。
柔軟性と拡張性：データレイクは、異なる種類のデータを柔軟に統合することができます。また、データの量や種類が増えても、データレイクを拡張することが比較的容易です。
リアルタイム処理：データレイクでは、リアルタイムでデータを取り込むことが可能です。これにより、ビジネス上の即時の要求に対応することができます。

# セクション2：DWHの概要と特徴
DWH（データウェアハウス）は、組織がビジネス上の意思決定をサポートするためにデータを集約・統合するデータベースです。以下に、DWHの特徴をいくつか紹介します。

トップダウンアプローチ：DWHでは、データの設計と統合が先行して行われます。つまり、データのスキーマや構造が事前に定義され、その上でデータが取り込まれます。
データ品質と整合性：DWHは、データ品質と整合性に重点を置いています。データ品質の管理や整合性の確保には、データの変換やクレンジングが含まれます。
ビジネスインテリジェンス：DWHは、ビジネスインテリジェンス（BI）ツールと組み合わせて使用されることが一般的です。BIツールは、データの分析や可視化を容易にするために使用されます。

# セクション3：データレイクとDWHの違い
データレイクとDWHの主な違いは、データの取り込みや管理のアプローチにあります。データレイクでは、生のデータをそのまま保持し、柔軟なスキーマ設計とリアルタイム処理が可能です。一方、DWHでは、データの事前定義されたスキーマとデータ品質の管理が行われ、トップダウンのアプローチが取られます。

データレイクは、大量の異種データを統合し、高速で柔軟な分析を可能にするために使用されます。データの取り込みや分析のプロセスは柔軟であり、ビジネス要件に応じて変更できます。一方、DWHは、整合性のあるデータを使った正確なレポートやビジネス分析を提供するために使用されます。データ品質の管理やビジネスインテリジェンスツールとの統合が強化されています。

# まとめ：
データレイクとDWHは、それぞれ異なるアプローチでデータ管理と分析を行います。データレイクは柔軟性と拡張性に優れ、生のデータをそのまま取り込みます。一方、DWHはデータ品質の管理や整合性に重点を置き、ビジネスインテリジェンスに活用されます。適切な選択は、ビジネスのニーズと目標に応じて行う必要があります。

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
PHPの列挙型（Enum）の使い方をまとめたみた

# はじめに

PHP 8.1 から列挙型が使えるようになりました。

https://www.php.net/manual/ja/language.enumerations.php

ぜひ使いこなせるようになりたいと思い、記事にまとめました。
ちなみに、これまでは laravel-enum のようなライブラリを用いて管理することが多かったです。

https://github.com/BenSampo/laravel-enum


# 列挙型（Enum）とは？

公式には以下のように説明されています。

> 開発者は取りうる値を限定した独自の型を定義できます。 これによって、"不正な状態を表現できなくなる" ので、 ドメインモデルを定義する時に特に役立ちます。

つまり、各プロジェクトごとに必要となる独自の値を管理することができます。

```php:Pure Enum
enum Pricing
{
    case Light;
    case Standard;
    case Premium;
}

echo Pricing::Standard->name;
// Standard
```

:::note warn
上記の例では `Pricing::Light ≠ "0"` であることに注意。配列のようなインデックスは設定されません。（ case はシングルトンオブジェクトであるため）
:::

列挙型に値を持たせたい場合は以下のように記述します。

```php:Backed Enum
enum Pricing: int
{
    case Light = 1000;
    case Standard = 2000;
    case Premium = 3000;
}

echo Pricing::Standard->name;
// Standard
echo Pricing::Standard->value;
// 2000
```



# 使い方

## case の一覧を取得する

`cases()` を用いると配列として取得できます。

```php
var_dump(Pricing::cases());
// array(3) {
//   [0]=>
//   enum(Pricing::Light)
//   [1]=>
//   enum(Pricing::Standard)
//   [2]=>
//   enum(Pricing::Premium)
// }
```

## 値から case を取得する

`tryFrom()` を用います。不正な値が与えられた場合は NULL を返します。

```php
$valid = Pricing::tryfrom(2000);
var_dump($valid);
// enum(Pricing::Standard)

$invalid = Pricing::tryfrom(1500);
var_dump($invalid);
// NULL
```

## case と紐づく他の値を取得する（例：表示名）

列挙型にはメソッドを含めることができるので、case に応じて他の値を取得するメソッドを作成します。

```php
enum Pricing: int
{
    case Light = 1000;
    case Standard = 2000;
    case Premium = 3000;

    public function text(): string
    {
        return match ($this) {
            Pricing::Light => 'お手軽プラン',
            Pricing::Standard => '標準プラン',
            Pricing::Premium => '特別プラン',
        };
    }
}

echo Pricing::Standard->text();
// 標準プラン
```

## value => name の配列を取得する

static メソッドを作成します。今回は他の Enum でも使えるように Trait で作成してみました。

```php
trait EnumSelectable
{
    public static function forSelect(): array
    {
        return array_combine(
            array_column(self::cases(), 'value'),
            array_column(self::cases(), 'name')
        );
    }
}

enum Pricing: int
{
    use EnumSelectable;

    case Light = 1000;
    case Standard = 2000;
    case Premium = 3000;
}

var_dump(Pricing::forSelect());
// array(3) {
//   [1000]=>
//   string(5) "Light"
//   [2000]=>
//   string(8) "Standard"
//   [3000]=>
//   string(7) "Premium"
// }
```
csvファイル出力

csvファイル出力
~~~java
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

public class CSVWriter {
    public static void writeDataToCSV(List<String[]> data, String filePath) {
        try (FileWriter writer = new FileWriter(filePath)) {
            for (String[] row : data) {
                StringBuilder csvRow = new StringBuilder();
                for (String value : row) {
                    // 文字列中にカンマや改行が含まれる場合は適切にエスケープする必要があります
                    String escapedValue = escapeSpecialCharacters(value);
                    csvRow.append(escapedValue).append(",");
                }
                csvRow.deleteCharAt(csvRow.length() - 1); // 最後のカンマを削除
                csvRow.append("\n"); // 改行を追加
                writer.write(csvRow.toString());
            }
            System.out.println("CSVファイルにデータを書き込みました: " + filePath);
        } catch (IOException e) {
            System.err.println("CSVファイルの書き込みエラー: " + e.getMessage());
        }
    }

    private static String escapeSpecialCharacters(String value) {
        // 文字列中のカンマや改行をエスケープする必要がある場合に実装するロジック
        // 例: カンマが含まれる場合にはダブルクォートで囲むなど
        // この例ではエスケープ処理は省略しています
        return value;
    }
~~~
レコメンドアルゴリズムを応用して作った「存在しそうで存在しない漢字ランキング」TOP5

↓こちらの記事でも似たようなことをやっているようなので併せて読むと面白いかもしれません

https://qiita.com/hakatashi/items/e5f803e3476fd4a75b55

# 存在していそうで存在していない漢字について

漢字にはヘンとツクリで構築されているものがあります
例えば｢渚｣という漢字はヘンである｢氵｣と, ツクリである｢者｣の二種類で構築されています

ヘンとツクリをランダムに選んだらどうなるでしょうか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/3ba43c9c-5c7e-043e-b19c-477a32ddbb4f.png)

なんか......右の文字は存在していなそうな気がしますが, 左の文字は存在していそうな気がしますね
(主観的な意見ですみません)
ヘンとツクリをテキトーに選んだとき, ｢この漢字は実在していそう｣と思える字とそうじゃない字があります
この｢存在していそう度｣を数値化しランキングを作成しました

# レコメンドについて

漢字について語る前に, レコメンドについて説明します.
多くの人は｢何だそれ｣となると思いますが, 黙ってきいてください.

レコメンド(推薦)というのはAmazonなどででてくる｢あなたへのおすすめ｣のことを言います.
ユーザーの過去の履歴をもとにオススメすべきアイテムについて算出する技術となっています.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/77a426a9-6065-d54a-1102-5f8ea420d457.png)

レコメンドの基本的な考え方に評価値行列というアイデアがあります.
まず初めに, 全ユーザー×全アイテムの行列を用意します.
そこから実際に閲覧されたユーザーとアイテムのペアに｢1｣をそれ以外に｢0｣をつけます. 
(ちなみにこの行列はたまにしか1があらわれないスパースな行列になることが知られています)
さいごに, 機械学習などの手法を使って｢0｣のマスから｢次に閲覧されそうなマス｣を求めていきます.

### BPR modelについて

｢0｣のマスから｢次に閲覧されそうなマス｣を求める手法について説明していきます.
一般には機械学習モデルをつかい, レコメンドモデルなどと呼ばれます.
今回は, このレコメンドモデルの中で一番基本的なBPR modelについて説明していきます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/87fd6516-f1ef-d5a9-4b6d-09120482ee06.png)

モデル自体は深層学習としてみるとすごく簡単です.
まず初めにユーザーとアイテムをそれぞれエンべディングして, それを内積させたのをスコアとします.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/6e17b637-7701-0239-45b6-b69afa8a2392.png)

ただ, 損失関数が少し変わっており, まず初めに同一ユーザーから正例と負例それぞれの一つずつ引っ張ってきて, そのスコアを求めます.
次に
$$
\mathrm{sigmoid}(score(正例)-score(負例))
$$
を最大化させます.
感覚としては$score(正例)>score(負例)$となる確率の最大化をしているイメージです.


# 漢字について

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/5a505a98-fe13-c729-d6c2-aea024259ede.png)

評価値行列というアイデアを漢字にも適用させましょう.
漢字はヘンとツクリからなっているためヘンツクリ行列が構築できます.

まず初めに, 全ヘン×全ツクリの行列を用意します.
そこから実際に存在している漢字=(ヘンとツクリのペア)に｢1｣をそれ以外に｢0｣をつけます. 


# レコメンドと漢字の比較

||レコメンド|漢字|
|-|-|-|
|評価値行列|アイテム×ユーザー|ヘン×ツクリ|
|行列の要素|1 or 0(閲覧or未閲覧)|1or0 (実在or非実在)|
|行列の特徴|スパース|スパース|
|目的|閲覧されそうなアイテム×ユーザーのペアを探す|実在しそうなヘン×ツクリのペアを探す|
|ターゲット|ユーザーごとのランキングほしい|全体でのランキングほしい|

レコメンドと存在している漢字に付いて比較してみました.
こうやって考えると, レコメンドのアルゴリズムがそのまま｢存在しそうで存在しない漢字｣の判別に使えそうです.
そのため, ヘン×ツクリ行列でBPRを行えば, 「存在しそうで存在しない漢字ランキング」が作れる算段です.

一点だけターゲットのところが異なっています.
これは損失関数を変えることで対応しました.
BPRでは同一ユーザーから正例負例を取り出していたのですが, 漢字の場合は全ヘン×ツクリ行列の中から正例負例を取り出します.
それにより, 全体での順位付けが可能になると期待できます.

# モデル構築について

web漢和辞典からスクレイピングし, ヘンとツクリに分割でき, その両方が常用漢字に使われたことのあるものをターゲットにしました
常用漢字とはメディアなどが漢字を使うガイドラインで, 異自体/旧字体を除外するために用いました.

# 結果

実際の｢存在しそうな漢字ランキング｣はこんな感じになりました.
いえーい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/169af6de-e3c1-0a90-efdd-630e217eee9c.png)

なんか, ありそうな字が並んでいます.
それっぽいものができたので, ちゃんと問題ないアルゴリズムになっているんじゃないかなと思いました.


逆にスコアから｢なさそうだけど, 実は存在している漢字｣ランキングも作れます.
それがこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/017df498-76eb-b894-6c75-de233bf444a2.png)
全体的にヘンもツクリもこってりしたものが多く漢字っぽくないのではないでしょうか.
cscの作法 その367

# 概要
cscの作法、調べてみた。
opentkのgamewindow使ってみた。
GL.Material使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/60a37882-9687-5c82-5ca9-c52521f444dd.png)


# サンプルコード

```

using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace App
{
	class Gwin: GameWindow {
		double counter = 0;
		public Gwin(int width, int height, GraphicsMode mode, string title): base(width, height, mode, title) {
			this.VSync = VSyncMode.On;
		}
		protected override void OnRenderFrame(FrameEventArgs e) {
			base.OnRenderFrame(e);
			counter += e.Time;
			GL.Enable(EnableCap.DepthTest);
			GL.MatrixMode(MatrixMode.Modelview);
			Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
			GL.LoadMatrix(ref modelview);
			Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(1.8f, 1.0f, 1.0f, 200.0f);
			GL.MatrixMode(MatrixMode.Projection);
			GL.LoadMatrix(ref perspective);
			GL.ClearColor(Color.CornflowerBlue);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			GL.Rotate(counter / 2, 1.0, 0, 0);
			GL.Rotate(counter / 2, 0, 1, 0);
			GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, Color4.White);
			GL.Begin(PrimitiveType.Quads);
			GL.Normal3(Vector3.UnitX);
			GL.Vertex3(-10.0f, 10.0f, 10.0f);
			GL.Vertex3(-10.0f, -10.0f, 10.0f);
			GL.Vertex3(10.0f, -10.0f, 10.0f);
			GL.Vertex3(10.0f, 10.0f, 10.0f);
			GL.End();
			this.SwapBuffers();
		}
	}
	class Program {
		static void Main(string[] args) {
			Gwin window = new Gwin(500, 500, OpenTK.Graphics.GraphicsMode.Default, "Test");
			window.Run();
		}
	}
}





```

以上。
cscの作法 その366

# 概要
cscの作法、調べてみた。
opentkのgamewindow使ってみた。
DepthTest使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ced01a36-6ee0-4a9d-ade0-04b9774d1a73.png)


# サンプルコード

```

using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace App
{
	class Gwin: GameWindow {
		double counter = 0;
		public Gwin(int width, int height, GraphicsMode mode, string title): base(width, height, mode, title) {
			this.VSync = VSyncMode.On;
		}
		protected override void OnRenderFrame(FrameEventArgs e) {
			base.OnRenderFrame(e);
			counter += e.Time;
			GL.Enable(EnableCap.DepthTest);
			GL.MatrixMode(MatrixMode.Modelview);
			Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
			GL.LoadMatrix(ref modelview);
			Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(1.8f, 1.0f, 1.0f, 200.0f);
			GL.MatrixMode(MatrixMode.Projection);
			GL.LoadMatrix(ref perspective);
			GL.ClearColor(Color.CornflowerBlue);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			GL.Rotate(counter / 2, 1.0, 0, 0);
			GL.Rotate(counter / 2, 0, 1, 0);
			GL.Begin(PrimitiveType.Quads);
			GL.Color4(Color4.Red);
			GL.Vertex3(-10.0f, 10.0f, 10.0f);
			GL.Vertex3(-10.0f, -10.0f, 10.0f);
			GL.Vertex3(10.0f, -10.0f, 10.0f);
			GL.Vertex3(10.0f, 10.0f, 10.0f);
			GL.End();
			this.SwapBuffers();
		}
	}
	class Program {
		static void Main(string[] args) {
			Gwin window = new Gwin(500, 500, OpenTK.Graphics.GraphicsMode.Default, "Test");
			window.Run();
		}
	}
}





```


以上。
2023/6/19主にITとかセキュリティの記事

マイナンバーカードで最も怖いのは個人情報漏洩　何か起きても「デジタル庁は責任を負わない」と規約に明記(6/17)
https://news.yahoo.co.jp/articles/466f67ae6947e9990519cff3545dc3bf8ef02957

防衛技術で重点12分野、サイバーや無人機　装備庁指針案
5年以内に実用、企業に投資促す(6/17)
https://www.nikkei.com/article/DGXZQOUA170CO0X10C23A6000000/

サイバー防御など１２分野、装備化検討へ…「防衛技術指針」の概要判明(6/17)
https://www.yomiuri.co.jp/politics/20230616-OYT1T50291/

千葉県内の自治体にも「チャットGPT」導入に向けた動き(6/16)
https://nordot.app/1042349280005702442

宮城県、生成AI積極利用へ　個人情報や非公開情報は禁止　近く職員に方針通知(6/17)
https://news.yahoo.co.jp/articles/266480e4099529a6be24e7fab5c958c73c3b8b3e

巨大IT規制、アプリ販売・決済開放　手数料下げ促す(6/17)
https://www.nikkei.com/article/DGXZQOUA163TX0W3A610C2000000/

2022年マカオ廉政業務報告公布、公務員によるDBへの不正アクセス事案増(6/17)
https://news.yahoo.co.jp/articles/e26b5726186850bb337d79f021afb0b039bb8a1d?source=rss

アンチウイルスソフトの管理方法は？問題点や対策のまとめ
https://www.ntt.com/business/services/network/internet-connect/ocn-business/bocn/knowledge/archive_69.html

ヤマハのアメリカ販売子会社が不正アクセスの被害…「ランサムウェア」による攻撃が原因(6/17)
https://news.yahoo.co.jp/articles/380fd3fdf232e23d1a91b4b6bc285492b8f6fb35

電子機器の〝フリーズ〟なぜ起きる？　専門家に聞く家庭での対処法(6/16)
https://withnews.jp/article/f0230616000qq000000000000000W0gd10701qq000025838A

偽セキュリティ研究者、GitHubとTwitter悪用してPoC偽装したマルウェア拡散(6/17)
https://news.mynavi.jp/techplus/article/20230617-2705448/

NRIセキュア、アイデンティティに関連する脅威を検知・対応するマネージドサービス(6/16)
https://cloud.watch.impress.co.jp/docs/news/1509285.html

Androidスパイウェアに注意、メッセージアプリで感染することが判明(6/17)
https://news.mynavi.jp/techplus/article/20230617-2706427/

Cyber Threat Intelligence​ のためのNLP技術調査​(6/14)
https://qiita.com/mkkon/items/70c26a7f15fb877ba6e2

復旧には1,000万円超かかることも…医療機関を狙う「サイバー攻撃」が急増中！いますぐできる「2つの対策」(6/17)
https://news.nicovideo.jp/watch/nw12781732

“タダだけど使い物にならない”と言われていた「Windows Defender」が、「Microsoft Defenderウイルス対策」になって一目置かれるようになった訳(6/17)
https://news.yahoo.co.jp/articles/7f0d9864a96f19cc2b61bbfbbd973bc6e75d859e?source=rss

暗号資産、犯罪利用のリアリティ(6/17)
https://www.coindeskjapan.com/184839/
https://news.yahoo.co.jp/articles/e0472e58786a56c37eef69fba7a5fe2bf0f6aaef?source=rss

国立「産業技術総合研究所」中国人研究者のスパイ行為を検挙…中国軍の先端兵器開発にも関わる国防7校とは(6/17)
https://www.fnn.jp/articles/-/543584

U字工事の漫才でセキュリティ啓発、警視庁が公開した動画をチェックしてみよう(6/16)
https://internet.watch.impress.co.jp/docs/column/dlis/1509007.html

急にスマホが使えなくなった！そういえばフィッシング詐欺サイトに…　SIMスワップ被害に遭わないために(6/17)
https://news.yahoo.co.jp/byline/tadafumiaki/20230617-00352980

フェイスブック「乗っ取り犯」を主婦が撃退できたワケ(6/17)
https://www.yomiuri.co.jp/life/digilife/column/20230612-OYT1T50080/

「生成AIを全製品に搭載する」、マイクロソフトが自社の戦略を説明(6/16)
https://xtech.nikkei.com/atcl/nxt/news/18/15421/

【コラム】AIが人類を滅ぼす日！？…イギリスの「リーダーシップ教育」とは【ロンドン子連れ支局長つれづれ日記】(6/17)
https://news.yahoo.co.jp/articles/f70410de5b6a43b7019ef1262aa4c22140b94550

ポストコンサル転職の事情は？メリットや注意点を含めてわかりやすく解説(6/16)
https://zuuonline.com/archives/253947
エンジニアって200色あんねん

# 200色は無いです
エンジニアって種類多すぎますよね
みなさんは最終的にどんなエンジニアになりたいでしょうか
今回はいろんなエンジニアについてざっくり簡単にまとめたよ
括りが曖昧だったり、自分の知らない領域もあるのでちょっと怪しい部分もあるかもしれないけど、見てくれるとうれしいです🙏

* 開発系
[フロントエンドエンジニア](#フロントエンドエンジニア)
[バックエンドエンジニア](#バックエンドエンジニア)
[アプリケーションエンジニア](#アプリケーションエンジニア)
[組み込み系エンジニア](#組み込み系エンジニア)
[AIエンジニア](#aiエンジニア)

* インフラ系
[ネットワークエンジニア](#ネットワークエンジニア)
[データベースエンジニア](#データベースエンジニア)
[サーバーエンジニア](#サーバーエンジニア)
[セキュリティエンジニア](#セキュリティエンジニア)
[クラウドエンジニア](#クラウドエンジニア)

* 管理系
[プロジェクトマネージャー](#プロジェクトマネージャー)
[プロジェクトリーダー](#プロジェクトリーダー)
[ITコンサルタント](#itコンサルタント)

* その他
[社内エンジニア](#社内エンジニア)
[セールスエンジニア](#セールスエンジニア)
[データエンジニア](#データエンジニア)
[テストエンジニア](#テストエンジニア)

# 開発系
##### フロントエンドエンジニア
Webサイトの画面側をHTML、CSS、JavaScript、PHPなどで開発する人
流行りのフレームワークとしてはReact、Vue.js、Angularなどです
度重なる文言とデザイン修正でずっと忙しいイメージ
##### バックエンドエンジニア
ユーザーから見えないサーバー側のAPIやバッチなどの実装がメインです
言語はJavaScript、Python、Ruby、PHPが多く使われている印象です
仕様変更の餌食になると辛いです
##### アプリケーションエンジニア
WEBサービスもアプリケーションに入るとは思うのですが、スマホアプリだけに絞るとAndroidは主にJavaでiOSはObjective-CやSwiftが使われています
##### 組み込み系エンジニア
家電や専用機器などの独立した機械に組み込むコンピューターのためのシステムを設計・開発する人
あんまりよくわからない、、

##### AIエンジニア
流行りのAIについてのエンジニア
ディープラーニングのアルゴリズムを考えたり、データを学習させたりする
めちゃくちゃ専門的で頭のいい人しかできないんじゃないかな

# インフラ系
##### ネットワークエンジニア
ネットワークの設計・構築・運用・保守をします
ネットワークの知識や物理的な機器を扱うスキルなどが必要です
保守と運用がきついイメージ、、
##### サーバーエンジニア
主にサーバーの構築を行います
Linuxやミドルウェアの知識が必要です
##### データベースエンジニア
データベースの開発や設計、運用、管理をするよ
データベーススペシャリストっていう資格があるよ
##### セキュリティエンジニア
システムやネットワークのセキュリティを考える人だよ
システム設計に関わったりして専門的な知識がいるので結構ハードルが高い気がする
##### クラウドエンジニア
クラウド(AWSやAzureなど)でシステムの設計や構築をします

# 管理系
##### プロジェクトマネージャー
その名の通りプロジェクトをマネージするお仕事です
まさにプロジェクトの代表という感じです
プロジェクトを成功に導くためにスケジュールやメンバー、タスクの管理をします
##### プロジェクトリーダー
マネージャーと異なりこちらはチーム単位でのリーダーです
システムの要件定義を客と直接行ったりもします
##### ITコンサルタント
一番上流部分を担当するよ
課題のヒアリングから解決までの全ての責任者って感じです
かなり年収が高い気がするよ

# その他
##### 社内エンジニア
社内ITシステム、ネットワークや自社製品の管理と品質向上などを行います
社内の何でも屋さんという感じです
わりと幅広い知識が必要な気がします
##### セールスエンジニア
技術的な知識で営業のサポート、もしくは直接営業を行う人

##### データエンジニア
ビッグデータの解析や解析基盤を作る人
データ自体の分析や活用等についてはデータサイエンティストの仕事？
##### テストエンジニア
システムのテスト工程を考えたり、自動テストのロジックを作ったりする
作る側からしたら頭が上がらない存在

# 感謝
素敵なキャリアプランの参考にしていただければと思います
**全てのいいね、ストックに感謝します**🙏
【cron】crontabのエディタを変更する方法

## 設定方法
crontab のエディタは`EDITOR`変数で変更できます。
`~/.zshrc`に以下のように記述すると vim に変更されます。
```~/.zshrc
export EDITOR=vim
```

しかしVSCodeに変更する際に以下のように記述するとVSCodeは開きますが、編集前に`crontab -e`コマンドが終了してしまうためcorntabの編集ができません。

```~/.zshrc
export EDITOR=code
```

```zsh:ターミナル
$ crontab -e
crontab: no changes made to crontab
```

編集前に`corntab -e`コマンドが終了してしまうのを回避するために以下のようにします。

まず以下の内容で`code-wait.sh`を作成します。

```code-wait.sh
#!/bin/zsh
code --wait "$@"
```

次に`code-wait.sh`に実行権限を与えます。

```zsh:ターミナル
sudo chmod +x /path/to/code-wait.sh
```
または
```zsh:ターミナル
sudo chmod 755 /path/to/code-wait.sh
```

そして`~/.zshrc`に以下を追記します。

```~/.zshrc
export EDITOR=/path/to/code-wait.sh
```

すると編集前に`corntab -e`コマンドが終了してしまうのを回避できます。

![スクリーンショット 2022-09-16 18.27.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/171d1539-16f6-ffde-50dc-c32bc91313da.png)
いまさら"スレッド"についてまとめる

## はじめに
時々出てきて、雰囲気で使っている言葉にスレッドがある。await関数内などでこのスレッドに関する処理がいい感じに非同期処理を実現してくるらしく、こんな感じでも扱えてしまうところがカプセル化の力かと感謝するしかない。
ただ、甘えてばかりだと力もつかないので、雰囲気で受け取っていたスレッドへの浅い理解を深め、知ったかぶりから脱したい

## スレッドから思い浮かぶワード
* プロセスよりも小さい単位で、スレッドの集まりがプロセスとも言う
* JavaScriptはシングルスレッドで動作し、イベントループで
* Unityは、UIまわりをプログラムから変更する際、メインスレッドで行う必要がある
* スレッドセーフならマルチスレッドでも安心
* 掲示板のこともスレ（スレッド）って言うよね

シングル？　メイン？　セーフ？　スレッドに付随するワードが多くて、いろんな
文脈で出てくるからスレッドはややこしくなってそう。一つ一つ確認していきたい

## スレッドの辞書的な意味
まず、スレッド単体の意味はこれ
> スレッド（thread）とは、コンピュータプログラムにおいて特定の処理を行うための一貫性のある命令の流れのことであり、プロセッサ利用の最小単位[1]。プロセスは少なくとも1つ以上のスレッドを含む。一般的に各プロセスには独立した仮想アドレス空間が割り当てられるが、プロセス内のスレッド群はアドレス空間を共有する。そのためプログラムを実行するときのコンテキスト情報が最小で済み、同じプロセス内でスレッドを切り替える際はアドレス空間の切り替えが不要となるので、切り替えが高速になる[2]。 ([wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF)))

語源としては糸のことらしい
> 原義は縒り糸を構成している糸のうちの一本や、筋状の物体のうちの一本の筋などを意味する英語threadである。ここから派生し、同時進行する事象のうちの一つをあらわすようになった。 ([wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89))

### 糸とシングルスレッド
この例えで言うと、糸の端と端はプログラミングの文頭から文末に対応し、処理を上から下に順番で実行し、最後にスレッドは消える。糸の先端と先端の様に、ひと繋ぎになっている。シングルスレッドというのは、この糸が一本だけあって端から端まで他の糸が絡む子ことがない様子を表すのだろう。

一直線に上から下といっても、whileループやif文があれば一直線にならないと思ったが、whileの時は意図が途切れずその場で回るし、ifだと曲がるだけとイメージすれば、やはり途切れない糸というのは納得できた

### マルチスレッドの中のメインスレッド
メインスレッドはマルチスレッドがあることで出てくる言葉で、メインから枝分かれするサブスレッドがあるため、区別するためプロセスの開始から終了までを処理するスレッドのことをメインスレッドと呼ぶのだろう。マルチスレッドの中の一番太い糸(thread)をメインスレッドと呼ぶのだろう。

メインスレッドの途中からGitのブランチみたいに枝分かれすることがあるのが、シングルスレッドに対するマルチスレッドの違いということになりそう。
Gitでもブランチ切った後に合流しようとする時のコンフリクトが発生することがあるが、マルチスレッドも糸を増やせば絡まることがあるという話なのだろう。

### スレッドセーフ
> 複数のスレッドからメソッドやプロパティにアクセスされても問題が起きない、もしくは複数スレッドからアクセスされることを想定し排他制御が行われているようなクラスやメソッドを「スレッドセーフ」と呼ぶ

__排他制御__ で引っかかった。競合が発生しないようDBのようにロックするのはそれはそうかと思いつつ、ロックしている間にアクセスがる場合処理が進まないわけで、裏で別の処理をするためにスレッドを分けたのに排他制御で待たされたら、結局パフォーマンス上がらないじゃん! という疑問が自然と浮かぶ。
こういう本末転倒なことが容易に発生しうるのでマルチスレッドは難しいと言われるのだろう。
安易にマルチスレッドに手をつけるとパフォーマンスがそれほど向上しないにも関わらず、ログで追えないようなバグが発生するだけということになりかねない、というのが今の所の理解

## おわりに
UnityでUniTaskを使って非同期処理を書いている時、UIを操作しようと意した時に「メインスレッドから呼ばれていない」的なエラーに出会した。
おまじない的にObserveOnMainThread()を足して凌いでいたりしたが、これはUnityが描画を行うメインスレッド以外のスレッドでUI操作を行うとスレッドセーフで無くなるから例外として扱っている、と解釈できるのか？　　何はともあれ理解に一歩近づけた気がする。

## 参考
https://xtech.nikkei.com/it/article/COLUMN/20070416/268374/
[iOS]「Appが暗号化を使用する場合、輸出コンプライアンス書類をアップロードする必要があります。」のコンプライアンス問題

## はじめに
2022年のどこかのタイミングでアプリを審査に出すためにこのコンプライアンスエラーがビルドしたアプリに出て審査ができません。

## 原因
暗号化に対してコンプライアンス仕様が変わったために毎回出るようになっている。
米国、フランスで暗号化を使用するアプリの輸出入に規制があるためのよう。

方法として暗号化の質問をいくつか乗り切ればいいらしいが、そもそも「標準的な暗号化のみ、または暗号化を使用していない」場合は輸出の暗号化コンプライアンスに該当しないため回答する必要すらないです。

詳細はこちら
https://developer.apple.com/documentation/security/complying_with_encryption_export_regulations

## コンプラインスに該当しない場合の解決策

xcodeからinfo.plistにキー「App Uses Non-Exempt Encryption」を追加ししてNOを指定することでコンプライアンスのエラーに引っ掛からなくなる。

![app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/b0321314-3e9a-d4e6-e4e9-824e1a6af527.png)

## 最後
基本的なアプリであればコンプラインスに引っかからないため上記対応を行なっておけばOKです
5.マップ作製

**5.マップ作製**

タイル（画像）情報からマップを作成し、画面に表示する手順をまとめていきます。

・目次
1.GBMBダウンロード&配置
2.GBMBを使用してマップ作成
3.マップを表示
　P1.タイル、マップファイルについて


<br>
<br>
<br>
<br>

**1.GBMBダウンロード**
　以下の記事を参考にしました！
　配置場所は任意

https://qiita.com/blackpman/items/12258e6a9ee9f2d032de

<br>
<br>
<br>

**2.GBMBを使用してマップ作成**

GBMB.EXEを起動し、基本操作を確認してみる

メニュー
└File
　└Open・・・一度作成済みの".gbm"ファイルを開く
　└Save・・・保存（マップ加工情報）
　└Save As・・・新規ファイルで保存（マップ加工情報）
　└Reopen・・・一度作成済みの".gbm"ファイルを開く（開きなおし）
　└Map properties・・・タイルを読み込み、マップを作成
　└Location properties・・・属性設定（<font color="Red">別記事にてまとめ予定</font>）
　└Default Location properties・・・？？？
　└Export・・・GBに表示する用のソースファイルを出力
　└Export to・・・新規でソースファイル出力
　└Exit・・・アプリ終了

└Edit
　└Undo・・・直前操作を取り消す
　└Cut・・・タイルをコピー、ペーストできる
　└Copy・・・同上
　└Paste・・・同上
　└Copy as bitmap・・・不明（今度調べる）

└Design
　└Pen・・・ペン（線画）
　└Flood fill・・・バケツ（塗りつぶし）
　└Dropper・・・スポイト
　└Insert row・・・列追加
　└Insert column・・・行追加
　└Delete row・・・列削除
　└Delete column・・・行削除
　└Clear map・・・クリアする
　└Block fill・・・上下左右を指定してタイルを置ける

└View
　└Zoom・・・拡大縮小
　└Info panel・・・画面下にセル番地と属性を確認できる
　└Grid・・・ます目非表示
　└Double markers・・・ますの境界線を強調
　└Property Color・・・？？？
　└Auto update・・・アップデート？？（ファイル更新されたら反映？？）
　└Color set・・・色変更（プリセット）
　└Set bookmark・・・ショートカットをカスタマイズ？？
　└Goto bookmark・・・ショートカットをカスタマイズ？？

└Help・・・ヘルプ（開けない）



Map properties　時の設定内容

Size・・・マップのサイズを指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476538/b487b9aa-582d-f88d-22a4-bfcd9e5c7859.png)


Export to時の設定内容

Filename・・・ファイル名（ラベル名と同一のほうが分かりやすい）
Type・・・ファイルタイプ（拡張子）　GBDK　C　FileでOK
Label・・・プログラム内で使用する関数名的なもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476538/437c8f89-2a58-a667-9c23-07a0b61b243a.png)


Plane count・・・1 plane(8bit)を指定（理由は今度調べる）
Plane order・・・Planes are continuesを指定（理由は今度調べる）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476538/76418403-3383-bc2f-805f-43a064b2d0bf.png)


<br>
<br>
<br>

**3.マップを表示**
以下のコードを"main.c"に記載しマップを表示させる


```main.c
#include <gb/gb.h> 
#include <stdint.h>  //ライブラリ参照
#include "map.h"

// タイル単位のmapの位置
uint8_t map_pos_x, map_pos_y;

void main(){
    DISPLAY_OFF; //画面停止
    	SHOW_BKG; //背景の表示ON
		
    	set_bkg_data(0, 241u,Taile); //タイルを背景にセット

    	map_pos_x = map_pos_y = 0; 
		
		//サブマップ32×32 マスを越えるタイルマップを設定できる。
    	set_bkg_submap(map_pos_x, map_pos_y, 20, 18, Map, MapWidth);//初期表示位置
	
    DISPLAY_ON; //画面更新
```
◇解説
>#include <gb/gb.h> 
#include <stdint.h>  //ライブラリ参照
#include "map.h"
→GBMBで作成したマップのソースファイル（map.h）を記載

>uint8_t map_pos_x, map_pos_y;
→変数定義

>DISPLAY_OFF;
→画面を停止

>SHOW_BKG;
→背景の表示ON
		
>set_bkg_data(0, 241u,Taile);
→タイルを背景にセット

>map_pos_x = map_pos_y = 0; 
→初期値代入

>set_bkg_submap(map_pos_x, map_pos_y, 20, 18, Map, MapWidth);//初期表示位置
→submap関数で32×32 マスを越えるタイルマップを設定

>DISPLAY_ON;
→画面更新


コンパイル結果（large_mapサンプルの背景を変更できました！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476538/38b3ccab-6579-b7b0-e8a3-a4f7acc5cb85.png)


<br>
<br>
<br>

**P1.タイル、マップファイルについて**

GBTD、GBMBを使用してタイル、マップを出力する場合、
タイル名、マップ名に【const】（定数宣言）が記載されないため、手動にて【const】を記載する。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476538/b97a0a02-5b23-e5c7-3793-2dbe06d8568e.png)

<br>
<br>
<br>

以上！
次回はランダムエンカウントを実装し、バトルシーンに遷移しよう！
メモ：Dockerビルドステップの「apt-get update」で「executor failed running」エラー

Dockerビルド中に「RUN apt-get update」でエラーが出た。
GPG keyとかレポジトリへの接続の問題と思いきや、単にローカル環境の容量不足でした。


## 解決した方法

>$ docker system prune
WARNING! This will remove:
>  - all stopped containers
>  - all networks not used by at least one container
>  - all dangling images
>  - all dangling build cache
...
...
>Total reclaimed space: 43.17GB


------                                                                                      

## Error LOG
 > => ERROR [4/7] RUN apt-get update                                                                                   1.1s                           
 > [4/7] RUN apt-get update:
#0 0.753 Get:1 http://deb.debian.org/debian bookworm InRelease [147 kB]
#0 0.785 Get:2 http://deb.debian.org/debian bookworm-updates InRelease [52.1 kB]
#0 0.789 Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
#0 0.869 Err:1 http://deb.debian.org/debian bookworm InRelease
#0 0.869   At least one invalid signature was encountered.
#0 0.947 Err:2 http://deb.debian.org/debian bookworm-updates InRelease
#0 0.947   At least one invalid signature was encountered.
#0 1.036 Err:3 http://deb.debian.org/debian-security bookworm-security InRelease
#0 1.036   At least one invalid signature was encountered.
#0 1.051 Reading package lists...
#0 1.078 W: GPG error: http://deb.debian.org/debian bookworm InRelease: At least one invalid signature was encountered.
#0 1.078 E: The repository 'http://deb.debian.org/debian bookworm InRelease' is not signed.
#0 1.078 W: GPG error: http://deb.debian.org/debian bookworm-updates InRelease: At least one invalid signature was encountered.
#0 1.078 E: The repository 'http://deb.debian.org/debian bookworm-updates InRelease' is not signed.
#0 1.078 W: GPG error: http://deb.debian.org/debian-security bookworm-security InRelease: At least one invalid signature was encountered.
#0 1.078 E: The repository 'http://deb.debian.org/debian-security bookworm-security InRelease' is not signed.
>ERROR: failed to solve: executor failed running [/bin/sh -c apt-get update]: exit code: 100

------

## 参考
微妙にログは違うけど、同じ内容だった
https://qiita.com/yukia3e/items/6e2536dd90d34a8b01cc
https://note.yu9824.com/error/2022/03/19/docker-debian-gpg-error.html
PukiWikiのテーブルをカスタマイズ！スクロール・段毎に色を変えたい 

PukiWikiを作成しましたが、デフォルトのテーブルの使い勝手が悪すぎるのでプラグイン導入とCSSをカスタマイズすることにしました。

・目次

[1-前提条件](#1-前提条件)
[2-プラグインを許可](#2-プラグインを許可)
[3-プラグインを設置](#3-プラグインを設置)
[4-テーブルをカスタマイズ](#4-テーブルをカスタマイズ)




## 1-前提条件
PukiWiki バージョンを 1.5.3以上導入していること。
1.5.1では上手く動作しませんでした。(1.5.2は不明)

## 2-プラグインを許可

`php:pukiwiki.ini.php`にあるマルチプラグインの値を0にして許可します。

```php:pukiwiki.ini.php
define('PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK', 0); // 1 = Disabled
```

## 3-プラグインを設置

今回使用するプラグインは下記になります。

https://jpngamerswiki.com/?b437f86eb4

下記のGitから`datatable.inc.php`をダウンロードします。
ダウンロード完了したら、`plugin`フォルダにファイルを入れてください。

https://github.com/kanateko/pukiwiki-plugin

パーミッションを念のために変更しておきましょう。
私は`644`に変更しました。

動作確認してみます。
サンプルコードがあったのでWikiの編集ページにコピペします。

```
#datatable(number|string||hide|hide|date=YYYY-MM-DD|number|hide|){{
|~連番|~氏名（カタカナ）|~氏名（ローマ字）|~性別|~電話番号|~生年月日|~年齢|~出身地|~血液型|h
|1|コモリアヤネ|KomoriAyane|女|0495228672|1999-07-05|22|岡山県|B|
|2|コガヒデオ|KogaHideo|男|0189706790|1933-02-11|88|高知県|B|
|3|カミノゴロウ|KaminoGorou|男|0688183323|1962-06-14|59|愛知県|A|
|4|モリカワサイチ|MorikawaSaichi|男|0880784905|1967-03-25|54|福井県|O|
|5|ハマセイラ|HamaSeira|女|0273267688|2004-11-19|17|千葉県|O|
}}
```

無事テーブルが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/efd290fd-dffe-0836-eab0-12c96af3cc8a.png)

## 4-テーブルをカスタマイズ

しかしこのままだとスマホ表示やブラウザの幅を小さくするとテーブルが見づらくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/478939dc-5f19-64ac-9f80-28945a2d5a24.png)


文字が折り返しで表示させないようCSSをカスタマイズします。

変更前と変更後のコードを書きました。(コピペで使用できます。もしかしたら不要なプロパティがあるかも・・・)
カラーや線の太さはお好みで変更してください。


`skin/pukiwiki.css`を編集します。

```css:pukiwiki.css (変更後)


thead th.style_th,
tfoot th.style_th {
  color: inherit;
  background-color: #a2a2a2ce;
  border: dashed 1.5px #d3d0d0;
}

.style_table {
  padding: 0;
  border: 0;
  margin: auto;
  text-align: left;
  color: inherit;
  background-color: #ccd5dd;
  /* 追加 線を重ねる*/
  border-collapse: collapse;
  border: dashed 0.1px #d3d0d0;
  /* 追加 */
}

.style_th {
  padding: 5px;
  margin: 1px;
  text-align: center;
  color: inherit;
  background-color: #EEEEEE;
  /* 追加　波線をつける・横の破線は無効化する */
  border: dashed 0.1px #d3d0d0;
  border-top: none !important;
  border-bottom: none !important;
  /* 追加 */
}

.style_td {
  padding: 5px;
  margin: 1px;
  color: inherit;
  background-color: #dddddd;
  /* 追加　波線をつける・横の破線は無効化する */
  border: dashed 0.1px #d3d0d0;
  border-top: none !important;
  border-bottom: none !important;
  /* 追加 */
}

/* 新規追加　交互に色をつける */
table td {
  background: #eee;
}

table tr:nth-child(odd) td {
  background: #fff;
}

```


改行禁止と横スクロールを設定しました。
overflowは画面幅に合わせてスクロールしてくれます。


```css:pukiwiki.css (変更後)

div.ie5 {
  text-align:center;
  /* 追加 改行禁止と横スクロールを行う*/
  white-space: nowrap;
  overflow-x: auto;
  /* 追加 */

}
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/36b83279-3b01-cacf-ca0c-99d626ecd1ee.png)


無事テーブル内にスクロールバーが表示されました。



プラグイン無しの場合も正常に動作します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/495e6c88-362f-201a-185a-3a126075aa29.png)



以上になります。お疲れ様でした！