OmniAICreator/Qiita-1.07M huggingface dataset:
VirtualBox CentOS7をダウンロードする手順

### はじめに
VirtualBox CentOS7のisoファイルをダウンロードする手順を学んだため、まとめました。
※今回、一番小さいサイズのisoファイルをダウンロードするため、ディスクは使用しません。

**パソコンのメモリが最低でも8G以上必要です。** 私のPCはメモリ8Gのため、なんとか動作しています。

infracollegeにもダウンロードの動画があります。
https://infracollege.vamdemicsystem.black/linux/

### 前提条件
インターネットに繋がる環境であること
Windows端末であること
VirtualBoxをインストール済みであること

### 作業手順
#### ブラウザで「Download CentOS」検索し、Download - CentOSという検索にトップに上がるサイトをクリックする。
※検索の表示は状況によって変わる可能性があります。ダウンロードしたサイトを念のため、記載します。
https://www.centos.org/download/

#### CentOS linuxを選択し、今回、CentOS7のため、赤枠「7-2009」であることを確認し、任意のArchitecuturesのRPMsをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/a8925b63-9b29-3321-b828-e0dd6840c17d.png)

#### 赤枠のisosをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/a50f26db-3f48-9f39-cb82-cec02be98b52.png)
#### 赤枠のx86_64をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/ac530d49-37c0-d9c1-3c06-b04500ef0ff6.png)

#### 任意なものを選択し、クリックする。今回は以下の赤枠をクリックしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/1d837677-50cd-f185-c722-6d022a023edd.png)

#### CentOS-7-x86_64-Minimal-2009.isoをクリックする。
※今回はダウンロード時間を少なくするために、必要最小限のOSをダウンロードする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/2fde30ef-4bb6-8bed-dfaa-7fb8e1082f47.png)

isoファイルを保存する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/71a92259-07b1-274a-b622-3cd317fc5f77.png)
Windows端末にVirtualBoxインストールする手順

### はじめに
Windows端末に、VirtualBoxインストールを学んだため、まとめました。

infracollegeで学びました。
https://infracollege.vamdemicsystem.black/linux/

### 前提条件
Windows端末
インターネットに繋がる環境

### 作業手順
#### VirtualBoxをインストールする
「Downloads　VirtualBox x.x」をクリックし、Windows hostsを選んでダウンロードする
https://www.virtualbox.org/
※ブラウザで「VirualBox」で検索する。

exeファイルを端末に保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/f158b857-24a1-e9a0-8067-0b9a5a948bd8.png)


####  ダウンロードフォルダにある「VirtualBox-6.1.32-149290-Win.exe」をクリックする。
※VirtualBox-x.x.xx-xxxxxx-Win.exe 6.1.32等のexeファイルに含まれる数字は、変わる可能性があります。

#### 画面に従ってセットアップする。
「Next」をクリックする。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/362d63db-d627-2b49-2c4c-31557a70992c.png)
「Next」をクリックする。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/6284bf25-78ba-5635-7541-034e936958ec.png)
「Next」をクリックする。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/23c1ecd4-dd8f-ef0e-38fa-c380d165675c.png)
「Yes」をクリックする。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/ff904f53-d59b-c238-6203-f1d98f6d3097.png)
「Install」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/57374ce3-374b-b5fc-fcce-44e37429287b.png)

インストールが始まる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/55a44965-cfb1-32a1-bfd4-09c1197fbcca.png)

「Finish」をクリックする。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/5e051894-0547-52a9-9c5f-1658f6c4dd8b.png)
#### 　インストール完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/a7d21dfa-8db7-ad5b-3651-de87f6fb329e.png)
Effective Java 第3版まとめ（項目5）

# 項目5.資源を直接結び付けるよりも依存性注入を選ぶ

## 書かれている内容

* 多くのクラスが一つ以上の下層の資源に依存している
* たとえば、スペルチェッカーは辞書に依存している
* このようなクラスが静的なユーティリティやシングルトンで実装されていると、
柔軟性に欠けてテストできない(例えばテスト用の辞書を使うことができない)
* スペルチェッカーに辞書を変更するためのメソッドを追加すると、扱いにくく、間違いやすく、並行な環境では機能しない
* 新しいインスタンスを生成するときにコンストラクタに資源を渡す
* または、コンストラクタに資源ファクトリを渡す
* Supplier<T>インタフェースは、ファクトリを表現するには最適
Microsoft Excelのワークシート作成サブルーチン

# Microsoft Excelのワークシート作成サブルーチン

　Microsoft Excelというのはもともとマッキントッシュのアプリケーションだから、いろいろとマックの制限を引きずっている。誰もが気がつくのは「なぜ印刷したらセルから文字がはみ出るんだぁ！」
　これは、マックのフォントが画面表示と印刷で幅が違う！という仕様だったので、それをアプリケーションで対応したからだ、ということだ。

　それ以外の制限として「ワークシート名」というのがある。３１文字以内。禁則文字はMS-Windowsでは類を見ないもの。しかも（仕様には書いてないみたいだが）禁則文字を全角にして乗り切ろうにも、Windowsのファイル名と違ってやはりエラーメッセージが出る。これはマックのOSである漢字Talkには半角と全角の区別がない、という素晴らしい特性によるものである。

　というわけで、本来ならば「例えばVBAで、Microsoft Excelのワークシートを作る際には使おうとしているワークシート名がそれでいいのか、独自のチェックをかけないといけない」はずである。が、今のところ見つからないので、
自分で作りました。

　拡張子と思しきものがあれば取っ払います。
　禁則文字をアンダースコアで置き換えます。
　シート名を31文字で切ります。
　すでに同名のシートがあれば削除して再作成します。
こんなもんでいいかしら。

```
'＜シートがあれば消して、作り直す。シート名は引数＞
Sub シートドロップクリエイト(作成シート名 As String)

    If ワークシート名検証(作成シート名) Then
        Application.DisplayAlerts = False
        Worksheets(作成シート名).Delete
        Application.DisplayAlerts = True
    End If

    'Set ws = Worksheets.Add() 'シートを最初に追加する場合
    Set ws = Worksheets.Add(after:=Worksheets(Worksheets.Count)) 'シートを最後に追加する場合。

    ws.Name = 作成シート名
    
End Sub

Function ワークシート名検証(名前候補 As String) As Boolean
'Microsoft Excelはもともとマックのソフトなので、シート名の制限は漢字Talkのファイル名規則に従う。
'そこで、ワークシート名としようとした文字列を"名前候補"として渡し、規則に従っているかを検証。
'それでも３１文字に切り縮め、禁則文字を置き換えるくらいのサービスはするので、実質は、
'シート名を整え、その上で重複したシート名があれば、Trueを返す関数となる。

'仕様にはないが全角もダメ。Macが全角と半角を区別しないから
Const シート名禁則 = ":,\,/,?,*,[,],：,￥,／,？,＊,［,］"
Dim arrシート名禁則 As Variant

Dim s As Integer
Dim wk_名前候補 As String

Dim ws As Worksheet, flag As Boolean

    arrシート名禁則 = Split(シート名禁則, ",")

    'ファイル名をシート名にしたい時もあるので拡張子があれば除く
    If InStr(名前候補, ".") > 0 Then
        wk_名前候補 = Left(名前候補, InStrRev(名前候補, ".") - 1)
    Else
        wk_名前候補 = 名前候補
    End If
    
    'MS-Excelのシート名の制限31文字で切る
    wk_名前候補 = Left(wk_名前候補, 31)
    
    '名前候補に禁則文字があれば、半角アンダースコアに変換
    For s = 0 To UBound(arrシート名禁則)
        wk_名前候補 = Replace(wk_名前候補, arrシート名禁則(s), "_")
    Next s
    
    '同じ名前のシートがないか確認
    flag = False
    For Each ws In Worksheets
        If ws.Name = wk_名前候補 Then
            flag = True
            Exit For
        End If
    Next ws
    
    名前候補 = wk_名前候補
    ワークシート名検証 = flag
    
End Function
```
　同じような長い名前をつける羽目になったとき、最後に(1)とか(2)とかの序数をつけるというサブルーチンも作ったのですが、結局１回しか使ってないので、それは省略。
（もともと長いファイル名のブックがあって、各人がそれに記入した後、ファイル名に自分の社員番号をつけて保存するルールとなっていて、そういうのが同じフォルダにズラーっと並ぶというのがあったわけ。集計する側はとりあえず「ファイル名から拡張子を除いてシート名に」しようとしたのだけども、３１文字の制限超えるんで、作ったの。）

　ちなみにMicrosoft Excelという表記も昔の名残で、Excelってケミカル銀行のファームバンキングソフトの名前だったのだな。でもどうしてもExcelという名前が使いたかったので「かならずMicrosoft Excelと表記するから」と約束して使わせてもらえることになった。その後、ケミカル銀行はマニファチャラーズ・ハノーバー銀行に買収され、更にチェース・マンハッタン銀行に買収されたのでExcelというファームバンキングソフトは宙に浮いた時期があり、そのとき購入しておけば当然商標権はおまけでついてくるので、買っちゃいましょう！すごい宣伝効果ですよ！！と社内で提案したが無視されてしまった。
minio インストール on CentOS 8

CentOS8にminioをインストールしてsystemd管理できるようにするまで

# minio ダウンロード

公式からDL。バイナリがよさげ

https://min.io/download#/linux

```bash
wget -O /usr/local/bin/minio https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x /usr/local/bin/minio
```

# systemd設定

serviceファイルをDL

```bash
wget -O /etc/systemd/system/minio.service https://raw.githubusercontent.com/minio/minio-service/master/linux-systemd/minio.service
```

serviceファイルが参照するconfigの作成

```bash
cat <<EOT >> /etc/default/minio
# MinIO server のデータ保管先ディレクトリを指定
MINIO_VOLUMES="/var/lib/minio/"
# MinIO の起動ポートを変えたいときに変更
MINIO_OPTS="--address :9199 --console-address :9001"
# コンソールログインで利用するユーザ(3文字以上)
MINIO_ROOT_USER=minio
# コンソールログインで利用するパスワード(8文字以上)
MINIO_ROOT_PASSWORD=P@ssw0rd
EOT
```



ユーザ・ディレクトリ作成

```bash
useradd -s /sbin/nologin minio-user
mkdir /var/lib/minio
chown minio-user:minio-user /var/lib/minio
```

有効化して起動
```bash
systemctl enable minio
systemctl start minio
```

# 参考

https://github.com/minio/minio-service/blob/master/linux-systemd/README.md

https://qiita.com/uehatsu/items/1c00a84347c867b99ea0
初心者がLaravelでWebサービスを作るまで

## 現在開発中ですので随時更新中です！！

環境構築
Dockerで環境構築
MySQLのコンテナ内の/etc/my.cnfをchmod 444 my.cnfなどで読み取り専用にする。
"Ports are not available..."はPowershellでnetstat -ano | Select-String ":3306"、taskkill /F /PID 4545でポートを開放。

phpMyAdminはDockerコンテナ内の/etc/phpmyadmin/config.inc.phpをホストにコピーしてパスワードをMySQLのパスワードと同じに編集して、編集ファイルを/etc/phpmyadmin/config.inc.phpにコピーする。

設定周りをいじったら、php artisan config:cacheでキャッシュをクリアにすると解決することがある。Docker Desktopや本体の再起動が有効な場合もよくある。


開発
ホーム画面と主要画面の作成。


ホーム画面と主要画面のレイアウトとコントローラを作成し、ルーティングを設定。
nl2br,csrfなどに配慮。

テーブルとマイグレーションの作成
MySQLコンテナ内でCREATE DATABASE foobareats;でデータベースを作成。
Appコンテナ内でphp artisan make:migration create_foobars_table --create=foobarsでテーブルとマイグレーションファイルを作成。
マイグレーションファイルでカラムの設定。

ユーザ情報を渡す。
主要画面でPOST送信するので、モデルでリレーションメソッドを作り、コントローラで動的プロパティとを呼び出す。
Eloquentのモデルはテーブルの名前を明示的に指定しないかぎり、クラス名を複数形のスネークケースにしたものが、テーブル名として使用される。Foobarクラス->foobarsテーブルを採用。
N+1問題を解消するためにFoobar::with('user')->get();などとしてeagerloadする。
不正なリクエスト対策として$fillableを記述。

Selectboxの値を渡す。
マイグレーションファイルとモデルを作成。
php artisan migrate でテーブルを作成。
コントローラのcreate()メソッドで 
$examples = Example::all();
$examples_name = $examples->pluck('name');
とし、viewに渡す。
{{ Form::select('example', $examples_name, null) }}
で表示。

認証機能を実装
Breezeをインストールする。lang/ja.jsonで日本語仕様へ変更。
ルーティングが上書きされるので環境構築後に導入するべし。
【Typescript】型推論されたオブジェクト型のキーをオプショナルにした型を作る


絶対に忘れるのでメモ。

https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#handbook-content

2022-04-18追記
知識浅すぎて悲しくなりました。
`Partial`というそれ用の型宣言方法がありました。

https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype

内部でやってることはこの記事と似てる。

# やりたいこと
変数宣言時にオブジェクト型を代入すると勝手にその値の`key`を持った型として定義される。
そのオブジェクト型変数のキーをオプショナルにした上で他の変数の型として使いたい。

単純にその型を書けばいいんだけど面倒なので書きたくない。
新しく追加するたびに型の部分も値の部分も直さなきゃだし。

```ts
const ErrorMessages: {
  // ここを書きたくない
  logInFaild?: string;
  invalidValue?: string;
} = {
  logInFaild: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}

const messages: typeof ErrorMessages = {}
```

# 結論
ここまでの内容で察せられる人用。

```ts
const ErrorMessages = {
  logInFaild: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}
type keys = keyof typeof ErrorMessages
type ErrorMessageType = {[key in keys]?: string }

const messages: ErrorMessageType = {}
```

```ts
// ↓定義される型
type ErrorMessageType = {
  logInFaild?: string | undefined
  invalidValue?: string | undefined
}
```

# 詳しく
オブジェクト型（辞書型）を変数に入れると型推論によって勝手に型が決まる。

例としてはこんなシチュエーション。

表示するメッセージの一覧的な定数（＝メッセージ辞書）を作る。
実際にメッセージを入れておく変数には、メッセージ辞書のキーと値を入れる。

メッセージ変数のキーはメッセージ辞書に存在するもののみに制限したい。
そのメッセージが不要な時は値を入れたくないのでオプショナルにもしたい。

コードにするとこう↓
```ts
const ErrorMessages = {
  logInFailed: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}

const messages = {}

if (login()) {
  // ログイン成功
} else {
  // ログイン失敗
  messages.logInFailed = ErrorMessages.logInFailed // エラー
}
```

このままだと`messages`には`{}`型、つまり「キーを持たないオブジェクト型」が定義されているので`エラー`部分でエラーになる。

```
Property 'logInFailed' does not exist on type '{}'
```

# 解決方法（結論部分の説明）
`typeof`、`keyof`、`in`、`Mapped Types`を組み合わせて解決する。

まず`typeof`と`keyof`で「メッセージ辞書のキーのみを入れられるstring型」を作る。

```ts
const ErrorMessages = {
  logInFaild: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}

type keys = keyof typeof ErrorMessages
// 実際に作成される型
// type keys = "logInFaild" | "invalidValue"
```

[Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)でキーを制限したオブジェクト型を作るが、その時に`?`を付けてオプショナルにする。

```ts
type ErrorMessageType = {
  [key in keys]?: string // `key`には'logInFaild'と'invalidValue'しか入れられない
}
```

これでメッセージ変数を宣言すればキーがオプショナルなオブジェクト型ができる。

```ts
const messages: ErrorMessageType = {}
```
GAS:シートの存在確認はgetSheetByName()で済む

# GASは公式ドキュメントが一番
後輩のコードレビューをしていた時、**今月のシート**というものが設定されているスプシファイルに対して、全シートをforループで走査していたのを発見。
試しに「GAS シート　存在確認」でググったところ、上位4件中3件が、
「一発で存在確認できるクラスはない」
「自作関数を用いて簡素化せよ」
という内容のブログだったので、あえて否定記事を書かせていただきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984110/aa4e1654-8d2e-66c5-67e2-e16e8c5d53b8.png)

存在するシートの名前の全てを走査しなくとも、`getSheetByName()`で存在しないシートを参照した場合、`null`が返ってくるので、ifステートメントでnullじゃないことを確認すれば済む。

「GAS check sheet existance」と検索すると一番に出てくるのがこちらの記事↓
https://stackoverflow.com/questions/48974770/check-for-existence-of-a-sheet-in-google-spreadsheets
```Javascript
var ss = SpreadsheetApp.getActiveSpreadsheet(); 
var sheet = ss.getSheetByName('SHEET_NAME');

 if (!sheet) {

   //DO;
}
```
※nullはfalseになる。

公式ドキュメントにもしっかり
`Returns null if there is no sheet with the given name.`
と書いてある。
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getsheetbynamename
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1984110/31e81066-13ec-88a9-ce22-11a54caee515.png)

ちなみにここにも注意。
`If multiple sheets have the same name, the leftmost one is returned.`
（同じ名前で複数のシートがあった場合、一番左側(最初に見つかった分)のシートが返ってくる）

1. 英語でググりましょう。量と正確さが違う。
1. GASは公式ドキュメント参照するのが一番
【SourceTree】GithubからCloneできない問題

GithubからSourceTreeを介してCloneしようとしたら、「リボジトリのクローン」のポップ画面で、
「ソースパス、またはソースURLとして正しくありません」という画面が出てクローンができなかった。

下記画面のソースURLにGithubのSSHからURLをコピーして貼っても
「これは正しいGitリボジトリです」にならない。

![スクリーンショット 2022-04-17 4.04.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145328/003056ce-7ad2-4d17-3d17-83fbe886ed00.png)

ちなみにもちろん、GithubにSSH設定はしていて、前はそれでクローンできていた。
しかし、久しぶりにクローンしようとしたらできない。

そこで対策方法を検索してみたら

１）ホスト名とソースURLが違っている
（参考）
https://qiita.com/daijiro_maeyama/items/002301850c998b13a3aa
→同じだった
２）httpsの方法に変えてみる
Githubはパスワード認証を廃止し、トークン認証になるようで、これが私には合わなかったのでSSHでなんとかできないか検討.
(参考）
https://news.mynavi.jp/techplus/article/20201222-1604003/
３）SSHを再度作成する
基本的にはこれでうまくいった。
以下はSSHの作成方法について説明する

a) SSHディレクトリに移動
```
$ cd ~/.ssh
```
b) 公開鍵の生成コマンドを打つ
```
$ ssh-keygen
```
ｃ）　すると下記画面が出る
すでに前に作成したSSHキーが存在しているので
上書きするか聞かれるのでyキー押す
```
Generating public/private rsa key pair.
Enter file in which to save the key (/(パス名）/.ssh/id_rsa): 
/（パス名）/.ssh/id_rsa already exists.
Overwrite (y/n)? y
```
ｄ）するとパスワードを記入してEnterを押してと言われるので記入してEnter
（※ちなみにパスワード記入しないでEnterでもOK。ここらへんは好みで)
※ちなみにパスワードを記入しても画面には出ないが、ちゃんと認識されてる
Enterを押すと下の行、つまり同じパスワードを記入してと言われるので記入してEnter
※もちろん上で記入してなければただEnterでOK）
```
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
```
e) すると下記の画面（実はもっとあるがセキュリティ上割愛）が出て
作成されたことがわかる。

```
our identification has been saved in /(パス名）/.ssh/id_rsa.
Your public key has been saved in /（パス名）/.ssh/id_rsa.pub.
```
f)つぎにSSHをコピーする、まずは上で作ったファイルをコマンドラインで開く
```
cat ~/.ssh/id_rsa.pub
```
※ちなみにｐｂcopyの方法は私の場合うまくいかなかった
https://qiita.com/tetsu-upstr/items/e72147250701cf30ee72
どうやらコマンドが登録されていなかったらしい。
なので上の方法を使った

g)すると中身が出るので、「ssh-rsa」から最終行までを選択してコピー（Ctrl+c)
※セキュリティ上キャプチャは割愛

h)GitHubのsetting画面から「New SSH」で公開鍵をペーストして
タイトルは私の場合SourceTreeのためにつくったのでまんま「SourceTree」にした
タイトルは何でもいいと思う
その下にｇ）でコピーしたSSHをペーストして「Add SSH key」ボタンを押せばSSHが作られる

i) コマンドラインに戻って確認(下記コマンドを打ってEnter)
```
ssh -T git@github.com
```
j) パスを作っていればこの画面が出るのでパスワードを打ってEnter
```
Enter passphrase for key '/(パス名）/id_rsa':
```
ｋ）この画面が出れば、登録に成功
```
Hi (ユーザ名)! You've successfully authenticated, but GitHub does not provide shell access.
```
l)　再びクローンしてみると、「これは正しいGitリボジトリです」になり、問題解決

以上
2022/4/17主にITとかセキュリティの記事

「Chrome」や「Microsoft Edge」にセキュリティ更新 - ゼロデイ脆弱性に対応
https://www.security-next.com/135848

ＪＲ西子会社に不正アクセス＝個人情報４６５０件流出か(4/15)
https://news.nifty.com/article/economy/economyall/12145-1580705/

ざんねんなセキュリティ--流行のゼロトラストが「既に導入済」は本当か？(4/15)
https://japan.zdnet.com/article/35186181/

【金融庁】日銀との連携で地銀のサイバー対策を調査(4/15)
https://news.mynavi.jp/techplus/article/20220415-2322766/

CISAなど米政府機関、産業制御システム狙うマルウェアについて注意喚起(4/15)
https://japan.zdnet.com/article/35186362/

【記者のひとこと】ゼロトラストの実現に向けて(4/15)
https://www.bcnretail.com/market/detail/20220415_275234.html

北朝鮮ハッカー集団 オンラインゲームに攻撃で約780億円盗難か(4/15)
https://www3.nhk.or.jp/news/html/20220415/k10013583921000.html

北朝鮮、オンラインゲーム暗号資産780億円奪取　米当局(4/15)
https://www.nikkei.com/article/DGXZQOCB152OA0V10C22A4000000/

北朝鮮のハッカー集団、暗号資産780億円盗む 米FBI(4/15)
https://www.afpbb.com/articles/-/3400459?act=all

チェック・ポイント、3月に最も活発だったマルウェアを発表　Emotetの国内の影響は約2.5倍以上に急増(4/15)
https://www.jiji.com/sp/article?k=000000103.000021207&g=prt

トレリックスの報告書がインド、オーストラリア、日本の政府機関と重要インフラ・プロバイダーのサイバーレディネスを評価(4/15)
http://mjp.acrofan.com/article_sub3.php?number=98082&lang=

ベイスターズ、名場面デジタル動画　利用者間売買可能に(4/15)
https://www.nikkei.com/article/DGXZQOCC157WJ0V10C22A4000000/

3月マルウェアランキング、Emotetが1位で猛威続く(4/15)
https://news.mynavi.jp/techplus/article/20220415-2320819/

ネット印刷のプリントオンもEmotet感染、顧客から不審メールについて連絡があり発覚(4/15)
https://s.netsecurity.ne.jp/article/2022/04/15/47476.html

北朝鮮ハッカー集団　6億ドル超の暗号通貨盗む　米財務省(4/15)
https://jp.sputniknews.com/20220415/6-10634180.html

ゲーム攻撃で７００億円窃取　北朝鮮ハッカー、最大規模(4/15)
https://www.sankei.com/article/20220415-QJYIA5Z5CFKHHDDHILJTLAONRQ/

検索や閲覧履歴を見られたくない！プライバシー最優先なMac向けブラウザ誕生(4/15)
https://www.gizmodo.jp/2022/04/duckduckgo-beta-browser.html

テザーUSDT、クサマネットワーク（KSM）上で発行(4/15)
https://www.neweconomy.jp/posts/214786

高額なアプリ手数料など負担に、モバイルOS寡占状態の問題を訴え――デジタル庁の会合で楽天・三木谷氏(4/15)
https://gunosy.com/articles/evImc

iOS上で、「アプリからのトラッキング要求」を許可するユーザーが昨年から大幅に増加(4/15)
https://iphone-mania.jp/news-450167/

無料と思ったら実態は…！ Macのアプリストアで「無料と見せかけた詐欺的アプリ」がランキング上位に複数あると報告(4/15)
https://news.nicovideo.jp/watch/nw10802351

ゲームに攻撃、７８０億円窃取 北朝鮮ハッカー、最大規模 (4/15)
https://www.the-miyanichi.co.jp/news/World/2022041501000487.php

スマホにマイナンバーカード搭載、22年度中にもAndroidで実現へ(4/15)
https://gunosy.com/articles/eiF7a

Web3には根本的な矛盾がある。｢自由で民主的なインターネット｣というユートピアが実現しそうにない理由(4/15)
https://www.businessinsider.jp/post-253067

WordPressプラグインにCVSSv3スコア9.9の脆弱性　500万のWebサイトに影響か(4/15)
https://www.itmedia.co.jp/enterprise/spv/2204/15/news032.html

みずほFGとみずほ銀行、業務改善計画の進捗状況について発表(4/15)
https://www.nikkei.com/article/DGXZRSP630614_V10C22A4000000/

サイバー犯罪防止へ連携強化　警視庁と関連企業が協議会実施(4/15)
https://www.iza.ne.jp/article/20220415-MN2DSAP3VBKCBB4ZYWBZZPTOIQ/

サイバー企業を生み出すイスラエル国防軍の「8200部隊」とは？(4/15)
https://forbesjapan.com/articles/detail/46945

銀行の未来：ヒントはテレコムの歴史の中にある【コラム】(4/15)
https://www.coindeskjapan.com/146348/

カード情報窃取に気づかない　ウェブスキミングの手口(4/15)
https://www.nikkei.com/article/DGXZQOUC0720X0X00C22A4000000/

SSL証明書を無料で発行するLet’s Encryptが実世界の暗号化貢献をたたえる「レブチン賞」を受賞(4/15)
https://gigazine.net/news/20220415-lets-encrypt-receives-levchin-prize/
Pytorchで学習再開

![omoide048.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/2ae8c95f-47f3-373e-9076-c3630a27d658.jpeg)

# Pytorchでモデルをsave/loadして学習を途中から続ける方法です

学習の途中で、（コンピューターや人間の都合で）一旦中断して、後で学習を再開したい時があります。
Colabのような連続使用時間に制限があるような環境や、学習エポック数の初期設定に追加して学習したいときなどに、モデルの重みをファイルとして保存して、後でロードして再開したい。

# モデルを保存するだけでは、同じ正解率から学習再開できない

モデルの保存と読み込みは以下の通りですが、これは、復元したモデルをevalモードで単に推論に使うときは機能しますが、学習を再開しようとすると、ロスや正解率が保存前から継続せず、初期値に戻ってしまっていることに気づきます。

```python
# 保存
torch.save(model.state_dict(), PATH)

# 読み込み
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load(PATH))
model.eval()
```
# Optimizerも保存すべし

学習を継続して再開するには、モデルの重みの状態に加えて、Optimizerの状態も保存／ロードする必要があります。

```python
# 保存
save_path = "my_model_training_state.pt"
torch.save({'epoch': epoch,
            'model_state_dict': model.state_dict(),
            'optimizer_state_dict': optimizer.state_dict(),
            'loss': loss,},
           save_path)

#　読み込み
model = TheModelClass(*args, **kwargs)
optimizer = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)

PATH = "my_model_training_state.pt"
checkpoint = torch.load(PATH)
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# optimizerのstateを現在のdeviceに移す。これをしないと、保存前後でdeviceの不整合が起こる可能性がある。
for state in optimizer.state.values():
    for k, v in state.items():
        if isinstance(v, torch.Tensor):
            state[k] = v.to(device)
epoch = checkpoint['epoch']
loss = checkpoint['loss']

# model.eval()
# # - or -
model.train()

model = model.to(device)
criterion = nn.CrossEntropyLoss()
exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)
```

これで、保存前のロスと正解率から再開できる。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
Raspberry Pi Pico が無限ループして焦った話。

## 結論
出荷状態にするだけで良かった。
flash_nuke.uf2イメージをインストールするだけ。

> インストール先：https://datasheets.raspberrypi.com/

## インストール方法
いつも通り、わからない場合は以下参考
参考：https://www.raspberrypi.com/documentation/microcontrollers/micropython.html
結局WSLはUbuntuでいい

WSLの使用用途によってこれが向いてるとかこれは向いてないとかあると思うが僕が色々なディストリを擦って感じたことを簡単にまとめてみる。
**結論から言うとUbuntuでいい。**

### 環境
Windows11 WSLgあり

#### ArchLinux
悪くないけどMicrosoft Storeにないので自分で環境を作る必要がある。
Arch Wikiは最強なのでこれ使いこなせる人は普通に選択肢に入れてもいい気はする。

#### GentooLinux
論外。emergeとかで気持ちよくなれるドM専。
一応環境構築の記事はあるので興味があったらどうぞ https://qiita.com/nashinium/items/d6f6c04a98edf847f195

#### Ubuntu
マイクロソフトも開発に携わっているせいか、すごくwindowsとの相性がいい。
1. WSLgで動くGUIアプリケーションがWINDOWSのスタートに登録されるのでアクセスしやすい
1. 困ったら検索したら大体何とかなる（記事が多い）
1. Microsoft Storeからボタンワンクリックでインストールできる、楽

## 結論
Linux宗教に入ってない上、特殊な運用をするのでこのディストリじゃダメとかじゃない限りUbuntuでいいとワイトは思います。
【AtCoder】 ABC248【参加記録】

# [A - Lacked Number](https://atcoder.jp/contests/abc248/tasks/abc248_a)

```python
from sys import stdin

inputstr = stdin.readline()
numset = set([str(i) for i in range(0, 10)])

ans = [i for i in numset if i not in inputstr].pop()

print(ans)
```

問題の制約より、**0～9の数字のうち、入力文字列に登場しない数字はちょうど1つのみ**だと分かっている。

これは、0～9の数字からなる集合のなかには、入力文字列に含まれない数字が必ず1つ存在するということだと言い換えられる。

というわけでそれを素直にコードに落としこんだのが上記のコードである。

…………この文章を書いていて気付いたことだが、このロジックなら以下のコードのように、集合演算を利用した方がもっとスマートだったかもしれない。（試しに提出してみたところ、実行時間は変わらなかったので個人的な美意識の問題）

```python
from sys import stdin

inputstr = set([i for i in stdin.readline().rstrip()])
numset = set([str(i) for i in range(0, 10)])

ans = inputstr ^ numset

print(ans.pop())
```


# [B - Slimes](https://atcoder.jp/contests/abc248/tasks/abc248_b)

```python
from sys import stdin

a, b, k = tuple(int(i) for i in stdin.readline().split())
answer = 0
while a < b:
    a *= k
    answer += 1

print(answer)
```

単純にwhile文でループさせた。

# [C - Dice Sum](https://atcoder.jp/contests/abc248/tasks/abc248_c)

解けなかった。どう解けばいいのかもわからなかったので、精進の必要性を感じる。

また、問題文見た時点でpythonでやると実行時間が厳しいことになりそうだと感じたのでこの問題はGoで解くことにした。

しかし、**試験終了後に公開された公式の解説を見ながら数時間四苦八苦してようやくACできた**、という有様なのでアルゴリズムの勉強だけでなくGo言語（に限らず、Pythonよりも実行速度が高速な言語。C++, Rustあたり）の勉強もしていかねばならないと思う。

（ちなみになぜ今回Go言語を使おうとしたのかについては、特に理由はない）


# D問題以降

問題を見てすらいない。理由はC問題で詰まったのと、ちょうどテレビで放送していた『ドラゴンボール超ブロリー』に見入っていたことの二つ。ドラゴンボールにはあまり興味がなかったが、そんな私でも夢中になれたのでとても良い映画だったのだと思う。
ABC248 A~DをPythonで解く！

# はじめに
そろそろ茶色コーダーから抜け出したいChunky_RBP_Chanです。
ABC248 A~Dを解いたのでシェアします。

https://atcoder.jp/contests/abc248

# A: Lacked Number
https://atcoder.jp/contests/abc248/tasks/abc248_a
## 問題
0~9のうち9種類使った文字列Sが与えられるので使われていない数字を求めよ
## 解答
文字列を全部見て、ない数字を出力すればよいです。

```python
S = input()
for i in range(10):
    for j in range(len(S)):
        if i == int(S[j]):
            break
    else:
        print(i)
        break
```
# B: Slimes
https://atcoder.jp/contests/abc248/tasks/abc248_b
## 問題
一回叫ぶごとにK倍に増殖するスライムがA匹いる。B匹以上に増やすには何回叫べばよいか
## 解答
愚直にAをK倍してBを超えるまで繰り返せばよいです。
```python
A,B,K = map(int, input().split())
num = 0
while B > A*K**num:
    num += 1
print(num)
```
# C: Dice Sum
https://atcoder.jp/contests/abc248/tasks/abc248_c
## 問題
長さ$N$の数列$A = (A_1,...,A_N)$のうち
$1\leq A_i \leq M$
$\sum_{i=1}^{N}A_i\leq K$
を満たす数列$A$の個数を998244353で割った余りを求めよ。
## 解答
$N+1$行$K+1$列の配列を用いてDPにより答えを求めます。
$dp[i][j]=i-1$番目までの和が$j$である個数
DPの更新式
$dp[i+1][j+k] += dp[i][j] \space (j+k \leq K)$
を考えれば、$N$番目までの和が$K$以下となる個数は$dp[N][j]$ $(j\leq K)$の和です。

```python
N,M,K = map(int, input().split())
dp = [[0]*(K+1)for _ in range(N+1)]
dp[0][0] = 1
for i in range(N):
    for j in range(K+1):
        if dp[i][j] == 0:
            continue
        for k in range(1,M+1):
            next = k+j
            if next <= K:
                dp[i+1][next] += dp[i][j]
print(sum(dp[-1])%998244353)
```

# D: Range Count Query
https://atcoder.jp/contests/abc248/tasks/abc248_d
## 問題
長さ$N$の数列$A = (A_1,...,A_N)$と$Q$個のクエリが与えられる。
クエリごとに$L,R,X$が与えられるので$A_L,...,A_R$の中で$X$と等しいものの個数を求めよ。
## 解答
$L$,$R$,$X$が与えられたとき$A_i=X$となる添字を$B_j$とします。($j=1,...,$($A_i=X$となる$i$の個数))
$B_{j+1}$より前にある$X$は$A_{B_1},...,A_{B_j}$の計$j$個なので、
$B_{j} \leq L < B_{j+1}$
$B_{k} \leq R < B_{k+1}$
となる$j$、$k$を二分探索により見つければ$X$は$L$までに$j$個あり、$R$までには$k$個あることがわかります。
したがって$L$から$R$までにある$X$の個数は
$A_L=X$の場合  $\space k-j+1$
$A_L\neq X$の場合 $\space k-j$
解答では、$1$から$N$までをキーに持つ辞書numdictに$B_j$を配列を保管し、各クエリごとキー$X$がもつ配列について二分探索を行います。

**例** $A=(1,2,1,1),L=1,R=3,X=1$の場合
数列$A$で$1$となる添字は$[1,3,4]$であり、$L$と$R$は
$B_1\leq L < B_2$,
$B_2 \leq R < B_3$
を満たします。したがって、$L$までに$X$と等しいのは$A_{B_1}$の１つ、$R$までには$A_{B_1},A_{B_2}$の2つがあり、
$A_L=1$なので答えは$2-1+1=2$

```python
def bisect(x,ind,size):
    ok = -1
    ng = size
    while abs(ok-ng) > 1:
        mid = (ok+ng)//2
        if ind >= numdict[x][mid]:
            ok = mid
        else:
            ng = mid
    return ok

N = int(input())
A = list(map(int, input().split()))
Q = int(input())

numdict = {i:[-1] for i in range(1,N+1)}
for i in range(N):
    num = A[i]
    numdict[num].append(i)
for i in range(Q):
    l,r,x = map(int, input().split())
    L = bisect(x,l-1,len(numdict[x]))
    R = bisect(x,r-1,len(numdict[x]))
    print(R-L + (A[l-1] == x))
Blenderのアニメーション付き3DオブジェクトをReality Converterでusdz拡張子で書き出す

※この記事はMacで行う前提で記述しておりますので悪しからず

## なぜusdz拡張子を使おうとしたのか
[Cubemint](https://www.thecubemint.com/)というアプリの開発に参加させてもらっている中で、
3Dオブジェクトを利用するシーンが出てきたため、
Xcodeと親和性が高いusdz拡張子の3Dオブジェクトを制作することになりました。

## usdz拡張子だとどんなことができるのか
1. usdz拡張子のファイルをiPhoneで開くと画像のようにアプリなどを介さずともAR表示が可能。
2. Xcode及びAR開発と親和性がいい(？)

1がわかりやすいですね。後述するReality Converterというusdz変換ソフトで変換したファイルをiOS端末で開くと画像（[引用元](https://xtech.nikkei.com/atcl/nxt/column/18/00485/00005/?P=4)）のようにAR表示されます。
iOS端末を対象としたサービスであればこのファイルを開く仕組みを作るだけで簡単なARアプリができてしまいますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/f30538ef-b2d1-03ab-c628-8644f63b439a.png)

2に関しては僕はコーダーではないのでわかりかねますが、MacでAR開発をする人は一度触ってみてはいかがでしょうか。

## 実践編
1. まずはBlenderでusdzで書き出す任意のオブジェクトをモデリングします。
今回はこの立方体と正二十面体（だったはず）が捻れていくアニメーションを書き出していきます。
![usdz化するオブジェクト.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/9ef65b51-a422-b829-5e2c-c0ad5f1eb244.gif)
アニメーションの時間やオブジェクトの大きさの上限があるという記事をどこかで見たことがある気がしますが、正確には把握していないので見つけた方はコメントなどお待ちしております。

2. Reality Converterをインストールしましょう。
こちらのソフトはAppleのベータテスト版のソフトになりますので、
https://developer.apple.com/jp/augmented-reality/tools/
↑こちらからダウンロードくださいませ。
起動するとこのような画面が表示されると思いますのでそれで完了です。
![スクリーンショット 2022-04-17 1.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/10e17cb8-16a5-312a-fbb9-414f5ee5e0f0.png)

3. Blenderを書き出したものをReality Converterで開く。
Reality Converterは2022/04/17現在はOBJ/GLFLに正式しております。
Blenderで書き出す際、オブジェクトがアニメーションの場合はGLTFで良いかと思いますので、
今回はGTLFで書き出します。
Blenderで、[ファイル>エクスポート>glTF]を選択し、任意のフォルダに書き出しましょう。
![スクリーンショット 2022-04-17 1.48.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/44449468-e740-ba20-0c35-d7bfe8e1d6f8.png)
書き出しが完了したら、そのファイルを先ほどのReality Converterの起動画面にドラッグ&ドロップしてください。
上手くいけばこのように表示されるかと思います。
![スクリーンショット 2022-04-17 1.39.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/217cedb2-46e8-0cad-912e-f0b02d2444cf.png)
マテリアルやその他表示の詳細を編集する場合は右上のタブから変更が可能です。
![スクリーンショット 2022-04-17 1.40.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/e8077a85-bb80-9dc9-55de-40195824a405.png)
画面右上のアップロードマークから書き出し先を選択して保存しましょう。
<font color="Red">※この時、画面下のアニメーション停止ボタンを押してアニメーション開始状態をリセットしてから書き出しましょう。これをしておかないと書き出した時にアニメーションの終了時点からアニメーションが開始されて表示がバグるのを確認してます。</font>
書き出したものをiPhoneで開いてみると…
![usdzできたよ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1799122/d2f2d135-4dc9-f0e9-f310-297d8ba1fc9b.gif)
上手くできましたでしょうか？
usdz形式であれば手軽にAR表示が楽しめるので色々できそうな気がしますね！
それではまた👋
AtCoder Python 解答通りなのにTLE

# 回答通りのコードなのに、、、
PythonでとあるC問題に挑戦していました。
しかし、実行しても
**「TLE」**
の結果が返ってくる、、

あきらめて解答を見てみたら、
**合ってるやん！！**

まさかこんなに早い段階でPythonの限界が、、！？

# 対策
**言語をPyPy3で実行する**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522297/5cf03efa-4374-c56a-7603-f0b73b35b5c7.png)


PyPyはJITコンパイル機能があり、Pythonのコードを高速に実行できる言語です。ほぼほぼPythonのコードでもコンパイルしてくれます。
Galaxy Watch4の開発者設定

一般的なWear OS端末の開発者設定は下記のドキュメントに書いてありますが、Galaxy Watchだとうまくいきませんでした。
https://developer.android.com/training/wearables/apps/debugging?hl=ja

## 開発者モードを有効にする

1. 「設定」→「時計について」→「ソフトウェア」に移動
2. 「ソフトウェアバージョン」を連打

以上の手順で「設定」アプリに開発者向けオプションが表示されます。

## Wi-Fiデバッグの有効化

1. 「設定」→「開発者向けオプション」に移動
2. 「ADBデバッグ」をONにする
3. 「Wi-Fiでデバッグ」をONにする

## Android Studioと接続

### IPアドレスの取得

Galaxy Watchで下記の手順を実行する。

1. 「設定」→「接続」→「Wi-Fi」に移動
2. 接続中のWi-Fiをタップ
3. 「IPアドレス」の値をメモする

### 接続

1. PCでターミナルから`adb connect [メモしておいたIPアドレス]:5555`を実行。
2. Galaxy Watchに「接続を許可しますか？」的なダイアログが出るので許可する。

![スクリーンショット 2022-04-17 2.04.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155135/d9f2ad5c-b977-6a5c-2aa8-b143aba30b2e.png)

Android Studioで認識されればOK。
common lispで再帰によるsquash関数を書いてみる

# common lispで再帰によるsquash関数を書いてみる

[再帰プログラムいろいろ(続き) : セマンティックウェブ・ダイアリー](http://blog.livedoor.jp/s-koide/?p=3)

>	問題 2.16
リストを引数とし，その中のアトムだけを取り出してならべたリストを返す関数 squash を定義せよ．
>
>eval> (squash '(a (a (a (a b))) (((a b) b) b) b))
(a a a a b a b b b b)

こちらに掲載のある問題について、私なりの解き方を振り返ってみたいと思います。前提としてsquash関数は比較的簡素に書くことができたよね。。。といううろ覚えの記憶がござますのであしからず。

## 再帰関数の骨格を作る
まあ再帰関数なので、おおよそ骨格が決まっているんじゃないか。。。という予測からなんとなく骨格をつくりたいです。

また、appendを使うとリストの層を引き上げられるという経験則から。。。以下のような骨格を作りました。

```common-lisp
(defun squash0 (tree)
   (cond ((null tree) nil)
		(t (append (car tree)
				   (cdr tree)))))
										; => SQUASH0
(squash0 '(a))							; => error
(squash0 '((a)))						; => (A)
```
errorが出てはいるものの、'((a))が'(a)と層が引き上げられており、これを使いたいなぁ。。。という感じになります。

## CAR方向に再帰してみる

関数squash0は再帰関数になっていないので、とりあえずCAR方向に再帰してみます。また、(squash0 '(a))のエラーは、appendの際にCARがリストになっていないのが原因ですので、とりあえずリストにして返します。

```common-lisp
(defun squash1 (tree)
  (cond ((null tree) nil)
		((atom tree) (list tree)) ;; ここ
		(t (append (squash1 (car tree)) ;; ここ
				   (cdr tree)))))
										; => SQUASH1
(squash1 '(a))							; => (A)
(squash1 '((a)))						; => (A)

(squash1 '(((a))))						; => (A)
(squash1 '(a b))						; => (A B)
(squash1 '(a (b)))						; => (A (B))

```
とりあえず、CARに関しては良さそうだな・・・という感触が得られます。

少しずつテストを増やしていきます。

## CDR方向に再帰してみる

さらにCDR方向に再帰してみます。
```common-lisp
(defun squash2 (tree)
  (cond ((null tree) nil)
		((atom tree) (list tree))
		(t (append (squash2 (car tree))
				   (squash2 (cdr tree)))))) ;; ここ
										; => SQUASH2

(squash2 '(a))							; => (A)
(squash2 '((a)))						; => (A)
(squash2 '(((a))))						; => (A)
(squash2 '(a b))						; => (A B)
(squash2 '(a (b)))						; => (A B)
```

あ、なんかいいかも！という感触が得られます。

## 複雑な試験をする

ここまでのところ単純なツリーしか与えていません。もう少し複雑なテストをします。

```common-lisp
(squash2 '(a (b (c) d) e))				; => (A B C D E)
(squash2 '(a (a (a (a b))) (((a b) b) b) b))
										; => (A A A A B A B B B B)
```
ああ。これでいいのか。。。と結果オーライなコードが出来上がります。。。

## まとめ

私の場合ものすごく単純化して、ひとつひとつ動作確認をして潰していく感じで作っています。

駄文ですが、何かの参考になれば幸いです。ありがとうございました。
ある時刻を跨ぐまでの残り時間・経過時間を取得する関数

# 背景・概要
以前、[2つの時刻の間でn時を跨いだか判定する関数](https://qiita.com/Yamara/items/a658f454984d3b60cbe4)を作りましたが、残り時間や経過時間を取得できなかったり、細かい時間を指定できなかったりして不便だったので、もっと便利な関数を作りました。
今回作った関数 **GetTimeSpanOfCrossTime** の戻り値は、跨ぐ前は正のTimeSpan、跨いだ後は負のTimeSpanになるので、以前作った関数より汎用性が高いです。

# コード

``` ある時刻を跨ぐまでの残り時間・経過時間を取得する関数.cs
/// <summary>
/// ある時刻を跨ぐまでの残り時間・経過時間を取得
/// </summary>
/// <returns>跨ぐ前は、残り時間を正の TimeSpan で返す。跨いだ後は、経過時間を負の TimeSpan で返す</returns>
public static TimeSpan GetTimeSpanOfCrossTime(DateTime beforeDateTime, DateTime afterDateTime, TimeSpan targetTimeSpan)
{
    if (beforeDateTime > afterDateTime)
    {
        Console.WriteLine("beforeTime が afterTime の時刻を上回っています。 beforeTime[" + beforeDateTime + "] afterTime[" + afterDateTime + "]");
        return default;
    }
    // 跨ぐ日時となる targetDateTime を作成
    DateTime targetDateTime = beforeDateTime.Date.AddTicks(targetTimeSpan.Ticks);
    // 既に時刻を跨いでいたら、targetDateTime に1日加算
    if (beforeDateTime.TimeOfDay >= targetTimeSpan) targetDateTime = targetDateTime.AddDays(1);
    return targetDateTime - afterDateTime;
}
```

ある時刻・日時を跨いだ際にActionを実行する関数も用意しました。

``` ある時刻・日時を跨いだ際にActionを実行する関数.cs
/// <summary>
/// ある時刻を跨いだ際にActionを実行
/// </summary>
/// <param name="invokeOnPassed">既に跨いでいる際も実行する</param>
public static async void SetActionOfCrossTime(DateTime beforeDateTime, DateTime afterDateTime, TimeSpan targetTimeSpan, Action action, bool invokeOnPassed = false)
{
    double waitSecond = GetTimeSpanOfCrossTime(beforeDateTime, afterDateTime, targetTimeSpan).TotalSeconds;
    if (waitSecond > 0)
    {
        await Task.Delay((int)waitSecond * 1000);
        action?.Invoke();
    }
    else
    {
        if (invokeOnPassed) action?.Invoke();
    }
}

/// <summary>
/// ある日時を跨いだ際にActionを実行
/// </summary>
/// <param name="invokeOnPassed">既に跨いでいる際も実行する</param>
public static async void SetActionOfCrossTime(DateTime dateTime, DateTime targetDateTime, Action action, bool invokeOnPassed = false)
{
    double waitSecond = (targetDateTime - dateTime).TotalSeconds;
    if (waitSecond > 0)
    {
        await Task.Delay((int)waitSecond * 1000);
        action?.Invoke();
    }
    else
    {
        if (invokeOnPassed) action?.Invoke();
    }
}
```
go言語のインポートについて（「Go言語でつくるインタプリタ」の1.3字句解析器のエラー対処）


## 概要

「Go言語でつくるインタプリタ」の1.3字句解析器を実行中にエラーで躓いたので備忘録
対象者は
* 解析のためにこの本を買ったけどgo言語がわからずに躓いた人
* go言語のインポート関係で躓いてる人

## 環境

win11
go 1.18
書籍に記載のあったdirenvは未使用

## エラー内容

lexer_test.goで以下のエラー。ヒントで隠れてるのでコードを以下に記載。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/728667/6b665fe0-7f50-5b48-75e9-19c83c33ade6.png)

```go
import (
	"testing"
	"monkey/token"
)
```

## 解決方法
shellで
```
#PROJECT_NAMEじゃなくてもなんでもいいかも
go mod init PROJECT_NAME(サンプルプログラム試しているルートフォルダ）
```
その後import文のmonky/tokenをプロジェクトルートを含めたパスにしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/728667/61a1392f-76d2-46ed-8a73-599343a02a3f.png)

## なんで動かなかったのか

2021年2月にgo言語はver1.16がリリースされました。
その時に環境変数であるGO111MODULEのデフォ値がautoからONになりました。
Go言語にはモジュールのインポート方法にモジュール対応モードとGOPATHモードがありまして、
* GO111MODULE=ON(モジュール対応モード)
    * go.modにかかれたものをもとにインポート
* GO111MODULE=OFF(GOPATHモード)
    * GOPATHに指定されたディレクトリをもとにインポート
* GO111MODULE=auto
    * go.modがあればONのときの挙動、なければOFFの挙動

この本の場合だとおそらくGO111MODULE=autoの挙動を想定していたのですが、アプデによって動かなくなった、ということだと思います。
（この本の初版は2018年6月のため、おそらくコードが古い）

また、go言語では相対パスではなくてプロジェクトルートフォルダ(go.modのあるディレクトリ）を基準とした絶対パスが推奨されています。

## 参考URL
GO111MODULEについて
https://text.baldanders.info/golang/manage-modules/

相対パスについて
https://teratail.com/questions/297324
https://selegee.com/7188/
alacritty + tmux で true color対応したい

# よく見かける設定例

同じような環境で使っている人の設定ファイルを見ると、下記のような設定が多く見られる

```yaml:alacritty.yml
env:
  TERM: xterm-256color
```

```conf:.tmux.conf
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-256color:RGB"
```

確かに、これでもtrue color表示できるけど、$TERMを`alacritty`に設定したい

# そもそもtrue color表示できているかの確認

下記コマンドを実行

```bash
curl -s https://gist.githubusercontent.com/lifepillar/09a44b8cf0f9397465614e622979107f/raw/24-bit-color.sh | bash
```

## true color表示できている場合

こんな感じで継ぎ目がなく表示されればtrue color表示できている
![Screen Shot 2022-04-17 at 0.58.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466880/f4164c23-7dca-6988-73e0-ae32fd8a6a80.png)

## true color表示できていない場合

対応できていない場合は、こんな感じに継ぎ目が明らかになる
![Screen Shot 2022-04-17 at 0.59.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466880/2140e490-e7c6-cbd6-04ac-a765cd43d504.png)


# 結論

下記設定でtrue color対応できる

```yaml:alacritty.yml
env:
  TERM: alacritty
```

```conf:.tmux.conf
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",alacritty:RGB"
```

# 参考

- https://gist.github.com/andersevenrud/015e61af2fd264371032763d4ed965b6
- https://github.com/alacritty/alacritty/issues/109
error while creating mount source path '~~path~~'でやったこと

### 状況
Docker-composeでコンテナを立て->down->もう一回立てる時に、
**error while creating mount source path '~somepath~'**
が出ました。
使ってるOSはwindows10 Home
![スクリーンショット 2022-04-15 183258.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327519/ed79626e-7143-6e23-87cd-a52755e3de54.png)


### 対応
WSLのUbuntu上の **/mnt/wsl/docker-desktop-bind-mounts/Linux名** 
にエラー文と同じフォルダがあったので、
それをsudoで削除
![Inkedスクリーンショット 2022-04-15 190611.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327519/b4b66abe-e1da-813d-d396-297724fa4a66.jpeg)

### ref
[Docker公式のfile sharingについて](https://matsuand.github.io/docs.docker.jp.onthefly/desktop/windows/)
M1macでMySQLインストール必勝法

## はじめに
今回は、M1macでMySQLをまだインストールしていない人も中途半端にインストールしてエラーに悩んでる人を助けられればと思い記事にしました。

```c#:コマンド
mysql -u root
```
上記の感じでMySQLのコマンドを走らせて、
```
ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)
```

これは1つのサンプルエラーですが、こんな感じのエラーを1億回ぐらい見た私でも、今回必勝法を見つけたので共有したいと思います。

ここでただサーバーを起動していないだけ問題があるかもなので、
```c#:コマンド
mysql.server start
```
上記を走らせて問題なくMySQLに接続ができたらこの記事とはおさらばしてもらって大丈夫です。

#### 作戦
今回は中途半端にインストールしてエラーに悩んでる人向けに、
アンインストールしてまっさらにしてからもう一度インストールしていきます。

なのでまだインストールすらしたことのないない人は、アンインストールした後の記事から見るといいかもです。

```c#:コマンド
which mysql
```
これをコマンドに入力してパスがでなければ入ってない可能性があります。


またこの記事は、homebrewがインストールされている前提で進めていきます。
まだの方は、[こちら。](https://brew.sh/index_ja)


## 今あるMySQLをお掃除する



```c#:コマンド
rm -rf ~/Library/PreferencePanes/My*
sudo rm /usr/local/mysql
sudo rm -rf /usr/local/mysql*
sudo rm -rf /Library/StartupItems/MySQLCOM
sudo rm -rf /Library/PreferencePanes/My*
sudo rm -rf /Library/Receipts/mysql*
sudo rm -rf /Library/Receipts/MySQL*
sudo rm -rf /private/var/db/receipts/*mysql*
sudo rm /Library/LaunchDaemons/com.oracle.oss.mysql.mysqld.plist
```

```c#:コマンド
brew uninstall mysql
```


```c#:コマンド
sudo rm -rf /usr/local/Cellar/mysql*
sudo rm -rf /usr/local/bin/mysql*
sudo rm -rf /usr/local/var/mysql*
sudo rm -rf /usr/local/etc/my.cnf
sudo rm -rf /usr/local/share/mysql*
sudo rm -rf /usr/local/opt/mysql*
sudo rm -rf /etc/my.cnf
```
これできれいサッパリ。

## あとはインストールするだけ

```c#:コマンド
brew install mysql
```

## 一応確認する

```c#:コマンド
mysql.server start
```

上記のコマンドで、
```
Starting MySQL
. SUCCESS! 
```
とでれば起動の確認成功!!


```c#:コマンド
mysql -u root
```
下記のようになれば完了です!!!
```
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.28 Homebrew

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
```
javascript 学び２

●while
 繰り返し
　while(条件式) { 繰り返す式 }

●for
 繰り返し
　for(変数;条件;計算式) { console.log }

●配列
　const animals1 = "dog";
  const animals2 = "cat" ;   → const animals ["dog","cat","sheep"];
  const animals2 = "sheep";
,で区切る
インデックス番号は０からの開始となるので注意！！

●length
要素数
　console.log(animals.length); 要素数を出力

●オブジェクト
　const item {プロパティ1：値1,プロパティ2：値1};
 item.プロパティ１　= 値; で該当するプロパティの値を変更可能
eclipseでJavaFXを利用するための環境設定手順

システム開発の会社に入社して、研修でJavaFxでGUIアプリを作るよう言われたのだが、想像以上に環境設定に詰まってしまったので、備忘録として残しておく。
※初心者なので、よくわかっていないまま設定しているところもあると思います。

使用環境
OS:windows11
eclipse:2020-12 (4.18.0)

・eclipseのマーケットプレイスで「e(fx)clipse」というプラグインをインストール

※この状態でjavaFxのライブラリをインポートしようとしてもライブラリが見つからない旨が表示される。
※Java11以降?にはjavaFxのライブラリは除外されているかららしい。
※一応JREシステムライブラリーを1.8に変えるとJavaFxが使えるようにはなるが、Java11以降のライブラリが使えなかったり、外部のライブラリとうまく連携できなかったりするので、Java11の環境でjavafxが使える方法が以下になる。

・以下のサイトよりJavaFXのSDKをダウンロード(java11以降別でSDKを用意する必要がある)
https://gluonhq.com/products/javafx/
※以降C:\pleiades\java配下にSDKをダウンロードした体で本記事記述していきます。

・環境変数に以下を設定(多分この辺は設定しなくてもいい？)
path             C:\pleiades\java\javafx-sdk-18\bin
JAVAFX_HOME      C:\pleiades\java\javafx-sdk-18\lib
CLASSPATH        C:\pleiades\java\javafx-sdk-18\lib\*

・eclipseの画面→新規→JavaFxプロジェクト選択でJavaFxのプロジェクトを作成

・moduleinfojavaというファイルが作成されていたら削除する

・JAVAFX SDKというライブラリが追加されていたら削除する

・ビルドパス画面よりjavafx-sdk-18\lib配下のjarファイルを全て追加する

・実行の構成画面よりVM引数に以下を入れる
--module-path \C;\pleiades\java\javafx-sdk-18\lib --add-modules javafx.controls,javafx.fxml
※「:」じゃなくて「;」
※--module-path "%JAVAFX_HOME%" --add-modules javafx.controlsだとうまく動作しなかった..

これでJavaFXが起動すると思います。
package is in a very bad inconsistent state; you should  reinstall it before attempting configuration

# 参照 url
https://askubuntu.com/questions/1065556/broken-python-dependencies-after-trying-to-re-install

# 症状

`sudo apt upgrade` とかするとエラーが出る。

```
dpkg: error processing package libpython3.8-minimal:amd64 (--configure):
 package is in a very bad inconsistent state; you should
 reinstall it before attempting configuration
No apport report written because the error message indicates its a followup error from a previous failure.
                                                                                                          dpkg: dependency problems prevent configuration of python3.8-minimal:
 python3.8-minimal depends on libpython3.8-minimal (= 3.8.10-0ubuntu1~20.04.4); however:
  Package libpython3.8-minimal:amd64 is not configured yet.

dpkg: error processing package python3.8-minimal (--configure):
 dependency problems - leaving unconfigured
dpkg: dependency problems prevent configuration of libpython3.8-stdlib:amd64:
 libpython3.8-stdlib:amd64 depends on libpython3.8-minimal (= 3.8.10-0ubuntu1~20.04.4); however:
  Package libpython3.8-minimal:amd64 is not configured yet.

dpkg: error processing package python3.8-dev (--configure):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 python3.8-minimal
 libpython3.8-minimal
 libpython3.8-stdlib:amd64
 python3.8-dev
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

参照 url に書いてあることを一通り試したがだめ

```
sudo dpkg --configure -a
sudo apt-get install --fix-broken
sudo apt-get purge python* && sudo apt-get autoclean && sudo apt-get install python*
sudo dpkg-reconfigure python2.7*
```

# 解決策

dpkg でパッケージを 手動で再帰的に remove していくと解決できた。
```
sudo dpkg --remove --force-remove-reinstreq --force-depends <package-name>
```

remove 対象パッケージ (上記エラーメッセージの最後)
```
 python3.8-minimal
 libpython3.8-minimal
 libpython3.8-stdlib:amd64
 python3.8-dev
```

python3.8-minimal を remove -> error
```
$ sudo dpkg --remove --force-remove-reinstreq python3.8-minimal
dpkg: dependency problems prevent removal of python3.8-minimal:
 python3.8 depends on python3.8-minimal (= 3.8.10-0ubuntu1~20.04.4).
 python3-minimal depends on python3.8-minimal (>= 3.8.2-1~).

dpkg: error processing package python3.8-minimal (--remove):
 dependency problems - not removing
Errors were encountered while processing:
 python3.8-minimal
```

python3.8 と python3-minimal が depends on python3.8-minimal -> remove
```
$ sudo dpkg --remove --force-remove-reinstreq python3.8
$ sudo dpkg --remove --force-remove-reinstreq python3-minimal
```

これを繰り返していく

remove 対象の4つのパッケージすべてが remove できたら apt upgrade できた
bashのC-tが効かない (bash_execute_unix_command: cannot find keymap for command)

# やりたいこと
プロンプトで C-t を押すと本来は文字を入れ替えるが、エラーが出てできない

```
$ ab|c
bash: bash_execute_unix_command: cannot find keymap for command
```

`|` がカーソルだとすると、C-t を入力すると通常は `ac|b` となる

# 原因

readline の transpose-chars が not bound になっている

```
$ bind -p | grep transpose-chars
# transpose-chars (not bound)
```

fzf が悪さをしているようだ

```
$ bind -X
"\C-r": "__fzf_history__"
"\C-t": "fzf-file-widget"
```

# 解決策

~/.bashrc の ~/.fzf.bash を source した後に bind で上書き

```
# ~/.bashrc

[ -f ~/.fzf.bash ] && source ~/.fzf.bash
bind '"\C-t": transpose-chars'
```

# 余談
- C-t にはいかなる shell command も受け付けてくれない (おま環かも)
```
# bash: bash_execute_unix_command: cannot find keymap for command となる
bind -x '"\C-t": date'
```

- C-q には普通に shell command が割り当たる
```
bind -x '"\C-q": date'            # ok
bind -x '"\C-q": fzf-file-widget' # ok
```

- ~/.inputrc よりも ~/.bashrc の設定のほうが優先度が高いので、~/.inputrc に書いても解決できない
```
# ~/.inputrc
"\C-t": transpose-chars # これでは解決できない
```
Swift Errorの使い方 エラーハンドリング

# エラーハンドリング、Errorの使い方

## 概要

[Error](https://developer.apple.com/documentation/swift/error)のクラスの使い道を考えてみた。

***結論***

下記のような`extension`を作成します。

```Swift

import Foundation

extension Error {
    var domain: String {
        (self as NSError).domain
    }

    var code: Int {
        (self as NSError).code
    }

    var info: [String: String] {
        guard let userInfo = (self as NSError).userInfo as? [String: String] else { return [:] }
        return userInfo
    }
}

```

エラー発生時は下記のようにします。

定数
```Swift
import Foundation

enum AppConstant {
    static let LocalizedSuggestion = "LocalizedSuggestion"
}
```

下記のようにします。

```Swift
completion(.failure(NSError(domain: "Server Error",
                                                code: -10001,
                                                userInfo: [AppConstant.LocalizedSuggestion: "Http response header invalid status code: \(response.statusCode)"])))
```

それを呼ぶときは下記のようにします。

```Swift
        api.session { error in
            DispatchQueue.main.async {
                self.alert(title: error.domain,
                           message: error.info[AppConstant.LocalizedSuggestion])
                print(error)
            }
        }
```

こうすることにより、`Error`クラスを有意義に活用できます。
これまで様々な人のエラーハンドリング時の文言などをみてきましたが、大体は`String`クラスを用いるだとか、`struct`を用いるだとか、`error.localizedDescription`を用いるだとかが多いですが、

今回のこの方法が良いのでは無いかと思うわけであります。

[Gihub gist Error+](https://gist.github.com/keisukeYamagishi/e306f652abbedbd9e548cab4130372ee)
IBM Cloud認定資格のまとめ（2022年6月版）

# IBM Cloud認定資格

クラウド系の認定資格としてはAWSやAzureのものが有名ですが、IBM Cloudにも同様に認定資格があります。先日全て（2022年4月時点）の資格取得に成功したので、改めて、IBM Cloudの資格を整理します。

## ロール別Associateレベル

最も基本となる資格です。SREとAdvocate系があり、Advocate系はエンジニア向けのTechnical Advocateと全職種向けのAdvocateがあります。SREはとても難しく、Technical AdvocateとAdvocateは易しめでした。

資格名|試験名|受験体験記
---|---|---
IBM Certified Associate SRE - Cloud v1|IBM Cloud Associate SRE v1|https://qiita.com/teruq/items/c01fa06c7c9e535ba8d3
IBM Certified Technical Advocate - Cloud v3|IBM Cloud Technical Advocate v3|https://qiita.com/teruq/items/c1086dd52bd427aec224
IBM Certified Advocate - Cloud v1|IBM Cloud Advocate v1|https://qiita.com/teruq/items/1bb67c516dd73c7a1ef8
IBM Certified Advocate - Cloud v2 (2022/5-)|IBM Cloud Advocate v2|https://qiita.com/teruq/items/b6e80c6ff6dfa4ba9586

## ロール別Professionalレベル

中級レベルの資格です。SRE、Developer、Architect、Sales Engineerと細分化しています。SREとSales Engineerは易しめ、DeveloperとArchitectは難しめでした。

資格名|試験名|受験体験記
---|---|---
IBM Certified Professional SRE- Cloud v2|IBM Cloud Professional SRE v2|https://qiita.com/teruq/items/4bcc0ae8365c721267cd
IBM Certified Professional Developer - Cloud v5|IBM Cloud Professional Developer v5|https://qiita.com/teruq/items/f9ffed4f98691a82c531
IBM Certified Professional Architect - Cloud v5|IBM Cloud Professional Architect v5|https://qiita.com/teruq/items/54c66a3f02cdad7faab6
IBM Certified Professional Sales Engineer - Cloud v1|IBM Cloud Professional Sales Engineer v1|体験記作成を失念

## ロール別Advancedレベル

上級レベルの資格です。現在はArchitectしかありません。今後その他のロールも追加されていくようです。

資格名|試験名|受験体験記
---|---|---
IBM Certified Advanced Architect - Cloud v1|IBM Cloud Advanced Architect v1|https://qiita.com/teruq/items/c18e6b915cecc9b3d679

## Specialty試験

ロール別レベル別ではなく、特定サービスや技術への特化資格もあります。こちらは試験名と認定名が同一なのでわかりやすいです。

資格名/試験名|受験体験記
---|---
IBM Cloud for Financial Services v1 Specialty|https://qiita.com/teruq/items/e80afffa7b523ee5a29b
IBM Cloud Security Engineer v1 Specialty|https://qiita.com/teruq/items/8e6631f883570376406a
IBM Cloud Satellite v1 Specialty|https://qiita.com/teruq/items/1fb6abd86f0772fb4210
IBM Cloud DevSecOps v1 Specialty|https://qiita.com/teruq/items/b8ff63ba31711ff0e5ea

# オンライントレーニング

IBM社外の方は下記サイトがポータルとなっています。資格別のオンライントレーニングもありますので、ご利用ください。無料です。

https://ibm.com/training/cloud

# 試験対策サイト

2022年6月に試験対策に特化したサイトが公開されました。時間のない方はこのサイトだけでも合格が狙えるかもしれません。

https://qiita.com/teruq/items/e99a231911836e039dae
【C/C++】dockerでncurses.hを使う

# はじめに
docker上でncurses.hを使うための最低限の環境を構築します。
[ローグライクゲーム](https://github.com/Aruminium/TMToB)を作成したときにもこの環境で動作しました。

[【C言語】ncursesでローグライクゲームづくり](https://qiita.com/Bana7/items/780aedc4f3625baba12a)も併せてどうぞ

# ncurses.hとは何なのか
ずばりC言語でより高度な画面制御ができるヘッダファイルです。
また、いちいち[Enter]Keyを押す必要をなくすことができたりと、C言語でCLIゲームを作るならば是非おすすめしたい。

# なぜdockerを使うのか
結論を言うと環境差があるからです。

ncursesは別途インストールする必要があります。
macだと ``` brew install ncurses ```ですみますが、それ以外だと少し面倒です。

また、ゲーム等を制作し、他の人に遊んでもらう場合において
上記のような環境差によって予期せぬエラーやそもそもの心理的ハードルが高いことから、ゲームを遊んでもらうことはないでしょう。

そこでdockerによって環境を統一することによってユーザにはコンテナを作ってもらう。ただそれだけに注力させ、エラーなど考える必要をなくすことができます。

# 環境構成

OS : CentOS 7

installするもの

* vim
* make
* ncurses-devel
* Development Tools

今回使用するコンテナは一つですが、Docker composeで環境つくります。

### 1. vim

テキストエディタの一つです。
動作がはやいのでよく使ってます。

### 2. make

通常コンパイルするときは
```
cc hogehoge.c
```
としますが、


別途Makefileを記述すれば
```
make
```
でコンパイルできます。

### 3. ncurses-devel

今回の目玉です。これでncurses.hが使えます。

### 4. Development Tools
色々セットです。
gccやgitなどがインストールされます。

# 手順

## 1. 前準備

Dockerを使うためには「Docker for windows」や「Docker for mac」が必要になります。

ここでのインストールの説明は省略します。

## 2. ディレクトリ構成

C-gameというディレクトリを作成しそれを基準にして考えます。

```
C-game/
   ├ src/
   │   ├ Makefile
   │   └ main.c
   ├ Dockerfile
   └ docker-compose.yml
```

## 3. 各ファイルに記述

### Dockerfile

```
FROM centos:7

WORKDIR /root

RUN yum -y update && \
        yum -y groupinstall "Development Tools" && \
        yum install -y vim make ncurses-devel

COPY src /root/
```

``` COPY src /root/ ```
でC-game/src/がコンテナのroot/にコピーされます
ここでいうと、Makefileとmain.cがコピーされます

### docker-compose.yml

```
version: "3.8"
services:
 cdev:
  build:
   context: .
   dockerfile: Dockerfile
  image: cdev
  container_name: cdev
  volumes:
   - type: bind
     source: .
     target: /cdev
  stdin_open: true
  tty: true
  working_dir: /cdev/src/
```

### Makefile

```
hoge: main.c
        gcc -std=c99 -o hoge main.c -lncurses
```

-std=c99を忘れずに記述しましょう

## 3. 実行

``` docker-compose.yml ```がディレクトリに移動します。


ビルドします。(docker imageが作成されます)

```
docker-compose build
```

``` docker-compose ```でエラーが発生する場合は``` docker compose ```と打ち込んでください。

```
docker-compose up -d
```

コンテナが起動します。

```
docker exec -it cdev bash
```

でコンテナにアクセスできます。
そのコンテナ内で

```
make
```

```
cd ./hoge
```

で無事実行することができます。