OmniAICreator/Qiita-1.07M huggingface dataset:
Laravelでシンプルかつ最強なAPIを作る設計パターン - QueryControlModel

今回は私が実務でも利用しているLaravelを用いたAPI量産パターンの中で中核を担う QueryControlModel を利用したデザインパターンを紹介します。
もうこれ無しではやりにくくて困ってしまうくらいには便利な拡張になってます。

サンプルリポジトリ：[madakaheri/sample-laravel-qc](https://github.com/madakaheri/sample-laravel-qc)

## Laravel + QueryControlModelを用いたシンプルで強力なAPI

実際に実務で利用しており、GraphQLよりも柔軟で強力なAPIを実現しています。  
シンプルなCRUDを実装した後は、PolicyやRequestバリデーションを設定するだけでOK。

## カスタム QueryControlModel トレイト
App\Models\Traitsに[QueryControlModel](https://github.com/madakaheri/sample-laravel-qc/blob/main/app/Models/Traits/QueryControlModel.php)を作成し、各モデルに継承させRequestのクエリストリングスから自由に検索、リレーションデータの追加、ページネーションをコントロールできるよう拡張しています。

```
namespace App\Models\Traits;

trait QueryControlModel
{
    /**
     * Append datas
     */
    public function scopeQueryControl($query)
    {
        return $query
        ->when(request()->query('select'), function ($query, $csv) {
            return $query->select(explode(',', $csv));
        })
        ->when(request()->query('with'), function ($query, $csv) {
            return $query->with(explode(',', $csv));
        })
        ->when(request()->query('withCount'), function ($query, $csv) {
            return $query->withCount(explode(',', $csv));
        });
    }

    /**
     * Please Override in Model
     */
    public function scopeQueryFilter($query)
    {
        return $query;
        // ex)
        // ->when(request()->query('user'), function ($query, $csv) {
        //     return $query->whereIn('user_id', explode(',', $csv));
        // })
    }

    /**
     * count(), paginate() and get() supported.
     */
    public function scopeQueryGet($query)
    {
        $count = request()->query('count', false);
        $paginate = request()->query('paginate', false);

        if ($count) {
            return $query->count();
        }
        if ($paginate) {
            return $query->paginate((int) $paginate);
        }
        return $query->get();
    }
}
```

QueryControlModelはRequestクエリにのみ反応するローカルスコープとして実装していますので、tinkerやバッチ処理の邪魔はしないようになっています。  
scopeQueryControl($query)は[各モデルでオーバーライド](https://github.com/madakaheri/sample-laravel-qc/blob/main/app/Models/Post.php)して使用します。  


## コントローラーメソッドでの利用
indexやshowメソッドから呼び出して使用します。  

UserControllerの例
```
namespace App\Http\Controllers;

use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Models\User;

class UserController extends Controller
{
    public function index()
    {
        return User
        ::queryControl()// <-- withやwithCountのデータ追加
        ->queryFilter()//  <-- 各モデルのクエリフィルター
        ->queryGet();//    <-- count() / paginate(Int) / get() に対応
    }

    public function show($id)// <-- インジェクションせず $id として取り出します
    {
        return User
        ::queryControl()// <-- withやwithCountのデータ追加
        ->queryFilter()//  <-- 各モデルのクエリフィルター
        ->findOrFail($id);
    }
}
```
2022/7/3主にITとかセキュリティの記事

セキュリティ管理者を悩ませる「脆弱性まつり」がもっと深刻になる理由(7/1)
https://japan.zdnet.com/article/35189631/

2022年第1三半期版「セキュリティ脅威レポート」を公開　ウクライナ侵攻で不 正メールが急増(6/30)
https://ovo.kyodo.co.jp/ch/mame/a-1778765

ネットワークカメラの不正アクセス防止対策について(6/30)
https://canon.jp/corporate/caution/180426

Amazon、「Amazon Photos」アプリの脆弱性修正 - 悪用により不正アクセスが可能に(7/1)
https://news.mynavi.jp/techplus/article/20220701-2385349/

unrarに脆弱性、アップデートを(7/1)
https://news.mynavi.jp/techplus/article/20220701-2385010/

中国へ、米国へ…流出する頭脳、資金力なく見放される日本(7/1)
https://business.nikkei.com/atcl/gen/19/00478/062900004/

[FT]国に欺かれ、サイバー攻撃に手を染める中国の大学生(7/1)
https://www.nikkei.com/article/DGXZQOCB010KZ0R00C22A7000000/

訴訟を有利に進めるために弁護士や裁判の当事者にハッキングを仕掛ける「傭われハッカー」の実態とは？(7/1)
https://article.auone.jp/detail/1/3/7/48_7_r_20220701_1656652782577379

サイバー犯罪グループがAMDの機密情報を窃取したと主張、AMDは調査開始(6/30)
https://news.mynavi.jp/techplus/article/20220630-2384403/

NTTデータ、神奈川など自治体向け受託業務で情報漏洩(7/1)
https://www.nikkei.com/article/DGXZQOUC016GM0R00C22A7000000/

5月のネット詐欺、クレカを騙るフィッシング詐欺が急増…新成人狙いも(7/1)
https://www.tsuhannews.jp/shopblogs/detail/69190

電気通信事業者を標的とした「DecisiveArchitect」アクティビティクラスタをCrowdStrikeが解説(7/1)
https://scan.netsecurity.ne.jp/article/2022/07/01/47827.html

NFTマーケットプレイスのOpenSea、ユーザーのメアドが流出(7/1)
https://japan.cnet.com/article/35189783/

コストコ40周年に乗じたフィッシング詐欺に注意(7/1)
https://news.mynavi.jp/techplus/article/20220701-2385133/

海賊もサイバーの時代、コンテナ船をハッキングしてスエズ運河座礁事故クラスの損害を引き起こす可能性も(7/1)
https://gigazine.net/news/20220701-cyber-pirate/

「外国による選挙介入」　米が情報提供に報奨金　最高13億円超(7/1)
https://mainichi.jp/articles/20220701/k00/00m/030/166000c

公安調査庁「国際テロリズム要覧2022」、テロ組織の暗号資産活用や重要インフラへのサイバー攻撃 ほか(7/1)
https://scan.netsecurity.ne.jp/article/2022/07/01/47826.html

現物商品とデジタルを融合させたNFTマーケットプレイス 『APREX(アプレエックス)』 2022年6月30日(木)にローンチ(β版)(6/30)
https://www.atpress.ne.jp/news/316427

楽天モバイルのキャリアメール、7月1日から提供　名前は「楽メール」(7/1)
https://www.itmedia.co.jp/mobile/articles/2207/01/news060.html

サイバー人材不足が深刻　ゲーム「デバッガー」も要員に(7/1)
https://www.nikkei.com/article/DGXZQOUC053DW0V00C22A6000000/

立川市役所の通信システム障害、4日経っても影響続く(7/1)
https://www.itmedia.co.jp/news/articles/2207/01/news095.html

自治体の業務で情報漏えい NTTデータ関西(7/1)
https://nordot.app/915564775437778944?c=39546741839462401

県が委託する業者のPCがウイルスに感染　２３１１件の個人情報流出【新潟】(7/1)
https://news.goo.ne.jp/article/nsttv/region/nsttv-10844.html

CMSベンダーに独禁法違反の疑い　「独自の方がセキュリティ対策になる」と自治体に営業、他社参入を阻害(6/30)
https://www.itmedia.co.jp/news/articles/2206/30/news214.html

またUSB紛失　患者の個人情報入り、杏林大病院　院外持ち出し禁止のはずが(7/1)
https://www.itmedia.co.jp/news/articles/2207/01/news116.html

位置共有のゼンリー幹部「自分の居場所がコンテンツ」 テックの未来(7/1)
https://www.nikkei.com/article/DGXZQOUC1154K0R10C22A5000000/

ハーモニーの1億ドル流出のハッキング事件、北朝鮮のハッカー集団が関与か＝分析会社指摘(7/1)
https://jp.cointelegraph.com/news/infamous-north-korean-hacker-group-identified-as-suspect-for-100m-harmony-attack

大手仮想通貨取引所のCoinbaseが位置情報データを法執行機関に販売していると報じられる(7/1)
https://article.auone.jp/detail/1/3/7/48_7_r_20220701_1656644573324100
DockerでNginxのリバプロを作ったときの備忘録

Dockerは関係ないかもしれないが、リバプロを介したWordPressで1MB以上の画像がアップロードできない問題が発生した場合の対策

リバースプロキシの設定ファイルに

```
client_max_body_size 1024M;
```

のように、ある程度大きいサイズを書いておこう。
CKA受験記(2022年6月25日の試験環境変更後)

# TL;DR
* Kubernetesの認定試験"Certified Kubernetes Administrator"(以下CKA)の試験環境が2022年6月25日に変更された(CKADとCKSも対象)
* 2022年7月1日に改定後の試験環境でCKAを受験した
* 環境変更のフォローと新環境で受験する際のアドバイスを少しだけ
![IMG_7236.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429161/ad4d3ece-3024-7a99-0385-7e17122fb476.jpeg)

※ お断り
本記事は2022年7月1日時点の情報です。最新の試験情報はFAQやCandidate handbookを参照してください。
また、従来の試験環境での試験経験がないため、従来の試験方式の情報はネットに転がっている参考情報をもとに記載しています。(誤っていたら優しくご指摘ください)
なお、本記事に記載した内容で生じた不利益に対して、責任は負いかねます。あくまで参考情報としてお読みください。

# 試験環境の変更

従来の受験システムからPSI Bridgeでの受験形式に変更された。
参考のリンク先に記載の通りだが、主な変更点は以下の４つ。

> 1. 画面共有が不要になった
> 2. プロテクター(試験監督)を待たずに試験のチェックインが可能になった
> 3. モニターは1枚だけ使用できる
> 4. chromeの代わりにPSIセキュアブラウザを使用する

## 1. 画面共有が不要になった
従来の試験では、試験画面(＋ターミナル)とローカルのブラウザ(chrome)を使って試験を実施していた
改定後の試験では、受験システム(PSIセキュアブラウザ)内に試験画面とブラウザ(Linux版FireFox)が含まれるため、PC画面の共有が不要になった

## 2. プロテクター(試験監督)を待たずに試験のチェックインが可能になった
試験開始時刻の30分前から受験システム(PSIセキュアブラウザ)のインストールが可能となり、チェックインを実施できる。
チェックインではID(パスポートや運転免許証)の確認や、部屋や机、身に着けているアクセサリーの確認を行う。

## 3. モニターは1枚だけ利用できる
従来の試験では、モニターは2枚まで利用が認められていた。
改定後の試験では、モニターの枚数は1枚に制限された。

## 4. chromeの代わりにPSIセキュアブラウザを使用する
従来の試験では、ローカルのブラウザ(chrome)を利用して、許可されたリソースを参照できた。
改定後の試験では、受験システム(PSIセキュアブラウザ)内のブラウザを利用する方式に変更になった。

# この改定で改善されたと感じた点
### 自分のchromeにたくさんお気に入りを入れる必要がなくなった
従来の試験では、アクセスしそうなリソースを事前にchromeのお気に入り登録する必要があった
改定後の試験では、設問ごとに必要になりそうなリソースのリンクを提示してくれるため、事前のお気に入り登録が不要になった
従来の試験では、各リソースについて記載があるページの勘所をつける必要があった気がするが、改定後の試験では設問ごとにリンクの提示があるので、少し試験のハードルが低くなったのではと推察します

### ターミナルを複数起動できるようになった
従来の試験では、ターミナルは１つのみ、複数使用したい場合はtmuxなどで仮想的に分割する必要があった
改定後の試験では、試験環境内(Linux)のターミナルアプリを複数起動可能となった
> ただ、今まで1面で慣れていたため、結局ターミナルアプリの複数起動をしなかった...

## この改定後にイマイチと感じた点
### Linux内ブラウザのレスポンスが遅かった
試験環境内のブラウザが非常に遅く、スクロールが2テンポ位遅れてくるので、正直使い物にならなかった
コンソールのレスポンスは問題なかったため、マニュフェストの記載で迷うところはできるだけkubectl explainで参照することでクリンチした
> kubectl explainだと情報が出てこない問題は非常に大変だった...

### 画面録画が不要となっているが、Macでは"画面収録の許可"設定が必要だった
MacでPSIセキュアブラウザを起動したとき、「セキュリティとプライバシー」環境設定の画面が出てきた
画面共有が不要と聞いていたのと、いろいろあって焦っていたため、"record this computer's screen"のためにプライバシーの許可設定が出ていることに気付かず、しばらくカメラやマイクの許可設定をいじっていた...

### コピペのキーバインドがkiller.shと違う
試験対策のkiller.shとコピペのショートカットキーが違い、やや違和感があった。
ただ、試験中に段々慣れてくるのと、今後killer.sh側も更新予定なので、そのうち事前に慣れるようになると思われる

| 　| 　コピー| ペースト |
|:--:|:--:|:--:|
|従来の試験方式|Ctrl-Insert (cmd + C )|Shift + Insert (cmd + v )|
|改定後の試験|Shift + Ctrl + C|Shift + Ctrl + V|

※()内はMacでのショートカットキー

## P.S. 個人的失敗：Webカメラのオートフォーカスが無効にできずチェックイン不可
試験端末(windows)にしていたPCにつけていたWebカメラが古いものだったため、オートフォーカスが無効にできず、ID確認に失敗しまくりました...
CKA-JPでしたが技術サポートからは英語でチャットが来て困惑しましたが、技術サポートと試験監督とやり取りを進めると別のデバイスで試してみることを勧められる。
⇒ 家にあるMacbookで試験ポータルにアクセスするも、すでに試験時間を過ぎており"take exam"(PSIセキュアブラウザのインストールリンク)が非表示...
結局、一度windows端末のPSIセキュアブラウザを終了し、ブラウザ履歴を漁って何とかリンクを見つけ出しMacbookでインストール、その後無事試験を開始できました(上記Macのプライバシー設定もあり、開始時間を１時間半ほど過ぎての試験開始になりました...)
> Webカメラの性能に不安がある方は、事前にID(身分証)だけをフレームに収めて氏名などの情報が識別できるか確認しておくといいかもしれません


# 最後に

CKA面白い試験だったので、K8sやってる人もやってないけど興味がある人も、ぜひ受けてみてください！

## 参考

https://training.linuxfoundation.org/blog/update-on-certification-exam-proctoring-migration/
【Flask】sitemap.xmlの設置と設定

```:ディレクトリ構成
/
 ├ static/
 ├ templates/
 └ app.py
```

## 手順
### 1. `static/` に `sitemap.xml` を設置
以下のサイトでサイトマップを作成できる。

http://www.sitemapxml.jp/


### 2. サイトマップの設定

```py:app.py
from flask import Flask, render_template
app = Flask(__name__)

@app.route("/sitemap.xml")
def sitemap():
    return app.send_static_file("sitemap.xml")
```

## 参考
https://aiueos.blog.jp/archives/30124444.html?ref=foot_btn_prev&id=7786201
[Swift5] TableViewCell 別のStoryBoardに遷移する方法

## イメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1678932/2adba8ce-684a-3dc2-ccd8-eeaa045d7553.gif" width="300">

## 手順
①TableViewCellのIdentifierを設定する(名前はなんでもOK)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1678932/1c79ac8a-f86d-ee82-73f9-3d3b1c55c3e8.png" width="200">

②遷移先StoryBoardのStoryBoardIDを設定する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1678932/1297d64f-5ddd-1e2e-dcb8-b36306496268.png" width="200">
後述の `withIdentifier: ""` に入る箇所である。

③遷移元ControllerのDelegateに以下を記載する。
・遷移先StoryBoardの取得
・遷移先StoryBoardのStoryBoardIDを記載
・pushViewControllerで遷移処理を記載
```Swift
extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // 遷移先のStoryBoardを取得（"Sub"はSub.storyboardのSub)
        let SubStoryBoard:UIStoryboard = UIStoryboard(name: "Sub", bundle: nil)
        switch indexPath.row {
        case 0:
            // widthIdentifierには遷移先StoryBoardに設定したStoryBoardIDを記載する
            let targetViewController = SubStoryBoard.instantiateViewController(withIdentifier: "sub")
            // navigationControllerを設定していないと遷移しないので注意
            self.navigationController?.pushViewController(targetViewController, animated: true)
        default:
            break
        }
    }
}
```

## 全体
### ViewController(遷移元)
```Swift
import UIKit

struct tableData {
    var id: Int
    var name: String
}

private let tableList: [tableData] = [
    tableData.init(id: 1, name: "テストA"),
    tableData.init(id: 2, name: "テストB"),
    tableData.init(id: 3, name: "テストC")
]

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableList.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = tableList[indexPath.row].name
        return cell
    }
}

extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let SubStoryBoard:UIStoryboard = UIStoryboard(name: "Sub", bundle: nil)
        switch indexPath.row {
        case 0:
            let targetViewController = SubStoryBoard.instantiateViewController(withIdentifier: "sub")
            self.navigationController?.pushViewController(targetViewController, animated: true)
        default:
            break
        }
    }
}
```

## 参考にさせていただいた記事
https://qiita.com/Simmon/items/6c3d6bcd6bfffbfd970d
AtCoder ABC258 A-C (Python)

### はじめに
- python初心者+Atcoder初心者です。解いた(+解説集等を参考に学習した)問題を投稿させていただきます。
- アドバイス等あれば、是非お願いいたします。

[AtCoder Biginner Contest 258問題リンク](https://atcoder.jp/contests/abc258/tasks)
### A - When?
問題文は[こちら](https://atcoder.jp/contests/abc258/tasks/abc258_a)
- Kの値を60で割った商と余りを使用する。
```python
K = int(input())
mod = K % 60
q = K //60
H = 21 + q
if mod < 10:
  M ="0%s"%mod
else:
  M ="%s"%mod
print("%s:%s"%(H,M))
```
### B - Number Box 
問題文は[こちら](https://atcoder.jp/contests/abc258/tasks/abc258_b)
- 出発点及び移動したマスを全探索。
- マス目の上下左右がつながっていることに関しては、Nの余りを取ることで考える。
```python
#標準入力
N = int(input())
arr = [list(map(int,input())) for x in range(N)]
#探索時のベクトル
p = [1,1,1,0,0,-1,-1,-1] #左右の探索
q = [1,0,-1,1,-1,1,0,-1] #上下の探索

ans =0
for i in range(N):
    for j in range(N):
        for k in range(len(p)):
            now = 0
            #初期位置
            x = i
            y = j
            for l in range(N):
                now*=10
                now+=arr[x][y]
                x+=p[k]
                y+=q[k]
                x%=N #左右端移動時の対策
                y%=N #上下端移動時の対策
            ans = max(ans,now)
print(ans)
```

### C - Rotation
問題は[こちら](https://atcoder.jp/contests/abc258/tasks/abc258_c)
- 「S の末尾の文字を削除し、先頭に挿入する」という操作を実施した回数だけを考える。(愚直に計算した場合、実行制限時間に間に合わない。)
- 上記の操作をP回した後の文字列のi番目の文字は、操作する前の文字列の$(i-P)\mod N$番目の文字

例)
文字列：abcdefg (7文字)
3回操作した後の文字列の5番目の文字を考える。
下記の計算より、操作前文字列の2番目の文字であるとわかる。

> $\begin{align}
   \underset{文字列の順番(操作後)}{\underline{(5}}-
   \underset{操作回数}{\underline{3}}\quad)
   \mod 
   \underset{文字列の長さ}{\underline{7}}=
   \underset{文字列の順番(操作前)}{\underline{2}}
\end{align}$

<center>

|操作回数|文字列|
|---|---|
|0|a**b**cdefg|
|1|gabcdef|
|2|fgabcde|
|3|efga**b**cd|
</center>

```python
N,Q = map(int,input().split())
S = str(input())
arr = [list(map(int,input().split())) for x in range(Q)]
 
P =0
for i in range(len(arr)):
    if arr[i][0] == 1:
        P+= arr[i][1]
    else:
        num = (arr[i][1] -  P) % N -1
        print(S[num])
```
好奇心でスーパーマリオ1-1をクリアする

[強化学習でスーパーマリオをクリアする話](https://qiita.com/hrs1985/items/d249bf5d41078ded60c2)の続きです。読んでいない方は先にそちらを読んでおいた方がいいかもしれません。

![rl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134222/19d6778d-247f-2565-7f88-f3a83cafa161.png)
1. エージェントは環境から時刻$t$の状態$s_{t}$と報酬$r_{t}$を受け取る
1. エージェントは$s_{t}$に応じた行動$a_{t}$を環境に渡す
1. 環境は$a_{t}$を用いて時刻を1ステップ分進めて時刻$t+1$の状態$s_{t+1}$と報酬$r_{t+1}$を得る
1. エージェントは環境から$s_{t+1}, r_{t+1}$を受け取る
1. 1に戻る


強化学習では以上のような手順を繰り返すことで得られる報酬$r_{t}$の総和（の期待値）を最大化する方策を得ることを目的とします。報酬は学習のための重要なシグナルであり、報酬が全く手に入らない条件では学習は進みません。また、そこまで極端でなくとも稀にしか報酬が得られない（ほとんどの時刻で$r_{t}=0$となる）ような条件では学習が難しくなります。

前回はマリオが右に進むごとに報酬を与えるようにしたためエージェントは頻繁に報酬を受けとることができ、比較的短い学習量でゴールできました。これをマリオがゴールできた場合のみに与えるようにすると同じ量の学習を行っても上手くクリアできません。

# 好奇心
環境からの報酬が与えられない場合の代理の報酬として、まだ訪れたことのない状態に訪れることができたなら報酬を与えることを考えます。つまり、新しい状態に対する好奇心の強さに報酬を与えることで探索を促します。

状態の目新しさを評価するためのネットワークを用意してそこからの出力を報酬として扱う手法として[Intrinsic Curiosity Module](https://pathak22.github.io/noreward-rl/)が提案されています。

# Intrinsic Curiosity Module (ICM)

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134222/dde11aeb-4e54-20b1-f6d2-6018c63d1616.png)

ICMは3つのモジュールからなっています。

Features：状態$s_{t}$から特徴$\phi(s_{t})$を抽出する
Forward Model：ある時刻の特徴$\phi(s_{t})$と行動$a_{t}$から次の時刻$t+1$の状態の特徴$\hat{\phi}(s_{t+1})$を予測する
Inverse Model：ある時刻の特徴$\phi(s_{t})$と次の時刻の特徴$\phi(s_{t+1})$からその間で取られた行動$\hat{a}_{t}$を予測する

## ICMの学習
ICMは以下の2つの損失の和を最小化するように学習します。
$\mathcal{L}\_{forward} = || \phi(s\_{t+1}) - \hat{\phi}(s\_{t+1})||\_2 $
$\mathcal{L}\_{inverse} = - \sum a\_{t} \log \hat{a\_t}$ (cross entropy誤差)

## ICMによる報酬
$r\_t^i = || \phi(s\_{t+1}) - \hat{\phi}(s\_{t+1})||\_2$を報酬とします。

# 実験
スーパーマリオブラザーズ1-1で**環境からの報酬を全く与えずに**学習を行いました。
評価時には右に移動すると報酬が与えられる環境を用いました。
PPOとPPOにICMを組み合わせたもので報酬和の中央値を比較しています。
ICMありの方が報酬和が大きくなっていることがわかります。
ただし、ステージをクリアできる割合についてはPPO+ICMで(2/128)程度になりました（PPOでは(0/128）なのでICMによって改善はしていそうです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134222/3d2cfb0e-6faa-241e-aabd-5312f2393ff6.png)
tarコマンドの使い方

## アーカイブの作成
```:ターミナル
$  tar cvf アーカイブ名 対象ファイル1 対象ファイル2　...
```
```:ターミナル
$ tar cvf sample.tar test_1.txt test_2.txt
```

## アーカイブの展開
```:ターミナル
$  tar xvf アーカイブ名 対象ファイル1 対象ファイル2　...
```

```:ターミナル
$ tar xvf sample.tar
```

## 圧縮したアーカイブの作成
```:ターミナル
$  tar cvzf アーカイブ名 対象ファイル1 対象ファイル2　...
```

```:ターミナル
$ tar tar cvzf sample.tar.gz test_1.txt test_2.txt
```

## 圧縮したアーカイブの解凍及び展開
```:ターミナル
$  tar xvzf アーカイブ名 対象ファイル1 対象ファイル2　...
```

```:ターミナル
$ tar tar xvzf sample.tar.gz
```

## オプション
| オプション | 説明 |
|:-:|:-|
| c | アーカイブを新規作成 |
| x | アーカイブを展開 |
| v | 実行時に詳細を表示 |
| z | 圧縮処理を行う  |
| f | アーカイブファイルを指定 |
| t | アーカイブファイルの一覧を表示  |
windowsでDocker開発はまだ使い物にならない

ホスト側のファイル・フォルダをバインドする時、windowsだと強制的にrootになるのがツラすぎる。
バリバリ開発してる人、どうやってるか教えて下さいませ

再現用のファイル一式は以下の通り。windows10で、WSLではなくwindows側のフォルダに設置する。
```
//.env
COMPOSE_PROJECT_NAME=docker-file-volume-test

//docker-compose.yml
services:
  node-sys-container:
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - type: bind
        source: ./
        target: /app/bind

//Dockerfile
FROM node:18.4.0-alpine3.15
USER node
WORKDIR /app
RUN touch /app/touch-file
CMD ["node","/app/bind/index.js"]

//index.js
(async()=>{
  let counter = 1;
  while(true){
    console.log(`loop ${counter++}`);
    await new Promise(resolve => { setTimeout(() => { resolve() }, 1 * 1000) });
  }
})();

//package.json
{
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  }
}
```

上記ファイルを設置したフォルダで以下のコマンドを実行
`docker compose down && docker compose up -d --build && docker compose exec node-sys-container sh`

以下の様に、Dockerfileの中で作られたフォルダやファイルはnodeユーザーになっているが、docker-compose側でbindしたフォルダはroot権限になっている
```
/app $ ls -lav
total 8
drwxr-xr-x    1 node     node          4096 Jul  2 15:28 .
drwxr-xr-x    1 root     root          4096 Jul  2 15:28 ..
drwxrwxrwx    1 root     root          4096 Jul  2 15:06 bind
-rw-r--r--    1 node     node             0 Jul  2 15:23 touch-file
```

node.jsの場合、nodeのプロセスは非rootユーザー(node という名前のユーザー) で実行するべきとされている。
https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#non-root-user

bindしたファイル・フォルダはrootユーザー、nodeプロセスは非rootユーザーなのでどうにもならない。

解決策としては

1. nodeプロセスをrootユーザーで動かす。nodeを非rootで動かすのは「最小特権の原則」の為とされているからなのでrootで動かすのもアリのはず。
    - nodeプロセスをrootで動かした時のトラブル解決が面倒になる？「ずっとrootでやってるけど別に困らない」という情報があれば安心出来るが…
2. ファイル一式をwindows側ではなくWSL内のパスに設置する。これならlinux/macでUID GIDを一致させる数々のテクニックが使える。
    -. 現実的にはこれが最適解なんだろうが、UID GIDの沼に浸かる必要があるのか…
3. docker composeではなく、Dockerfile側でaddやcopyする
    -. 短絡的にはこれ。本番リリース時ならいいけど、開発時にファイルを1行弄るたびに再ビルドするのは…

bind時に任意のユーザー権限でと指定出来るようになれば万事解決なんだがなぁ
どうすればいいんだ
repeating groupをカード型レイアウトにする方法

repeating groupのスタイルを直接いじってカード型デザインにする方法が見当たらなかったので、groupを使って実装する。

【目標】
・cssでいうところのグリットデザインのようなものをrepeating groupでデータ参照しながら実装したい。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728891/83d286aa-87c1-5ab1-af87-cba2ffe89053.png)
上の画像の(b)のようなものを作る（(a)は割と簡単にできる)
画像元：https://gihyo.jp/design/serial/01/ui-design-unsung/0015

【実装】
・repeating groupのセル内に通常のグループを配置し、repeating groupの背景をnoneに設定し、通常のgroupの背景をFlatに設定する。
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728891/4c61a395-02cd-bc6e-3101-ee3105b4cac6.png)
(わかりやすいようにrepeating groupに背景色をつけてます）
React、cssでドロアーのメニュー(MUIやChakraUIは未使用)

React、cssでドロアーのメニューを実装したときのメモです。画面外からメニューが出てきます。
MUIやChakraUIなどのライブラリは使用しておりません。
左から出るメニューと右から出るメニューを作成しました。
左から出るメニューに関しては、closeボタン押下でメニューを閉じます。
右から出るメニューに関しては、メニュー外をクリックするとメニューを閉じます。
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/b5fa8c02-91ca-933e-7e53-a81d7ec27227.jpeg)


# 左から出るメニュー
DrawerMenuLeftのcssを当ててメニューを画面外に表示します。メニューアイコン押下時は.DrawerMenuLeft--isOpenのcssを追加で当てることでメニューが画面内に移動します。

```css:css (必要なもののみ抜粋)
.DrawerMenuLeft {
  transition: all 0.3s ease-in-out;
  transform: translate(-200px);
  position: fixed;
}
.DrawerMenuLeft--isOpen {
  transform: translate(0);
}
```
```javascript:ソース (必要なもののみ抜粋)
  const [isOpenLeft, setIsOpenLeft] = useState<boolean>(false);
  const onMenuColseLeft = () => {
    setIsOpenLeft(false);
  };
  const onMenuIconClickRight = () => {
    setIsOpenRight(true);
  };
       ：
       ：
  return (
    <>
       ：
       ：
      <nav
        className={`DrawerMenuLeft ${isOpenLeft && "DrawerMenuLeft--isOpen"}`}
      >
        <ul>menu-left</ul>
        <button className="CloseButton" onClick={onMenuColseLeft}>
          close
        </button>
      </nav>
```
# 右から出るメニュー
DrawerMenuRightのcssを当ててメニューを画面外に表示します。メニュー外クリック時は.DrawerMenuRight--isOpenのcssを追加で当てることでメニューが画面内に移動します。
右側なので、起点はright: 0;としています。また、今回はクリック座標とメニューの座標を比較することで、メニュー外でクリックされたと判断しました。
※メニューの下に全画面表示のラベル等を表示してそこをクリックするとメニューを消す方法もあります
```css:css (必要なもののみ抜粋)
.DrawerMenuRight {
  transition: all 0.3s ease-in-out;
  right: 0;
  transform: translate(200px);
  position: fixed;
}
.DrawerMenuRight--isOpen {
  transform: translate(0);
}
```
```javascript:ソース (必要なもののみ抜粋)
  const [isOpenLeft, setIsOpenLeft] = useState<boolean>(false);

  const concernedElement = document.querySelector(".DrawerMenuRight");
  const handleClickOutside = useCallback(
    (e: MouseEvent): void => {
      if (concernedElement && isOpenRight) {
        if (
          e.pageX < concernedElement.getBoundingClientRect().x ||
          e.pageY >
            concernedElement.getBoundingClientRect().y +
              concernedElement.clientHeight
        ) {
          setIsOpenRight(false);
        }
      }
    },
    [isOpenRight, concernedElement]
  );

  const onMenuIconClickRight = () => {
    setIsOpenRight(true);
  };

  useEffect(() => {
    document.addEventListener("click", handleClickOutside, true);
    return () => {
      document.removeEventListener("click", handleClickOutside, true);
    };
  }, [handleClickOutside]);
       ：
       ：
  return (
    <>
       ：
       ：
      <nav
        className={`DrawerMenuRight ${isOpenRight && "DrawerMenuRight--isOpen"}`}
      >
        <ul>menu-right</ul>
      </nav>
```

# 参考
[https://medium.com/@albertchu539/how-to-make-an-app-drawer-with-react-hooks-and-css-1338ae57afb4](https://medium.com/@albertchu539/how-to-make-an-app-drawer-with-react-hooks-and-css-1338ae57afb4)
[https://blog.logrocket.com/detect-click-outside-react-component-how-to/](https://blog.logrocket.com/detect-click-outside-react-component-how-to/)
Power Automateでオブジェクト配列から情報を抜き出す


以下のようなJSONデータが送られてきたときに`https://hogehoge.com/xxxx/yyy`というURLを抜き出すやり方メモです。

以下のようなデータを処理してみます。

> 実際にはTeamsからの通知で使ってます。
> 参考: https://qiita.com/n0bisuke/items/d5da6776d42ab1fce7a3

```json
[
	{
      "name": "投稿者",
      "value": "うこ"
    }, 
    {
      "name": "URL",
      "value": "https://hogehoge.com/xxxx/yyy"
    }, 
    {
      "name": "Status",
      "value": "Not started"
    }
]
```

## アレイフィルターを利用する

他にもやり方はあると思いますが、アレイフィルターを利用することで解決しました。

アクションの追加でアレイで検索すると`アレイのフィルター処理`というアクションを追加できます。

> ![スクリーンショット 2022-07-02 20.39.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/20d975e4-04b8-c5db-31bc-f2f5ad900502.png "スクリーンショット 2022-07-02 20.39.40.png")

`name`というキーを設定できるので、nameが`URL`という文字列と一致したら... という条件を設定します。

> ![スクリーンショット 2022-07-02 20.43.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/fff96777-1ff5-1d61-3f8b-e024c34e7483.png "スクリーンショット 2022-07-02 20.43.36.png")

これでnameがURLのオブジェクトのvalueを取り出せます。

```
{
 name: "URL",
 value: "https://hogehoge.com/xxxx/yyy"
}
```

以降のアクションで`value`という名前の"動的なコンテンツ"を扱うことができるようになります。

> ![スクリーンショット 2022-07-03 0.12.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b1565abd-a489-ecee-7950-4b85a8d49039.png "スクリーンショット 2022-07-03 0.12.43.png")

## 変数に格納する

変数に格納するところまでやってみます。

階層構造が深くなってしまうので変数に一旦格納して別の場所で呼び出すなどをしないと処理の可読性が良くない印象です。

### 変数の初期化

初期化をしないと変数を扱うことができないです。プログラミング的ですね、ノーコード系ツールなのでもうちょっと柔軟でも良い気もします。

アクションで変数と検索し、`変数を初期化する`を選択します。

**最上位の階層じゃないと初期化できないので注意です。何かの入れ子構造の内部では利用できません。**

> ![スクリーンショット 2022-07-03 0.17.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/64d5a792-2fd3-941b-9378-ffe73b3431a2.png "スクリーンショット 2022-07-03 0.17.45.png")

> ![スクリーンショット 2022-07-02 20.50.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/0e05a685-909f-24e7-9bf8-a4c9a47f0075.png "スクリーンショット 2022-07-02 20.50.27.png")

ここで変数の名前を設定できます。`URL`としました。
また種類は`文字列`を選択します。

> ![スクリーンショット 2022-07-03 0.20.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/675d7218-c96e-4433-5733-24266715f7b5.png "スクリーンショット 2022-07-03 0.20.23.png")

これで変数宣言（変数初期化）しておくことで、アレイフィルターをかけたあとのvalueの中身を変数に格納することができます。

`文字列変数に追加`のアクションで格納できます。

> ![スクリーンショット 2022-07-02 21.01.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a80d526e-b9af-2f3d-f1d9-4787e78a7683.png "スクリーンショット 2022-07-02 21.01.37.png")

あとはアレイフィルターの入れ子構造の外でもこの`URL`の値を利用できるので色々と条件の振り分けなどにも利用できます。

## 所感

アレイフィルターを使うやり方以外にももっとスマートなやり方があるような気もします。入れ子構造っぽくなってしまうのが正直操作しにくいですね。

あと、変数に格納するときに初期化が必要なのは気をつけたいです。普通にコード書く時は無いと気持ち悪いはずなのにPower Automateだと手間に感じるのは不思議ですね。
忘備録： Mac と Windows で Key入力環境をなるべく揃えた 

# 概要

自前の趣味用には Windows マシンを使用していて、分割キーボードのMint60を愛用しています。
今回、諸事情で MacBook Pro を仕事用に使用することになりました。
Windowsマシンを使うときも、Macを使うときも、USBを接続し直すことで同一のMint60を使用したい、というモチベーションがあり、しかも、コピペや日本語入力に使用するキーも同じにしたいと考え、試行錯誤したのち、とりあえず満足できる環境になったので、忘備録として、どんな設定を行ったかの記録を残します。

# 参照&参考

* [Mint60のご紹介](https://eucalyn.hatenadiary.jp/entry/about-mint60-01)

* [Mint60キーアサインの変更方法](https://lilakey.com/blogs/docs/mint60-remap)

* [Windows 10：Macのように「英数/かな」を「無変換/変換」キーに割り振り文字入力を切り替える方法](https://enjoypclife.net/windows-10-microsoft-ime-on-off-keyboard-mac/)

# 試行錯誤した結果のキー配置
* コピペ等の操作のキー配置が同じになるように、Windowsでの[Ctrl]と、Macでの[Command]が同じ位置とした。
* 日本語入力の開始と終了を、WindowsもMacも同じキーにアサインできた。
    * 日本語入力モードの開始と終了はキーを別にしておいた方が慣れると捗りそうなのは想像つくが、日本語入力を開始する時に左上キーを叩くのは染みついているので、日本語入力開始は左上のキーに割り当てて、日本語入力終了は使用頻度の低かったキーに割り当てた。

### Remap での Mint60 の キーアサイン
* 階層０
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/d865d0a5-abf7-22b2-707d-01c8d3e542d1.png)

* 階層１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/0012f5b7-bb01-46ca-6faf-0fda1ceedcfa.png)


* 階層２
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/d52433aa-d8ee-1d59-07b2-68037c090616.png)


### Windows 側の設定
* 「右下の Microsoft IMEの [A][あ]アイコンで右クリック」→ポップアップしたメニューの「設定」→「キーとタッチのカスタマイズ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/dc01725f-57b7-6c93-54ac-f02e12ebb310.png)
    * 変更内容
        * 「無変換キー」に「IME-オフ」
        * 「変換キー」に「IME-オン」
  

### Mac 側の設定

* 「システム環境設定」→「キーボード」→（ウインドウ内の右下の）「修飾キー」 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/c45b4dba-263e-3f84-6ac6-773200fdec57.png)

    * 「Control」と「Caps Lock」を入れ替えた。
ターミナルを好きな画像に変えてモチベ上げてみた

みなさん、普段からターミナルを使ってゴリゴリのプログラミングライフを過ごしているかと思います。結構な頻度で使う場合、真っ白なターミナルや真っ黒なターミナルでもやる気が出る人もいるとは思いますが、プログラミング苦手な人やモチベの変動が激しく、長続きしにくい人は一定数いますよね。
そんなあなたに朗報です！！
（もちろんゴリゴリのエンジニアさんもおすすめです😆）

# 実はターミナルの背景画像、変更できる

まずは、こちらをご覧ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/50c14873-4c16-4273-89b2-212d741bcc63.png)
このキャラクターはタイプムーンさんの処女作と名高い月姫（のリメイク版）のヒロイン、
アルクエイド・ブリュンスタッドです。**もし毎日ターミナルで推しが見守ってくれたら**、
**もし尊敬する人がいたら**、モチベ上がりませんか？
私は爆上げです🔥🔥🔥🔥🔥🔥

***この背景画像の設定方法をお伝えします！！！！！！***

# 設定方法
1. ターミナルの環境設定を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/c99a282c-ace3-aec4-98e7-36d9479973d0.png)
1. 「Text」の中の**image**をクリック
    1. 筆者はカッコつけて英語設定Macなので、位置で判断お願いします😅
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/5dbac29e-7413-dce3-b5c5-151cee65f10d.png)
1. 選択したい画像が入っているフォルダを選ぶ
1. 画像を選択
1. **設定完了！！！！**

# 工夫できる点
配色には注意しましょう。見にくくなるだけかもしれません。
1. 文字の色と背景画像の色の組み合わせ
    1. 文字の色→下の画像でText
1. 文字選択時の色と背景画像の組み合わせ
    1.   選択時の色→下の画像でSelection
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/4595a1c3-991c-dc14-1fac-15f38e74fb65.png)
Dockerのコマンド類【自分用メモ】

dockerコマンドのメモ用です。

### docker イメージ
ビルド
~~~イメージ
'通常
docker image build　
'省略
docker build
~~~

ファイル表示
~~~
'通常
docker image ls
'省略
docker images
~~~

取得
~~~
'通常
docker image pull
'省略
docker pull
~~~

削除
~~~
'通常
docker image rm
'省略
docker rmi
~~~

### コンテナ
実行
~~~
'通常
docker container run
'省略
docker run
~~~

停止
~~~
'通常
docker container stop
'省略
docker stop
~~~

一覧
~~~
'通常
docker container ls
'省略
docker ps
~~~

削除
~~~
'通常
docker container rm
'省略
docker rm
~~~
登山コミュニティの可視化（ＶＩＳ．ＪＳ）

 半ば仕事との関わりもあり、ネットワーク分析をやっています。Facebookというサイトは、友達になったら双方向のネットワークが広がるタイプのＳＮＳです。一方でTwitterはどうかと言うと、フォローする側と、フォローされる側が同じ関係にはなりません。ひとえにＳＮＳと言っても、その連関性と言うのは全く違うのですね。


http://www.iplab.cs.tsukuba.ac.jp/paper/master/gao_master.pdf


すこしJavaScriptが使えるようになったので、自分の運営しているＳＮＳサイトでの連関図を作ってみました。

https://create-react-app-yamap-y6hp.vercel.app/


実際、触れてみると、こういうデータ分析は面白いですね。
今のところは、データを全てJSONで手入力しているのですが、最終的にはFacebookをスクレイピングして、データ収集してみたいと思います。

リポジトリ(react-app)
https://github.com/chanmoto/create-react-app-yamap


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/18f26e7c-e2d5-afff-28c2-3636a653a2e5.png)


　傾向としては、最も参加数の多い管理人の私が、もちろん中心に来ますね（当然ですが）。現在のところ参加数が多いほど、枝の数が多くなり中心に来ますが、山アイコンを介在しているので、直接的な人→人の関係にはなっておらず、山アイコンの位置によって人アイコンが引っ張られています。
　このようにデータ分析することで、サークル活動を可視化して、今後の参加者の関連性を把握して、キーパーソンを整理していければと思います。
　グループの投稿についても、投稿者とコメント、イイネの関係性をネットワーク分析すると、より関係性が明らかになってくると思います。もう少し私のＩＴスキルが上がったら、そういう分析にも着手してみたいと思います。
[Java] 列挙型・enum

### はじめに
Java学習中です
今回はenumについてまとめました

### 列挙型（Enum）とは
プログラムの中で定義する定数を拡張（列挙）し、さらに安全かつ便利にする**仕組み**のこと

### 書き方
```java
// 通常のクラスの書き方
public class Dessert {

}

// enumの書き方
public enum Dessert　｛
  APPLE, ICE_CREAM, CAKE, // 最後のカンマはなくてもok
}
```
呼び出す時
(staticの定数を呼ぶときと同じ)
```java
System.out.println(Dessert.APPLE);
System.out.println(Dessert.CAKE);

#=> APPLE
    CAKE
```

### 特徴
##### 変数への代入ok
`Dessert apple = Dessert.APPLE;`Dessert型のインスタンスが出来上がる
`System.out.println(apple);`でさっきと同じ結果

##### メソッドの引数の型にできる
```java
static void printDessertName01(Dessert dessert){
  System.out.println(dessert);
}
```
呼び出す時は`printDessertName01(Dessert.APPLE);`

String型でやってきたことを列挙型にしている
→これで意味の異なる別の引数を渡してしまわないように出来る
絶対列挙型の定数が引数に入るなら列挙型で指定しようってことでしょうか？

```java
static void printDessertName02(String dessert){ 
  System.out.println(dessert);
}
```
`printDessertName02("cat");`とやると普通に通ってしまう
意図しない引数が渡ることを防止する意味で列挙型指定しておくと安心？
```java
printDesertName01(Dessert.APPLE); // ok
printDessertName02("cat"); // 通ってしまう
printDesertName02(Dessert.APPLE); // コンパイルエラー
```

##### 新しいインスタンスを生成できない
`Dessert orange = new Dessert();`はできない（コンパイルエラー）
コンストラクタは自動生成されるがprivateなので外部から呼べないようになってる

##### ==で比較できる
```java
Dessert x = Dessert.APPLE;
Dessert y = Dessert.APPLE;

System.out.println(x == y); // trueを返す
```
列挙型では`static final`で宣言されてるので一つインスタンスが作られれば同じところを参照するの`==`でもtrueが返ってくる

### 機能（メソッド）

**name()**
定数名そのものをString型で返す
`System.out.println(Dessert.APPLE.name());`
`APPLE`と出力

**ordinal()**
列挙した順序をint型で返す
`System.out.println(Dessert.APPLE.ordinal());`
`0`と出力

### もっと活用

##### 値を追加できる
列挙したインスタンスにさらに値をもたせることが出来る

```java
public enum Dessert {
  APPLE(100), ICE_CREAM(200), CAKE(300),
  private int price;
  
  private Dessert(int price) {
    this.price = price;
  }
  public int getPrice() {
    return price;
  }
}
```
`System.out.println(Dessert.APPLE.getPrice());`
`100`と出力

### メソッドを追加できる
インスタンス（定数）ごとにメソッドを追加することが出来る
抽象メソッド用意し、各インスタンスで継承するとインスタンスごとに実行したいコードを変えることが出来る

```java
public enum Dessert {
  // 基本形　public enum Dessert { APPLE, CAKE, }を変形
  APPLE(100) {
    @Override
    void advertise() {
      // りんご用のadvertiseの実装
      System.out.println("まっかなりんごが" + getPrice() + "円！"); // getPriceメソッドも活用できる
    }
  },

  CAKE(300) {
    @Override
    void advertise() {
      // ケーキ用のadvertiseの実装
      System.out.println("皆大好き甘いケーキが" + getPrice() + "円！");
    }
  },
  ;
  // ここから色々宣言してる
  private int price;

  private Dessert(int price) {
    this.price = price;
  }

  public int getPrice() {
    return price;
  }

  // 抽象メソッド、各インスタンスで実装する
  abstract void advertise();
}
```
`Dessert.APPLE.advertise();`で「まっかなりんごが100円！」と出力
`Dessert.CAKE.advertise();`で「皆大好き甘いケーキが300円！」と出力

### 最後
正直使ってみないとピンときませんがとりあえずまとめてみました
閲覧頂きありがとうございました！
Google AppSheetのライブ作成イベントに参加してきた

「誰でもすぐに使えるノーコードツール「Google AppSheet」タスク管理アプリをライブ作成！」というイベントに参加してきました。
普段はローコードツール開発に従事しているのですが、「ローコード／ノーコード」とひとくくりにされることが多いのでやはりノーコードのことも知っておくべきかな、と思い参加しました。

# 出来たもの
以下のようなスマホで使うタスク管理Webアプリを作成しました。
なおこのイベントは登壇者がライブ作成するものであり、参加者が作るのものではありません。でもせっかくなので、説明聞きながら裏で自分も同じものを作ってみました。以下のイメージ画像は私が作ったものです。
## イメージ
#### 一覧画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518616/f291ee77-8769-170f-2d13-5cb199edb611.png)
#### 編集画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518616/81b666a8-558d-2850-6ed3-2d689fdac530.png)

## 機能
作った機能は以下の通りです。
1. タスクの一覧表示／検索／作成／変更／削除をできる
1. ステータスをプルダウンで選択できる
1. 作成画面を開いた際、ステータスに”新規”が自動で設定される
1. ✓ボタンをクリックするとステータスを完了にできる
1. 完了を除く一覧を表示できる
1. レイアウトの調整（タスク名のフォントサイズを大きく、✓の背景をオレンジに、テーマカラーを青に）

1.はAppSheetに以下のExcelを食わせると自動生成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518616/e6b14437-187f-67f7-9df7-b415fa860696.png)

# Google AppSheetの良かった点・悪かった点
## 良かった点
#### コンセプトがしっかりしている
1. レイアウトの自由度が低い
それ良かった点？と言われそうですけど、良かった点です。登壇者いわく「Google AppSheet」では「もうちょいボタンを上に配置した」とか、細やかな修正ができないそうです。デメリットととらえる人のほうが多いと思いますが、私はターゲットを業務アプリに絞っている点を加味するとむしろメリットだと思っています。レイアウトの自由度が高いとUI標準やそれを守らせる仕組み(レビュー、✓ツール)も考えなければいけないですし。

1. できることが限定的
これもよかった点です。エンドユーザが作るわけなのできれいなアーキテクチャになるわけないです。そういう意味でもできることが限定的であることはむしろ良いことだと思っています。
例えばAppSheetでは基本的にExcelやスプレットシートを元にしてアプリを作る形となります。一から自分で作るということはできないそうです。コンセプト的にはExcel管理に嫌気がさしたら「Google AppSheet」で改善しよう！ということだと思っています。

#### とにかく早い
上記に記載した内容を登壇者は40分で作りました。ただその40分にはApp Sheetsのアカウント作成の説明や機能の説明なども含んでいます。説明なしで登壇者が普通に作れば15分で作れたのでは？という印象です。
これは同じノーコードツールであるAdaloやBubbleでもできない早さではないかと思います。「Excelをアプリ化する」というコンセプトに絞っているからこその早さだと思います。

## 悪かった点
#### エンジニアしか理解できない点が多々ある
1. 選択式の項目の場合はEnumを選択する
わかります？私はJavaで使っていたからわかりましたが、エンドユーザはわからないと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518616/548bfa6c-652b-5ade-d45e-7e2b47377c77.png)

1. 型の指定がないとうまく動かないことがある
例えばステータス＝”完了以外”のタスクのみを表示したいのにできませんでした。原因はステータスの型をテキストで定義するのが漏れていたためです。下記画像のBase typeが型にあたります。
エンジニアなら「あー、なるほど。あるある。」と思うかもしれませんが、エンドユーザはわからないですよね？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518616/30db8c8a-7beb-56dd-93f4-cbfcc3cdc9bb.png)

## 感想
・ノーコード／ローコードツールはコンセプトが大事
・ノーコードの開発スピードはまじでやばい
・エンドユーザでも簡単に作れるツールだと思うけど、デバックとか運用できるのかな？
レスポンシブ対応で役立つ実装の仕方

レスポンシブ対応しようと思っていたけど、いざ実装しようと思ってたら何をすれば良いのか分からない人向けの記事となります。
いくつか追加で載せていきますが、とりあえず絶対に知っておいた方がよさそうなことを3選まとめておきます。

1、まずはなんと言っても開発者ツールで携帯の表示を確認すること。
MacBookでは、ショートカットキーでoption + command + Iを打つと開発者ツールが開きます。
![94155508-951D-4ADC-BD47-18BB2EA18CAA.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358181/fe891a5a-2a49-73e3-162e-f449bda55678.jpeg)

ここの赤いところを押すと携帯での表示画面に切り替わる。

2、viewportの設定
<meta name="viewport" content="width=device-width, initial-scale=1">
とhtmlファイルのheadの中に記述しておく。
そうすることでパソコン上では小さく表示されていた文字の大きさが、携帯の画面に適した文字の大きさに切り替わる。

![22E3539E-D6FE-44AC-99C2-E8BB7C045244.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358181/c7fcf1f8-58df-dd41-eec5-3e3d42e0ec1f.jpeg)

↑上<meta name="viewport" content="width=device-width, initial-scale=1">をつける前の画面...
なんとも見にくい、、、というか小さい、、、

![7B3CD697-47C3-4E93-93C5-6D316BF4471D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358181/b311950f-6e83-fe97-d45e-53d72a33a993.jpeg)

↑上<meta name="viewport" content="width=device-width, initial-scale=1">をつけた後の画面...
形は崩れているけれど、文字が携帯の表示用に大きくなった！


3,ここからはcssでresponsive対応をしていく
モバイル版のcssの書き方はcssファイルに
@media(max-width: 600px){
 ~記述する
}
と言った流れになる
Raspberrypi4でvarを別パーティションにする

# やりたいこと

Raspberrypi4はデフォルトでSDカードからブートするようになっている。SDカードには書き込み回数上限があるので、サーバー的に運用するには安定性に欠ける。そこで、Overlayfsを使ってSDカードをリードオンリー化する機能があるが、一方で起動の度にログなど含めてすべてリセットされるのもそれは問題。ということで、/varを別パーティションにすることでログは残りづけるが、基本はリードオンリー化された状態を作りたい。


# 手順

### 1.まずは適当なディスクに/var用のパーティションを作る

https://qiita.com/ryot0/items/d3cb7d6e3d2850286597


### 2.上で作ったパーティションを適当なディレクトリにマウントする

```shell
sudo mount -t btrfs -o defaults,noatime,compress=lzo /dev/disk/by-partlabel/varpt01 /data/var
```


### 3.上でマウントしたディレクトリに/varの内容をコピーする

なるべく何も動いてない状態で作業したいので、シングルユーザモードに変更して行う

```shell
sudo init 1
cp -a /var/* /data/var/
mv /var /var.org
mkdir /var
```

### 4.fstabを修正して/varに作ったパーティションをマウントするようにする

```shell:/etc/fstab
PARTLABEL=varpt01    /var    btrfs    defaults,noatime,compress=lzo    0    2
```

### 5.再起動して/varにマウントされていることを確認する

```shell
sudo shutdown -r now
mount
ls -l /var
```

### 6.dphys-swapfileを無効化する

起動ログにdphys-swapfileのエラーが出るのでこれを無効化する。

```shell
sudo systemctl disable dphys-swapfile.service
```

もう一回再起動してFAILEDが出ないことを確認する。
もう/var/swapfileは不要なので、削除する。

```shell
sudo rm /var/swap
```

### 7.代わりにswapパーティションを有効にする

fstabに以下の行を追加する。

```shell:/etc/fstab
PARTLABEL=swappt01    swap    swap    defaults    0    0
```

あとは、raspi-configでReadonly化すればOK
Ruby 練習問題１ ~ハッシュの基礎~

こんばんは、プログラミング初学者"fujitacoma"です！

今回からシリーズとして、Rubyの練習問題を解いていきたいと思います。
徐々に難易度を上げていく予定ですので、お付き合い頂けますと幸いです！

それでは早速始めます！

# 問題
```
puts hash.keys
puts hash.values
```
上記のメソッドを実行した時に
```
one
two
three
1
2
3
```
とターミナルに表示されるような変数hashを作成するためのコードをシンボルを使って記述してください。

# 解答と解説
### 模範解答
```
hash = { one: 1, two: 2, three: 3 }
```
### 解説
シンボルを使ったキーの記述方法は、キーの後にコロン:をつけて定義します。
```
hash = { キー: 値}
```
ハッシュをシンボルで記述すると、コード上では文字列のように見えていますが、内部的には数値として処理されます。
数値として扱われるので、 __処理速度が速くなる__ ことと __文字列としての役割__ も果たします。
よって、ハッシュのキーにはシンボルを用いることが多いです。

ハッシュのキーを取得するにはkeysメソッド、値を取得するにはvaluesメソッドを使用し取得します。

オブジェクト.keysで、ハッシュに含まれるキーを取得します。
```
hash = { one: 1, two: 2, three: 3 }

puts hash.keys
one
two
three
```
オブジェクト.valuesで、ハッシュに含まれる値を取得します。
```
hash = { one: 1, two: 2, three: 3 }

puts hash.values
1
2
3
```

# 最後に

ここまでお読み頂き、有難うございました！
初学者なりに調べつつ記載しておりますが、
ご指摘やアドバイスがあればコメント頂けますと幸いです！
【プログラミング初心者】学習中意識していることについて

# はじめに
はじめまして。プログラミングスクールに通っている者です。
現在学習を開始し1か月が経ちましたので、自身の学習方法について振り返ってみようと思います。
こちらの記事をご覧になられた際、もし「こんな良い学習方法があるよ」などご意見があればぜひ教えていただきたいです。

# 学習中意識していること
学習中に意識していることは下記4つです。
個人的にはスクールに通い始め、②と④の重要さを特に実感しています。

### 全体学習での4つのポイント
**Point**
① **何**を学習するのか考える
② **スケジュール**を立てる（**いつまで**に**どこまで**を意識）
③ **実行**する（必要であれば**リスケ**）
④ **振り返る**

こう見ると、ほとんどPDCAサイクルと同じですね。笑

# Rails学習中に意識していること
学習の中でも現在、Railsを学習中に意識していることは下記5つです。
個人的にIT業界は①②③をサクッとこなし（曖昧にこなすわけではない）④にすぐ取り掛かれるかが重要なのかなと思いました。
（⑤は個人学習として必須項目ですが忘れがちなので意識するようにしています。）
### Rails学習での5つのポイント
① **何**を実装するのか**ざっくり理解**する
② **どこ**を編集するのか把握する
③ **手順**を整理する
④ **実装**に取り掛かる（実装しながらの理解を心がけています）
⑤ **振り返る**（実装中に気づかなかったところも気づけたりして、より理解が深まります。）

こちらも全体学習と同じくほとんどPDCAサイクルと同じでした。笑

# まとめ
自分自身、理解しないと手を動かせないタイプでしたが、様々な人の意見を聞き
 **「とにかく手を動かす」** ことの大切さを学び上記方法で学習を実践しています。
今後も学習方法を工夫しながら、成長し続けられるよう頑張りたいと思います。
Slackのカスタムレスポンス動かんぞ？？

Slackで便利なカスタマイズ、カスタムレスポンス。あらかじめ設定していれば、決まった内容を送ったり、まとめて決まったプロジェクトメンバーをメンションできたりします。そんな超超便利なカスタムレスポンスが動かない問題を解決します！！

# 原因
## カスタムレスポンスに設定した記号や文字の全角半角問題
大体ここに帰結します！！！！！
仮に、スマホアプリ開発のプロジェクトチームが発足したとしましょう。
その際に「@スマホアプリPJT」というカスタムレスポンスを設定します。（@は半角）
### 設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/b2c03102-ef5f-81a2-9305-01ee62ec9590.png)

この時、
**@スマホアプリPJT**
**＠スマホアプリPJT**
この２つをSlackのカスタムレスポンスは識別できますが、私たち人間からしたら
半角全角の違いだけで、正直見た目もほとんど同じで区別がつきにくいですよね？？💭

### 実際のSlack上での画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/68ccd8e6-39fb-03fd-4ba8-1517a3a9a5f2.png)
SlackBotは賢いので、簡単に判別しますが、正直半角・全角の違い分かりにくいですよね😅

この問題に対する解決策は至ってシンプルです！！

# 解決策
### 入力フレーズに全角の＠（記号）を追加する
これだけです！早速やってみましょう！

#### 設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/59629594-fac0-b8ee-aed2-adc7335f3411.png)

#### 実際の画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/c7f2f3dd-d8be-38e4-e73a-5b74bc2d2bc0.png)

先ほどと違って、**全角・半角問わずカスタムレスポンスが動きました**ね🎉🎉🎉

これにて、Slackのカスタムレスポンス動かんぞ？？事案は終了です！
お疲れ様でした！
PHPでMySQLのデータを出力する

PHPでMySQL連携ができたので、忘れないようにメモを残します。

# MySQLの設定

MySQLに以下のような設定をしました。なおログインユーザは`root`で、パスワードは`password`にしています。

```:MySQLのデータベース
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| shop               |
| sys                |
+--------------------+
```

```:shopデータベース内のテーブル
+----------------+
| Tables_in_shop |
+----------------+
| member         |
+----------------+
```

```:memberテーブル内のデータ
+--------+------+
| name   | age  |
+--------+------+
| satou  |   29 |
| tanaka |   35 |
| ueda   |   25 |
| yamada |   40 |
+--------+------+
```

# PHPファイル

下の`shop.php`ファイルを`/var/www/html/`配下に置きます。

```php:shop.php
<html>
<head>
</head>
<body>
member list<br>
<?php
$dsn = 'mysql:host=localhost;dbname=shop;charset=utf8';
$user = 'root';
$password = 'password';
try {
        $pdo = new PDO($dsn,$user,$password);
} catch(PDOException $e) {
        exit('Database error. ('.$e->getMessage().')');
}
$sql = 'select name,age from member where name like :name';
$stmt = $pdo->prepare($sql);
$name = '%'.$_GET['name'].'%';
$stmt->bindParam(':name',$name,PDO::PARAM_STR);
$stmt->execute();
$all = $stmt->fetchAll();
foreach($all as $row){
        print htmlspecialchars($row['name'],ENT_QUOTES,'UTF-8').'('.$row['age'].")<br>\n";
}
?>
</body>
</html>
```

これはmemberテーブル内のnameを検索し出力するプログラムです。
※SQLインジェクション対策としてbindParamを使い、クロスサイトスクリプティング(XSS)対策としてhtmlspecialcharsを使用しています。

# 動作確認

Firefoxで`localhost\shop.php?name=da`と入力します。（`da`を含む名前を持つデータのみ出力します）
![shop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593076/a3458e2a-daaf-cc26-c47e-593a85aa152c.png)

予定通り、uedaとyamadaが出力されました。
IntelliJ IDEAでAndroidエミュレータが起動しない件

Flutter開発でIntelliJ IDEAを使っているのですが、Androidエミュレータがどうやっても起動してくれないという事案が発生しました。自分なりに頑張ったIntelliJ IDEAを用いたエミュレータ起動の解決策を残します。

# 解決策
1. IntelliJ IDEAの右上の**Project Structure**を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/08e800a3-388d-7ff9-9500-199dcad37270.png)
1. ModulesのExport内にある、**Flutter for Android**をマイナスボタンで削除
    1. サイドバーにあるProblemの内容をチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/41899f52-1838-564c-e54c-be7bcf0bf20c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/21fc5915-a855-1184-e47b-9988a1e35044.png)
1. Modulesの**Module SDKでAndroid API 29 Platform**を選択
    1. 相当古いAPIじゃなければ、バージョンは何でもいい可能性あり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/91e550b1-6e8a-d07f-f1c8-118dc142aae7.png)

# エミュレータを起動してみる
今回は、事前にAndroid Studioで作成していた PIXEL API 28を起動してみます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/0eb96122-a6fb-ca94-443b-19bb15ea99eb.png)
#### 動いた！！！
デバッグモードのFlutterアプリも動くかな？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/162a9833-2c37-eaf7-ae91-3770cd5dd019.png)
#### きたあああああ！！動きました！！🔥

これにて、AndroidエミュレータをIntelliJ IDEAから起動できない問題完結です！
お疲れ様でした✨
MonoでDigit Separator (桁区切り文字)にハメられた話

## あらまし

まずは、こいつを見て欲しい

```csharp
using System;

static class Program {
    static void Main() {
        long x1 = 33076206526426037;
        long m1 = 1000000007;
        
        long x2 = 33076206526426037;
        long m2 = 1_000_000_007;
        
        Console.WriteLine(x1 % m1);
        Console.WriteLine(x2 % m2);
    }
}
```

違いは、`m2`が3桁ごとに`_`で区切られているというところだけ。
この区切りは、`Digit Separator (桁区切り文字)`と呼ばれるものである。

[digit-separators.md](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-7.0/digit-separators.md)から引用すると [^1]、

[^1]: https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/proposals/csharp-7.0/digit-separators に日本語翻訳があるが機械翻訳が酷すぎて読めたものじゃない

> Being able to group digits in large numeric literals would have great readability impact and no significant downside.
> (snip)
> The syntax is straightforward, and the separators have no semantic impact

とあるように、ソースコードの可読性のためだけに特化した機能。

実際このコードを手元の`dotnet SDK`でビルド・実行すると、両者とも`294892595`という結果となる。

## 本題

ここからが本題で、上述のコードを、`6.8系のMono JIT compiler`でビルド・実行すると前者が`294892595`であるのに対し、後者が`206526194505`と両者で違う結果となり、めっちゃ頭を抱えた。

実際には、競プロによくある。

> ただし、答えは非常に大きくなる可能性があるので、1,000,000,007 で割った余りで出力してください。

な問題を解いてて、WAになってあるぇとなったのが発端。

何やかんや調べていて行き着いた先が、monoの[issues/16648](https://github.com/mono/mono/issues/16648)で、どうにも`_`の次の数値をコピーする振る舞いらしい。

[atcoder](https://atcoder.jp/contests/arc143/rules)では、`dotnet core`を選択できるので回避可能ではあるが、`Mono-mcs 6.8.0.105`も用意されているため使用しないよう注意が必要と思われる。

[paiza](https://paiza.jp/guide/language.html)に至っては、`Mono-mcs 6.8.0.105`のみ(2022/7/2日現在)のため、スキルチェック問題で`digit separator`を使用するとぜっつぼ〜を味わうことになる。

## おまけ1

[issues/16648](https://github.com/mono/mono/issues/16648)にて、[pull/18539](https://github.com/mono/mono/pull/18539)が提出され、既に`main`ブランチに取り込まれてる模様。ただしリリースパッケージ化されているかどうかは不明（そもそも手元環境は`dotnet sdk6`だし）

## おまけ2

`1000000007`という数値は、`int`に収まる値であるにもかかわらず、`1_000_000_007`にしたら`int`超えとるぞゴルァとコンパイラに怒られていた。
勘のいい人はきっとここでなんかおかしいと気づけていたのかもしれない。
私は気づけませんでした。
【#17 エンジニア転職学習】Git/Github　.gitignore / commit --amend

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

昨日に引き続きGit基礎に関して進めていきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
基本的なローカル、リモートリポジトリとのやり取りを行うコマンドを中心に学習しました。

* ファイルの削除・移動
* **.gitignoreファイル　←Topics!!**
* リモートリポジトリへ送信
* **各種変更をもとに戻す方法　←Topics!!**

# .gitignoreファイル / git commit --amend
### .gitignoreファイル
この中にファイル名や拡張子を指定して記述しておくことで、指定のファイル等がGit管理から除外されます。
サーバのパスワードを記録しているファイル等**流出してほしくないファイルの誤流出を防ぐため**に使うそうです。
### git commit --amend
ローカルリポジトリへの直前のコミットをやり直すためのコマンド。
直前のcommit分がなかったこととして再commitする。
ただし、**リモートにpushしたコミットに対しては使用してはいけない。**


使用している教材はこちら↓


https://www.udemy.com/course/unscared_git/


# おわりに
最後までお読みいただきありがとうございました。
しばらくはGit基礎をやっていきます。
アドバイス・応援コメント等いただけますと幸いです。
macOSの開発環境を確認したい

macOSのビルド環境を確認するときのコマンドのメモ。

```zsh:checkEnv.sh
#!/bin/zsh checkEnv.sh
set -ex

# システム関連
sw_vers
uname -a
system_profiler SPHardwareDataType

# node関連
node --version
which node
npm --version
which npm
node-gyp --version
which node-gyp
yarn --version
which yarn

# python関連
python --version
python3 --version
which python3

# C/C++関連
clang --version
which clang
xcrun --show-sdk-path
xcrun --sdk macosx --show-sdk-path
xcodebuild -version
xcodebuild -showsdks

xcodebuild -sdk -version
```

## MacOS SDKの変更
xcrun --show-sdk-path で表示されるSDKがデフォルトで利用される。変更するときは以下のようにSDKROOTを環境変数で定義する。SDKは[ここ](https://github.com/phracker/MacOSX-SDKs/releases)から入手したものを以下のようにSDKsフォルダに展開する。
```rc:~/.zshrc
export SDKROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk"
```