OmniAICreator/Qiita-1.07M huggingface dataset:
サブネットマスクの正当性検証

サブネットマスク文字列のバリデーションコードです。
調べてもドンピシャの情報を見つけきれなかったので記録に残します。評価結果はいずれもbool値。
以下のようなそもそもIPv4アドレスとして正しいかの検証は、多くの言語でライブラリが存在すると思うので事前にそれを使用してください。

- 2進表示が8ビットを超えていない（255以下である）
- オクテットの個数が4

##サブネットマスク記法

###Java
```Java:
Arrays.asList(String.join("", "255.192.0.0".split("\\."))).forEach(x -> {
	String binStr = Integer.toString(Integer.parseInt(x));
	binStr = "00000000" + binStr;
	int len = binStr.length()
	binStr.substring(len - 8, len);
}).matches("^1*0*$");
```

###Javascript
```javascript:
"255.192.0.0".split(".")
.map(x => ('00000000' + Number(x).toString(2)).slice(-8))
.join("").match(/^1*0*$/) != null
```

##CIDR記法
仮に192.168.1.1/10などであるとします。

###Java
```Java:
"10".matches("^[0-9]{1,2}$") && Arrays.asList(IntStream.rangeClosed(0, 32).toArray()).contains(Integer.parseInt("10"));
```

###Javascript
```javascript:
'10'.match(/^[0-9]{1,2}$/) != null && [...Array(33).keys()].indexOf(Number('10'))
```
ViewcontrollerからTabBarControllerへコードで移動する

#ViewControllerからTabBarControllerに移動する
まず、最初に下の図のようにViewControllerからTabBarControllerに紐づいてた緑のViewControllerに遷移しても、ViewControllerへの移動なので、`下のタブが表示されません`。だから、TabBarViewControllerへ移動する必要があります。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/839966/9e9e5ac4-1ea4-3429-e7f7-40977a9775bf.png">
#コード

```ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    @IBAction func FromViewControllertoTabBarController(_ sender: Any) {
        
        let storybord=UIStoryboard(name: "Main", bundle: nil)
        let TabBarController=storybord.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
        //[0]が緑のViewControllerで[1]にすると赤のViewControllerに遷移する
        let ViewController=TabBarController.viewControllers?[0] as! FirstViewController
        //TabControllerに遷移した時に最初にどの画面を表示するかを選択する
        TabBarController.selectedViewController=ViewController
        TabBarController.modalTransitionStyle = .crossDissolve
        TabBarController.modalPresentationStyle = .fullScreen
        self.present(TabBarController, animated: true, completion: nil)
    }
    
}
```
赤色のViewControllerにはFirstViewControllerクラスが紐づいています。
<img width="300"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/839966/90970c43-f088-33af-0723-e7928b9b151e.gif">
GraalVM を使って Scala コードのネイティブイメージを警告なしで作る

[GraalVM を使って Scala コードのネイティブイメージを作る](https://qiita.com/__kijuky__/items/03bb1f65545f9418a13e) の続きです。

こちらの記事でネイティブイメージを作成したとき、下記の警告が出ていました。

```shell
Warning: Reflection method java.lang.Class.getMethods invoked at scala.Enumeration.populateNameMap(Enumeration.scala:201)
Warning: Reflection method java.lang.Class.getDeclaredFields invoked at scala.runtime.Statics$VM.findUnsafe(Statics.java:178)
Warning: Reflection method java.lang.Class.getDeclaredFields invoked at scala.Enumeration.getFields$1(Enumeration.scala:195)
Warning: Reflection method java.lang.Class.getDeclaredFields invoked at scala.Enumeration.populateNameMap(Enumeration.scala:197)
Warning: Reflection method java.lang.Class.getDeclaredFields invoked at scala.Enumeration.getFields$1(Enumeration.scala:195)
Warning: Aborting stand-alone image build due to reflection use without configuration.
```

こちらの警告が出ないようにするための対処方法を共有します。

# この警告は何？

GraalVM の `native-image` はリフレクションのコードに完全に対応しておらず、非対応のリフレクションのコードが出てきた場合にこの警告が表示されます。この警告を出さないようにするために、`native-image` に対してどんなリフレクションの機能を使っているかを教えてあげる必要があります。

# プロファイルの作成

その情報を作成する方法が下記です。

```
% mkdir -p META-INF/native-image
% java -agentlib:native-image-agent=config-output-dir=META-INF/native-image -cp .:/usr/local/opt/scala/libexec/lib/scala-library.jar Test
% ls META-INF/native-image 
jni-config.json			resource-config.json
proxy-config.json		serialization-config.json
reflect-config.json
```

参考までに各ファイルはこのような内容でした

```json:jni-config.json
[
]

```

```json:proxy-config.json
[
]

```

```json:reflect-config.json
[
{
  "name":"java.lang.invoke.VarHandle",
  "methods":[{"name":"releaseFence","parameterTypes":[] }]
}
]

```

```json:resource-config.json
{
  "resources":{
  "includes":[{"pattern":"\\Qlibrary.properties\\E"}]},
  "bundles":[]
}

```

```json:serialization-config.json
[
]

```

これらのファイルが存在した状態で再度コンパイルしてみます。

# コンパイル

```shell
% native-image Test -cp .:/usr/local/opt/scala/libexec/lib/scala-library.jar
[test:6158]    classlist:   1,292.99 ms,  0.96 GB
[test:6158]        (cap):   2,673.58 ms,  0.96 GB
[test:6158]        setup:   3,875.80 ms,  0.96 GB
[test:6158]     (clinit):     171.38 ms,  1.69 GB
[test:6158]   (typeflow):   5,738.16 ms,  1.69 GB
[test:6158]    (objects):   5,708.21 ms,  1.69 GB
[test:6158]   (features):     356.71 ms,  1.69 GB
[test:6158]     analysis:  12,223.73 ms,  1.69 GB
[test:6158]     universe:     331.86 ms,  1.69 GB
[test:6158]      (parse):     724.78 ms,  1.69 GB
[test:6158]     (inline):   1,821.46 ms,  1.71 GB
[test:6158]    (compile):   3,647.49 ms,  3.27 GB
[test:6158]      compile:   6,774.16 ms,  3.27 GB
[test:6158]        image:     934.15 ms,  3.27 GB
[test:6158]        write:     301.58 ms,  3.27 GB
[test:6158]      [total]:  25,898.56 ms,  3.27 GB
```

今度は警告なしでコンパイルできました。めでたしめでたし。

# 参考

- [Introducing the Tracing Agent: Simplifying GraalVM Native Image Configuration](https://medium.com/graalvm/introducing-the-tracing-agent-simplifying-graalvm-native-image-configuration-c3b56c486271)
yum update したら perforce が死んだ話

久しぶりに AWS サーバーにログインして yum update したら P4 が繋がんなくなったお話です。死ぬかと思った。

# インスタンスを再起動 ～ p4d 復旧まで
ひとまず EC2 インスタンスを再起動するかー、とコンソールから実行。
あれ、でも P4 サーバーってどうやって起動したんだっけ・・・？としばらくググる。
P4 コマンドさえも $P4PORT を設定していないので通らない状態でした。
> Perforce client error:
   Connect to server failed; check $P4PORT.
   TCP connect to perforce:1666 failed.
   perforce: host unknown.

備忘録として残しておきます。

```
p4 set P4USER=username
p4 set P4PORT=1666
```

## p4d コマンドの実行
まずは P4 サーバーのルートディレクトリ探しから。
自分の場合は /opt/perforce/servers/master/root に構築してました。
何のドキュメントを見ながら作ったのか、全く覚えてないのだが perforce ユーザー権限で作成されていた。こういうのはメモしておくべきだと激しく後悔。

```
-bash-4.2$ ls
db.bodresolve   db.graphindex  db.logger    db.revpx      db.templatesx
db.bodresolvex  db.graphperm   db.message   db.revsh      db.templatewx
db.bodtext      db.group       db.monitor   db.revstg     db.ticket
```
こういった db ファイルがたくさん並んでいるのがルートディレクトリのようです。
さっそく再起動コマンドを実行する。

```
-bash-4.2$ p4d -r /opt/perforce/servers/master/root -p 1666
-bash-4.2$
```
しかし、なにもおこらなかった！

## ログ調査
> /opt/perforce/servers/master/logs/log

cd コマンドを唯々繰り返していると logs ディレクトリが存在していることに気づく。

```
Perforce server error:
        Database is at old upgrade level 36.  Use 'p4d -r /opt/perforce/servers/master/root -xu' to upgrade to level 39.
```
これだ！これだよ！

```
-bash-4.2$ p4d -r /opt/perforce/servers/master/root -xu
Upgrades will be applied at server startup.
```
そして再び起動コマンドを実行。

```
-bash-4.2$ p4d -r /opt/perforce/servers/master/root -p 1666 -d
Perforce Server starting...
```
-r で P4ROOT の指定、-p でポートの指定、-d でバックグラウンド実行となります。

## P4V からの接続テスト
> ssl:{address}:1666

いつも通り SSL での接続を試みる。

> SSL connect to ssl:dev.nanae.online:1666 failed (既存の接続はリモート ホストに強制的に切断されました。 ).
    Remove SSL protocol prefix from P4PORT or fix the TLS settings.

？？？ SSL プロトコルで繋がんない？

> tcp:{address}:1666

繋がったァァァ！？！？？

# TLS 設定とはなんぞや？
[ついにTLS 1.0/1.1の無効化が決定！影響や確認・対応方法とは？](https://ssl.sakura.ad.jp/column/tls-invalidation/)
> 簡単に説明すると、TLSは「暗号化通信をするための手順書」のようなものですが、TLS 1.0/1.1などの古いバージョンには脆弱性がある（一定の条件下であれば暗号解読が可能である）ため、利用は非推奨とされていました。

どうやら脆弱性のある規格のようで。もしかすると yum update でその辺も更新されちゃったのかもしれないですね。

## Perforce の設定
Perforce を調べるにもなかなかに文献が少なく苦労します。
[SSL and TLS Protocol Versions](https://community.perforce.com/s/article/15258)

```
p4d -r /opt/perforce/servers/master/root -c"set ssl.tls.version.min=10"
```
ブログにある通り、一旦 TLS v1.0 でも接続できるように設定。"p4 admin restart" だけじゃ反映されないそうな。めんどくさいので sudo reboot しました。ここでようやく SSL でも接続可能に。

## P4V クライアントの更新
> Version:   P4V/NTX64/2020.2/2028073

って書いてあるんで
![bec1d9557fbcc8d97e156c2f473258f9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41105/0d0f0057-3d15-d0a2-1a9e-f738f12d0128.png)
更新ポチ。TLS 1.1 に戻しても無事繋がるようになりました。
Swift5で詰まったこと　実行時のエラー

Swiftを使うにあたって一番苦労したこと

<今回使用しているもの>
⚫️Swift5
⚫️FireBase


学校のゼミでiBeaconとFirebaseを利用して出席アプリを作成しています。
その中でコードエラーではないエラーに悩まされたので連携。

"Command CompileSwiftSources failed with a nonzero exit code"

さてはて何のエラーなんだろうと思って色々調べてみました。

どうやらFireBaseで利用しているPod関連だそうです。アプリの都合上、cocoapodsを少し古いバージョンでインストールしたために起こったかもしれないです。
初心者なので違ったら怖いですが、、

<解決方法>
ターミナルでPodfileを開き、 pod update -> pod clean -> pod install 
と打つとエラーは消えました！

もしかしたらpodの設定が初期化されているかもしれないので、pod install後の起動時にはエラーが出るかもしれません。

(特に下のQuoted Include~とか)![スクリーンショット 2021-01-26 16.15.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056286/2c05841c-746d-dc61-8e3a-3253751faabc.png)

<補足>

今回のエラーを解決しようとPodsを色々といじっていたら、謎のPodfile.swpというファイルができあがりました。swpファイルは基本的にバックアップファイルと考えていいですが、残しておくとメモリをたくさん消費しているようです。いらないなら消したほうが得策かもしれません。
【AWS認定】クラウドプラクティショナー&ソリューションアーキテクト - アソシエイト 合格体験記 


# はじめに
AWS認定 クラウドプラクティショナーとソリューションアーキテクト - アソシエイト(SAA-C02)に受かったので体験記です。
![AWS_Certified_Badges_20210126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/791798/c5d0bd16-44ae-e16c-2368-5e4c8aae3266.png)

以下、略称を利用することがあります

- クラウドプラクティショナー=CLF
- ソリューションアーキテクト アソシエイト=SAA

# 教材

## クラウドプラクティショナー編

### 黒本
- [リンク](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8-%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-ebook/dp/B07M7S9GDL)
- 古めだが初手に読む本としてはよいと思います
- 出題範囲に被りがあるため、CLFだけ受かりたい場合もおすすめ

### CLF向け問題集(udemy)
- [リンク](https://www.udemy.com/course/aws-4260/)
- 1周してよく復習すればCLFに関しては安泰 問題集で覚えるタイプの人におすすめ
- 黒本では頭に入らなくても問題集で間違えると頭に入るので、個人的には役に立ったと思います

### CLF向け問題集(kindle)
- [リンク](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E6%A8%A1%E6%93%AC%E5%95%8F%E9%A1%8C%E9%9B%86-Yoshi-Otobe-ebook/dp/B081D4ZJ5G)
- 直前に1周。udemyの問題集よりは遥かに簡単なので、あちらを解いたなら不要かも
- udemyの正答率が悪く不安な場合は解くと自信がつくのでおすすめ

## ソリューションアーキテクト アソシエイト編

### SAA-C02向け問題集(udemy)
- [リンク](https://www.udemy.com/course/aws-knan/)
- 1周+復習。ただしこちらは復習に時間がかかった(1試験あたり少なくとも2時間程度)
- 問題文の雰囲気は似ているが出題傾向は本試とは少々異なる印象。間違えた際は答えを暗記するのではなく、サービスの仕組みや設定方法まで遡って復習するのがよいと思います
- [試験突破講座](https://www.udemy.com/course/aws-associate/)の方は未履修です

### 各種技術系記事
- Qiitaはじめ、[Developers.io](https://dev.classmethod.jp/)、[サーバーワークスさんのブログ](https://blog.serverworks.co.jp/)、はてブなど
- 問題集で間違えた部分の復習+サービスの動かし方を知る用途に利用。  
1問間違えたら当該サービスの記事を3～5つは読むようにしていました

# 受験結果、所感
|  試験  |  得点  |  受験日  |
| ---- | ---- | ---- |
|  CLF-C01  |  965  |  2020-10-04  |
|  SAA-C02  |  793  |  2021-01-16  |

- CLFに関してはオーバーキルだったかも…  
黒本1周程度でも受かる人は受かれそうです
- SAAは少々危なかった…  
間違えた問題でも調べてみると大抵AWS公式のドキュメントにあったので、  
多少ハンズオンを経るのが確実かもしれません
- 学習期間はCLF,SAAともゆっくり1ヵ月程度。  
2週間程度の期間で密度濃く取り組んだ方が本当は良いと思います
 
#### SAA取れるならCLFは不要？
- **アソシエイト3冠するつもりならCLFは不要**が正しい気がします
- CLFでは、SAAではあまり出ないがDVAで出そうな開発系サービスやSOAで出そうなセキュリティ系サービスにも少々触れられます
    - AWSの実務経験はないが、今後のためにAWSの概要程度は抑えたいという温度感の場合はCLFもおすすめです

# 最後に
- CLF+アソシエイト3種+SAPの5冠までは目指す予定です(宣言)
    - 取り急ぎ、DVAに受かったらまた書こうと思います
[OutSystems]UI PatternのAdvanced Formatの使い方

OutSystemsの公式部品であるUI PatternのWidgetにはAdvancedFormatというプロパティがあります。

UI PatternはJavaScriptのライブラリをラップしてWidgetにしてあるようで、オリジナルのライブラリが持っている設定値のうち、Widgetのプロパティにない設定を行う事ができます。

OutSystemsのPatternのドキュメントには詳細が記述されていないので、調査・設定方法をまとめてみます。

以下、Mobile/Reactive用のPattern DatePickerを使って手順を確認していきます。

[DatePickerの公式ドキュメント](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Design_UI/Patterns/Using_Mobile_and_Reactive_Patterns/Date_Picker)

# 調査方法
## プロパティを確認
画面に配置したWidgetのプロパティを見て、AdvancedFormatがあることを確認する。
AdvancedFormatがないWidgetももちろんあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0d72ce8b-ad1b-63ff-370f-82ff38659b32.png)

## オリジナルのJavaScriptライブラリを特定
画面に配置したWidgetをダブルクリックするなどして、参照している部品を選択する。
Descriptionにオリジナルライブラリ (JavaScript) へのパスが書いてある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c9b1c90a-9fe6-8866-9f6b-034758e8eb44.png)

AdvancedFormatプロパティがある場合は、大体このようにDescriptionにオリジナルライブラリへのパスが書いてあるようです。

```
For advanced options, read the official documentation:
https://github.com/dbushell/Pikaday
```

## オリジナルライブラリのドキュメントから設定値を確認
[Descriptionにあったパス](https://github.com/dbushell/Pikaday)を開いて設定値をチェックします。
optionsとかConfigurationという題のことが多いと思いますが、設定値のドキュメントで使えそうな項目を探します。

注意点として、WidgetにInputパラメータとして露出している設定項目は、あえてAdvancedFormatを利用する必要がありません。

例示ということで、以下２項目を設定することにします。

- yearSuffix：年表示にサフィックスを指定する
- showDaysInNextAndPreviousMonths：月カレンダーを表示するときに、前月の最後の方の日、あるいは翌月の最初の方の日を表示するか否か。Widgetではデフォルト値がtrueのようなのでfalseに

# 設定
## 設定方法
JSON形式で設定します。
JSONオブジェクトなので、まず全体を中括弧「{}」で囲む。
各設定項目の分だけ「設定項目名: 値」の組を並べ、半角カンマ「,」で区切る。
最後に、この値を「OutSystemsのText型」であるAdvancedFormatプロパティに設定するのでダブルクォーテーション「""」で囲みます。

例：
"{yearSuffix: '年', showDaysInNextAndPreviousMonths: false}"

## 設定例
設定前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/144298bb-d761-41e6-fc9c-aaa98e4bac19.png)

設定後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/2a8214c0-a5ea-23ef-8851-b515e65eafbf.png)


# その他の例
以前QiitaにCarouselの例を書きました。
[OutSystemsのCarousel Widgetの使い方](https://qiita.com/jyunji_watanabe/items/d22fa868a7b518ff134d#advanceformat)
[メモ]`VirtualAllocEx`で確保した他プロセスメモリーをスマートポインターとして扱う

現時点では[microsoft/wil](https://github.com/Microsoft/wil/wiki/RAII-resource-wrappers)にもラッパークラスが用意されていなかったので、作ってみました。

```cpp:定義
struct virtualallocex_deleter {
    HANDLE const hProcess;

    template<typename T>
    void operator()(T* ptr) const
    {
        ::VirtualFreeEx(hProcess, ptr, 0, MEM_RELEASE);
    }
};

template<typename T = void>
using unique_virtualallocex_ptr = std::unique_ptr<T, virtualallocex_deleter>;
```

```cpp:使用方法
unique_virtualallocex_ptr<> pRemote{
    ::VirtualAllocEx(hProcess.get(), nullptr, sizeof(localData), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE),
    virtualallocex_deleter{hProcess.get()}
};
```
世界のVIPが指名する執事の手帳・ノート術

# 書籍情報
- 世界のVIPが指名する執事の手帳・ノート術
- 新井直之
- 文響社

# 読んだ目的
- 仕事の効率化のためにノートや手帳の活用方法を模索したかった。

# 学んだこと・感じたこと
- 打合せ前の3行
    - ゴール・次のアクション・しめきり
    - 打合せに目的意識を持つ
    - 事前に考えておくと、自分本位に仕事が進められる可能性が高まる
- よく使う単語は略語化
    - エビデンス：EV
    - なるはや：ASAP(as soon as possible)
    - その日中に：END(end of the date)
    - 参照：cf
    - 処理中：WIP（work in progress）
    - リマインド：RD
- 赤ペン方
    - メモしたノートから重要な単語を赤丸してつなぎ合わせて、要点をまとめる
    - その様子を周りに共有すると。共通理解につながる
- リーガルノートいいぞ
    - 切り離せる
    - 黄色い
        - アイデア出やすい？
        - 他の紙と混同しない
    - ノートパッドで見栄え丸
- 打合せの内容共有で、トラブル防止
    - 共有するというオープン性が信頼関係に繋がる
    - ノートはいざという時の保険
- 手帳で目標達成を見える化する
    - 月の初めに月の目標
    - 日々の箇所には、挑戦できたかNG or 〇を書く
    - ノート欄には、心に残った言葉、出来事を残す
    - 1年ですべて埋めることを目標とする。次の1冊には消化しきれていない言葉を残す
    - 100均ノートがコンパクトでシンプル
- アポイントや会議は15分始まりにする
    - 遅刻が減らせる
    - 45分で（0分に）終わらせようとする→会議の時間が減らせる、


# 今から何をするか
- 来月初めにリーガルノート。ノートパッドを購入する。
- 目標見えるか手帳を作り2月から運用する。
初心者必見！固定値（キー、URLなど）は.envファイルに書いて再利用しよう！！

皆さんこんにちは！

今日は.envファイルについて書いていきます。

ところで皆さん、例えばバックエンドとのやり取りを行う際、URLはどういう風に書かれていますか？

```
axios.get('http://127.0.0.1')
```

こんな風に書くと思います。

ただ、これを毎回コピーして持ってくるのって正直めんどくさいかと。

また、実際にサーバーにあげる時って、``http://127.0.0.1``のようなローカルホストとは通信を行いませんよね？？？

他にも、シークレットキーなど第三者に知られてはいけない情報をファイルに直接書き込むのは良くありません。

ここで、登場するのが**env**ファイルです！

聞き覚えのある方もいれば、全く聞いたことがないという人もいます。

全く知らなくても大丈夫！

この記事を見て、.envファイルを使いこなしていきましょう！！

一度使うと恐らくやめられないくらい便利なので、ぜひ見て下さい！

それでは順を追って説明しています。

#.envと.env.productionの作成#

プロジェクト直下に``.env``と``.env.production``を作成します。

>project/
    ┣ public/
    ┣ src/
    .env
    .env.produnction

こんな感じで作ります。

```
copy nul .env
copy nul .env.production
```

Macの方は``touch``で作成してください。

また、コマンドプロンプトでの作業に慣れてない方は、手動で作成してもOKです。

#固定値の設定#

次に、固定値を以下のように定めます。

```/.env
VUE_APP_BACKEND_SITE_URL = 'http://127.0.0.1'
```

```/.env.production
VUE_APP_BACKEND_SITE_URL = 'https://example.com'
```

また、ビルドした際に``.env.production``を参照できるように``package.json``の``build``に``--mode production``を追加します。

```package.json
"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --mode production",
}
```

ローカルサーバーを立ち上げてる人は一旦止めて下さい。

止めないと、.envファイルは更新されません。

名前を付けるときは、``VUE_APP``から必ず始めて下さい！！！

そして、これを実際に呼んでみたいと思います。

```index.js
axios.get(process.env.VUE_APP_BACKEND_SITE_URL).then(() => {})
```

``process.env``で始め、先ほど設定したキー名を付けます。

これで、ローカル環境の時は``http://127.0.0.1``がコールされ、実際のサーバーでは``https://example.com``がコールされます。

他にも、Saasを利用する際のAPIキーなどもここに保管しておくことが重要です。

簡単かつ作業効率もぐっと上がります！

また、セキュリティ面でも活躍するのでどんどん使ってください！！！

以上、「初心者必見！固定値（キー、URLなど）は.envファイルに書いて再利用しよう！！」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
【Chrome拡張機能】Chromeのズーム設定は拡張機能にも影響する

# はじめに
こんにちは、うめちゃんです。
先日、好きなサイトの閲覧履歴を作成できる拡張機能、[Custome Browsing History](https://chrome.google.com/webstore/detail/custom-browsing-hisotry/dklbojjfbmaonbdcgiabhfdindoppbko)をリリースしました。

リリース後にユーザー様から指摘いただいた謎の挙動に悩まされたのでその内容を共有します。

# ポップアップが指定のサイズにならない
Chrome拡張機能の縦*横の最大サイズは800px*600pxと決まっています。
私の拡張機能ではこれを最大限利用したいと思いbodyのwidthに800px, heightに600pxを指定していました。
このサイズのポップアップでスクロールしないようにコンテンツを配置するようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136368/ca0c9db2-b4c3-0ae7-1906-017bd715dc1d.png)

しかし、あるユーザー様からこのような指摘をいただきました。
「コンテンツがポップアップ外にはみ出して見づらい」
私の環境では正常に表示されているのですが、こちらのユーザー様の環境ではどうやらそうではないらしいのです。
試しにデベロッパーツールを使ってポップアップのサイズが幾つになっているのか確認していただきました。
すると、bodyは指定通りwidth:800px, height:600pxだったのですが、htmlがwidth:640px, height:600pxとポップアップの最大サイズになっていなかったのです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136368/42b73fb5-3cec-a38a-e9f6-a3e316cd5f39.png)

何故、このユーザー様の環境だけこのようなサイズで表示されたのでしょうか。
手元で再現できないため、ユーザー様に色々と環境周りをヒアリングしていきました。
その結果、、、

# Chromeのズーム設定が原因と判明
なんと、Chormeの設定画面で変更できるズーム設定の値をユーザー様は125%にしており、これが原因でコンテンツがポップアップ外にはみ出ていることが分かりました。
どういうことか、図で説明します。

今回は説明を簡略化するために、ズーム設定を200%に設定した例で説明します。
まず、下記の図は拡張機能のポップアップのサイズを表しています。
![無題の図形描画 (4).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136368/9de8dc10-df41-9394-c097-f2daaa44e681.jpeg)

このポップアップをChromeのズーム設定100%で表示した場合はこのようになります。
100%なのでポップアップのサイズ通りにコンテンツが表示されます。
![無題の図形描画 (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136368/69cec5dd-f51b-16e8-18a4-7c37259fcb54.jpeg)

これをズーム設定200%にするとどうなるか。
答えは下記の図のようになります。
![無題の図形描画 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136368/566982af-a90e-293f-13ba-abfca4672c19.jpeg)

ズーム設定を200%にすると、ポップアップの表示可能領域が元のサイズの1/2になります。
1/2のサイズの中に元のサイズ800px*600pxを表示しようとするため、コンテンツがポップアップ外にはみ出ることになります。

# 対策
これを回避するには、コンテンツ幅をサイズ指定ではなく比率で設定する必要があります。
比率で指定することで、表示領域の変化に合わせて柔軟にコンテンツ幅を変えることができます。
【ReactNative】push通知のスケジュール設定で使う、Cron形式(firebase)とは？

ReactNative（Expo）の開発で、push通知を実装する際に迷ったのでメモ。


以下が Cloud Functionsのスケジュール設定の構文

```index.ts
exports.scheduledFunctionCrontab = functions.pubsub.schedule('5 11 * * *')
  .timeZone('America/New_York') // Users can choose timezone - default is America/Los_Angeles
  .onRun((context) => {
  console.log('This will be run every day at 11:05 AM Eastern!');
  return null;
});
```
(Firebase公式)
https://firebase.google.com/docs/functions/schedule-functions?hl=ja



``('5 11 * * *')``がCron(クーロン)形式と呼ばれるfirebaseのスケジュール設定の記法。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692830/36c364b8-c0c6-4173-7bd8-37537d005e39.png)

(GoogleCloud公式)
https://cloud.google.com/scheduler/docs/configuring/cron-job-schedules?hl=ja

初見の時は迷いました:cold_sweat:
ではでは。
担当者一人のIT部署が高確率で破綻する理由

#タイトルの通り
担当者一人のIT部署は高確率で破綻する。
ドキュメントは完璧、ソースコードもきれいに整備されている。それでも破綻する確率は高い。なぜか？それは現場のノウハウが担当者の中にしかないからだ。
この１点に尽きる。
#例えば
担当者が交通事故で亡くなったとしよう。これはもう引継ぎもくそもない。現存する資料とソースコードだけがすべてだ。代わりに採用された担当者があるがままの資産で仕事ができればいいが、そこは期待できない。資料が整備され、ソースコードが読めたとしても、現場のノウハウを持っているのは元の担当者ただ一人である。交通事故という極端なケースではないとしても、担当者が退職する時にそれまでのノウハウを短い期間で引き継ぐのは事実上不可能だ。この「ノウハウ」と呼んでいる部分は対人関係や過去の業務履歴が含まれる。
#一人退職したくらいではびくともしない部署にするために
ノウハウの共有と、担当者Aができることは担当者Bもできるようにすること。つまり担当者は複数いなければ業務の継続性は危ういということだ。担当が複数いてお互いに同じことができること。誰かが不測の事態に陥っても仕事が回るためには、複数いることが絶対条件である。
#ノウハウは言語化しにくい
個人が持つノウハウというものは、言語化したり文書化しておくのは難しい。手順が決まっていることを手順書にするくらいなら簡単だが、状況にあわせてこういう時はこうする、といった属人的な判断が必要な部分は、他人に伝わる形では残しにくいからだ。そういうことは経験の中で培われ記憶していくものである。まあ別に担当レベルで所属会社の将来を憂いてやる義理も責任もないのだが、そういう義理や責任を感じる人は最低でも2人以上の体制にするよう上司に掛け合ってみる価値はある。
#ただし
担当者一人の部署ということは、行っている業務がどれだけ重要であるかに関係なく、人件費をかけたくない経営的な意思が働いている可能性が高い。属人的なノウハウの価値をどう見るかにもよるが、そもそもそういう価値の重要性がわかっていれば、担当者一人などという体制はあり得ない。よって一人体制を肯定する組織であるならば、将来その部署が破綻する可能性は低くない。１つの部署だけで済む話ならいいのだが、多部門にまたがる仕事をしているケースでは、アクシデント１つで企業がマヒしてしまう可能性がある。
#結論
- ノウハウを甘く見ない
- 属人的な情報は複数人で日々の業務を通じて共有する
- 文書化可能なノウハウはできるだけ文書に起こす
複数枚のHEIC画像をまとめて一つのPDFファイルに変換する(Python)

##概要
iPhoneで撮影した授業の板書の画像にgoodnotes5で書き込みをしたい。
しかも、一つの科目につき複数枚の写真を撮るのでそれらは一つのノートにまとめたい。

iPhoneからMacにAirdropをしたときに、その画像形式を見ると.HEICという（謎）拡張子が使われていた。
.HEICを.jpegに変換し、goodnotes5で扱えるように全ての画像をpdf形式に変換しまとめる。

input)
複数のHEIC画像が入っているフォルダー

output)
全てのHEIC画像が含まれている一つのpdfファイル

##0)pipする
```.sh
pip install img2pdf
```
他に使用するライブラリは全て標準ライブラリ(のはず)

##1)関数を定義

```.py
import glob
import subprocess
import os
import img2pdf

def HeicToPdf(image_dir,output_pdf_name):
    if image_dir[-1]!='/':
        image_dir=image_dir+'/'
    output_pdf_path=image_dir+output_pdf_name
    jpg_path=image_dir+'jpg_dir'
    os.makedirs(jpg_path,exist_ok=True)
    files = glob.glob(image_dir+"*.HEIC")
    files = sorted(files)
    for file in files:
        jpg_file=file.replace(image_dir,jpg_path+"/")
        command = 'sips -s format jpeg ' + file +  ' --out ' + jpg_file.replace('.HEIC','.jpeg')
        subprocess.call(command, shell=True)
    files=[]
    files = glob.glob(jpg_path+"/*.jpeg")
    files = sorted(files)
    with open(output_pdf_path,"wb") as f:
        f.write(img2pdf.convert([str(i) for i in files]))
    print("Done")
```

##2)関数を使用する

```.py
HeicToPdf("/Users/example_heic_dir","example_output.pdf")
```

##3)参考文献
1)Pythonを使ってHEICファイルをjpegに変換する
https://qiita.com/as-chapa/items/c3af6ab6ea4ce8349a90
2)pythonで複数画像をPDFファイルに変換する
https://qiita.com/meznat/items/31d947ed4826350fd9fa
3)Macのターミナルで簡単に画像処理できるsipsの使い方
https://qiita.com/livlea/items/53b755e5067d4ebc5b43
4)subprocessについてより深く（3系，更新版）
https://qiita.com/HidKamiya/items/e192a55371a2961ca8a4
「Undifined method 'upload' for nil:NilClass」エラーの対処

# 概要

Active Storageを利用する際に、「Undifined method 'upload' for nil:NilClass」エラーが出る。

# 状況
1. rails version -5.2.2.4でアプリケーションを作成
2. ActiveStorageをインストール
3. Model, Controller, Viewファイル作成
4. ブラウザでファイルのアップデートを実行すると、概要のエラーが発生

# 解決策
https://qiita.com/NaokiIshimura/items/c8aa4d55cb653ff0501a

こちらの記事と全く同じ症状であることが発覚。
同様の対処法で解決した。
モーダルウィンドウ表示

前回の続きです。
PHPでログイン機能：https://qiita.com/x49_n/items/07b80a1e88c483f7256a
#予定入力欄作成
予定を入れたい日を選択すると、モーダルウィンドウが表示され予定を記入できるようにしたい。
前回作成したカレンダーのクリックイベント（jQuery）に追加します。

```javascript:cal_script.js
$(function() {
  $("td").on("click", function() {
  //  選択部分の色変更
    $("td").removeClass("select");
    $(this).addClass("select");
  //  tdの値(日にち)を取得し出力
    $("#select_day").text($(this).text());
  //  スケジュール記入欄表示
    $('#plan-modal').fadeIn();
  });
  // 閉じるボタン
  $('.close-modal').on("click", function() {
    $('#plan-modal').fadeOut();
  });
  });

```
動作確認問題なしッッ！！
入力した内容もDBに登録されていたのでOKです！


![modal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934823/6ce71781-3915-10d6-d958-9bb51c784d96.gif)
流れをGIF画像で作成してみました！
GIF画像を初めて作成しましたが簡単でしたね。
【課題】PowerShellに触れる

#背景
久しぶりの投稿。なんちゃってSEの私に、冬休みの課題が舞い降りた。
業務を効率化するためにも、PowerShellを知りたい私に
鬼教官が課題を提示してきたのであった。
まともにプログラムに触れたことのない、私の戦いが今始まる。

#これまでのPowerShell経験
・簡単なファイル操作ができる。
・簡単な画面を作れる。
・DLLのメソッドをPowerShell経由で実行することができる。
・XMLの要素を特定の数字・文字に置換できる。

#課題
・PowerShellでIE画面の内容を出力する。
・PowerShellで別PCのIE画面の内容を出力する。
・PowerShellで別PCのIE画面を操作する。
・PowerShellで別PCのIE画面を起動する。
・PowerShellでEdge画面を操作する。

#感想
IE画面の情報取得とかプログラム作ったことないよ！
PowerShellで遠隔操作！？どうすんの！？
別PC・サーバとかないんだけど！？買えってこと！？
（落ち着けおれ）

#今後
課題を1つずつ解いていくよ。
できたらアップしていきます。（自己満）
いろんな記事参考にさせてもらいます。
緯度・経度を指定してApple標準マップアプリを起動する

## やりたいこと
指定の緯度・経度の場所を中心とした状態で、Apple標準マップアプリを起動したい。

## 実装方法


Apple標準マップアプリを開きたい場所で下記のコードを実行。
この例では、東経135度、北緯35度を中心として表示する。
zの値を変更すると、縮尺を変更できる。

```swift:OpenAppleMapApp.swift

let url=URL(string: "http://maps.apple.com/?q=35.0000,135.0000&z=14")!
UIApplication.shared.open(url, options: [:], completionHandler: nil)
```

## 動作確認環境

Xcode: 12.2
Swift: 5.3.1
iOS: 14.2
React実行エラー備忘録1 : React Hook "useState" is called in function...

# 概要

React アプリを開発する上で発生したエラーの原因と対策を忘れないためのメモです。

### 状況

某商品紹介用の Web アプリ開発中に発生

### エラー

```
> React Hook "useState" is called in function "productEdit" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter     react-hooks/rules-of-hooksx
```

### コード

```javascript
const productEdit = () => {

  const [name, setName] = useState(""),
        [description, setDescription] = useState(""),
        [category, setCategory] = useState(""),
        [gender, setGender] = useState(""),
        [price, setPrice] = useState("");

  const inputName = useCallback((event) => {
    setName(event.target.value)
  },[setName])
  const inputDescription = useCallback((event) => {
    setDescription(event.target.value)
  },[setDescription])
  const inputPrice = useCallback((event) => {
    setPrice(event.target.value)
  },[setPrice])
```

### 原因

関数名の 1 文字目を小文字にしていたこと

### 対策

"productEdit"を"ProductEdit"にすることで解消
Q18.[Forensic]leaf in forestをPythonで解いてみる

##Q18.[Forensic]leaf in forest
>このファイルの中にはフラグがあります。探してください。
>フラグはすべて小文字です！ 

CpawCTFのQ18を解いてみたので解法と
Pythonを使った特定文字列削除のメモです


###1.ファイルを調べてみる
とりあえず指定のファイルをfileコマンドで見てみる

```
root@kali:/home/kuratsuka/Documents# file misc100 
misc100: pcap capture file, microsecond ts (little-endian) - version 0.0 (linktype#1768711542, capture length 1869357413)
```

pcapって書いてあるから拡張子をpcapにしてwiresharkで開こうとしたらエラーが出た、よくわからん

中身をcatで見てみると・・・
![lovelive.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517314/f1aee7e3-7651-c7a7-3f8e-eccefd45d3e1.jpeg)

すごい勢いで「lovelive!」って出力される
レベル1でごちうさは神って問題もあったよね、あぁ^～ターミナルがぴょんぴょんするんじゃぁ^～

すごい文字量に圧倒されるけどスクロールしてみると所々に大文字が配置されている

問題名にもあったように木を隠すなら森の中でFLAGがこのラブライブ！の向う側にあるのだろう

###Pythonで指定文字列を消す
問題文にある"フラグはすべて小文字です！ "から、隠されている大文字を抽出して小文字に変換すれば大丈夫なはず
テキストファイルに文字列をコピーして下記コードで実行してみる

```python
f = open('C:/Users/kuratsuka/Desktop/misc100.txt')
data = f.read()
print(data.replace('lovelive!',''))
```

>Pythonよくわからなくてread()を書かなかったら「io.TextIOWrapper」でエラー吐かれた、よくわからんが動くからヨシ！

結果としてはこれ

```
ﾔﾃｲ｡       ％e!CCCelive!lovelivPPPovelive!loveAAAe!lovWWWve!{{{elive!loveliMMMelive!lovelGGG!lovelivRRRovelive!lEEElive!P
PPelive!}}}
```

ﾔﾃｲ・・・！
だいぶ削れたけどもう少し削りたいので'love'と'live!'に分けてみる


```python
f = open('C:/Users/kuratsuka/Desktop/misc100.txt')
data = f
data =data.replace('love','')
print(data.replace('live!',''))
```

結果はこちら

```
ﾔﾃｲ｡       ％e!CCCelivPPPoveAAAe!lovWWWve!{{{eliMMMelGGG!livRRRovelEEEPPPe}}}
```

・・・・
これはもうゴールしていいんじゃないか？？



##re.sub()を使ってもう少しだけきれいにする

わかる・・・フラグは分かるんだけれど・・・
もう少しだけきれいにしたい・・・
大文字抽出するのもあるんだろうけど、ここでは文字の削除の方向で解いてみる
replace()だと指定の文字列しか消せないらしくre.sub()使うと範囲内の文字列を消すことができるらしいので試してみる

```python
import re
f = open('C:/Users/kuratsuka/Desktop/misc100.txt')
data = f.read()
data = re.sub('[a-z,!]',"",data) #a-zと!を削除
print(data)
```
これで実行してみると・・・・

```
ﾔﾃｲ｡       ％CCCPPPAAAWWW{{{MMMGGGRRREEEPPP}}}
```
だいぶキレイになった！
緯度・経度を指定してGoogleMapアプリを起動する

## やりたいこと
指定の緯度・経度の場所を中心とした状態で、GoogleMapアプリを起動したい。

## 実装方法

Info.plistに以下のエントリを追加する。
これをやっておかないと、iOS10以降(iOS9だったかも?)以降ではアプリを開けない。

```xml:Info.plist
	<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>comgooglemaps</string>
	</array>
```


GoogleMapアプリを開きたい場所で下記のコードを実行。
この例では、東経135度、北緯35度を中心として表示する。
zoomの値を変更すると、縮尺を変更できる。

```swift:OpenGoogleMapApp.swift

let url=URL(string: "comgooglemaps://?q=35.0000,135.0000&mapmode=standard&zoom=14")!

if UIApplication.shared.canOpenURL(comgooglemapsUrl) {
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
    print("Google Map App is not installed.")
}
```

## 動作確認環境

Xcode: 12.2
Swift: 5.3.1
iOS: 14.2
FlywayMigrateでverifyをスキップ

備忘録です。

##　直面した問題

あるトピックブランチでmigrateファイルを作ったのち、それがメインブランチにマージされる前に他のトピックブランチを切って別件の作業をはじめました。DBは共有です（それもまあ問題なんですが）。

そちらでもデータ投入が必要だったため、以下の通りバージョンを飛ばして上げたmigrateファイルを作成したものの、うまくいかないだろうなーと思いながら`FlywayMigrate`を実行したら無事死亡（チーン）。


* V_3.2__xxx.sql
* // 3.3は別のトピックブランチで欠番
* V_3.4__xxx.sql <- 作った


やはりというか3.3がないので怒られます。

## 解決法

実行時のJVMオプションで`-Dflyway.validateOnMigrate=false`を指定。
未経験から応用情報技術者に合格する！(3)午後問題対策編

#はじめに
過去２回では応用情報技術者試験の概要と、午前問題の対策をお伝えしてきました。ここからは午後問題の対策についてお伝えしていきます！

#午後問題はどんな内容？
まず、応用情報技術者試験の午後問題のルールです。午後問題は選択、記述両方の問題が含まれます。11問あり、セキュリティ対策については必ず回答する必要がありますが、残り10問のうち、回答が必要なのは4問のみです。もちろん1問に小問が複数出題されます。各大問20点満点であり、最終的に60点以上獲得すれば合格となります。

ただし、気をつけなければならないこととして、1つは午前問題で60点以上獲得しないと採点すらされません。また午後問題は大問1つあたりの配点はそれぞれ決められていますが、それぞれの小問の配点は公表されていませんし、試験終了後の採点時に採点率に応じて変動するそうです。なのでどこまで正解すれば合格できるのか、不透明な部分があります。ちなみに僕が合格した時は60点ぴったりだったのですが、どう採点されてそうなったのか、いまだに謎です。

#必須問題の対策方法
まずは午後問題の1問目であり、必須回答であるセキュリティに関する問題からです。この問題については、最近はネットワークから出題されるのがやはりほとんどです。特にネットワーク構成が提示されるパターンが多いです。またこの問題は記述問題があることを除けば、基本情報技術者と難度や形式はそう変わらないように思います。（なんなら、僕が受験した時は基本情報技術者の方が難しく感じることが多々ありました）
それぞれの過去問を対策すればかなりの問題数を抑えられると思うので、類題に対処できると思います。ちなみに午前問題と違ってほとんど同じ問題は出題されませんが、類題や、ほぼ同じことを聞いている問題は多くあると思います。

またセキュリティに関する用語(攻撃方法など・・・）は記述問題で出題されることが多いので、午前問題の過去問からも対策はできると思います。
また文章で筆記する問題は他の問題でも同じですが、冷静に問題文を読めば正解に近いことが書いてあることも多いので、確実に正解に近づきたいですね。

#残りの4問、何を選択する？
残りの4問何を答えるかという点に移ります。未経験からするとテクノロジ系はかなり難関で、プログラミングやネットワーク、データベースなんかはほぼ不可能なレベルなので、当然ストラテジ系やマネジメント系の問題を選択することになります。個人的にプロジェクトマネジメントは記述問題が多いですが、知識よりも文章を読んで、当たり前の解決策をかけば正解できるという問題が多いのでおすすめです。ついで経営戦略、システム監査の問題は一部知識が必要な物も多いですが午前問題の対策で間に合うものが多いのと、プロジェクトマネジメント系の問題と同じく、文章を読めば答えられる問題が多いと思います。

#もう1問は何を選ぶか・・・
もう1問何を答えるかという点です。サービスマネジメントの問題は専門用語が多く、実際に働いている人でないと難しい問題も時にあります。僕は最終的にサービスマネジメントを選びましたが、この問題が難しいと思った時は、テクノロジ系でも組み込みシステム開発がお勧めできるかもしれません。問題のパターンがあまり多くなく、計算問題も午前問題の計算問題と近い形で回答で切るので、サービスマネジメントの問題が難しいと感じたらこちらを選ぶのもありかもしれません。事前にこの問題も対策しておくのもありですね。
システムアーキテクチャの問題も、身近に利用できるような物がテーマの場合案外解けることがあります。試験開始時にまずはざっと目を通してみるのもありだと思います。ただし試験時間は150分ですし、それぞれの問題の文章が長く、マネジメント系は文章の把握がかなり大事になるので問題選びに時間をかけすぎないことが大切です。

#おわりに
3回に渡って応用情報技術者試験について記載してきました。この資格を未経験のエンジニアが取得することで、就職に有利になるかどうか、それはまだなんとも言えませんが、とりあえず資格が欲しい人、また職務上取る必要がある人などの参考になれば幸いです。
きっとgit使えないとbad③

#はじめに
引き続き、少しずつ調べて実践しているけど、細かいところがわからないし、ミスったらどうしようという不安を感じながらコマンドを入力している、今日この頃です。

↓前回までの投稿
[きっとgit使えないとbad
](https://qiita.com/TerToEer_sho/items/8e5f9294c8d0cf936207)[きっとgit使えないとbad②
](https://qiita.com/TerToEer_sho/items/6dc482f12b1e261ed3f4)

##リモートの変更をローカルに反映させる
```bash
% git pull
```
##取り消す系
###addを取り消す

```bash

% git add reset
```


###特定のaddを取り消す
```bash

% git add reset ファイル名（pathで指定）
```

###直前のコミットメッセージを修正する
```bash
% git commit --amend "修正後のメッセージ"
```
gRPC command line toolをAlpine Linuxでビルドする

# はじめに

デバッグ目的でgrpc_cliをalpineに入れたくてやったらわりと手こずりました。必要なパッケージ見つけるのにけっこう時間がかかったのでメモっておきます。

grpc_cliのセットアップドキュメントは公式のこちらを参考にしました。

https://github.com/grpc/grpc/blob/1f670397ce7f8a12dfb1fb32d8857b2233022856/doc/command_line_tool.md

# ビルドする

alpineにログインする

```shell
docker pull alpine:3.13.0
docker run --name alpine-test -itd alpine:3.13.0 /bin/ash
docker exec -it alpine-test /bin/ash
```

grpcをクローンしてgrpc_cliをビルドする

```shell
apk add --update git cmake make clang build-base llvm-static llvm-dev clang-static clang-dev linux-headers
git clone https://github.com/grpc/grpc
cd grpc
git submodule update --init
mkdir -p cmake/build
cd cmake/build
cmake -DgRPC_BUILD_TESTS=ON ../..
make grpc_cli
```

実行する

```shell
./grpc_cli --helpfull
grpc_cli: Warning: SetProgramUsageMessage() never called

  Flags from root/grpc/test/cpp/util/cli_credentials.cc:
    --call_creds (Call credentials to use: none (default), or
      access_token=<token>. If provided, the call creds are composited on top of
      channel creds.); default: "";
    --channel_creds_type (The channel creds type: insecure, ssl, gdc (Google
      Default Credentials), alts, or local.); default: "";
    --local_connect_type (The type of local connections for which local channel
      credentials will be applied. Should be local_tcp or uds.);
...
```

# おわりに

alpineに入ってどうこうするってノウハウわりと探してもないものですね。ググり力が低いのか。。
sedで改行を追加できなかったのでcatとechoで対応した話

# 概要  
sedコマンドで先頭行に文字列と改行を追加しようとしたところ、改行がどうしても追加できなかったのでcatとechoコマンドで対応した時の方法です。  

# sedコマンドで実行しようとしたこと  
```
sed -i '' -e '1s/^/追加文字列\n/' (ファイルパス)
```
上記では文字列は追加できるが、改行だけ改行として認識されず、nが出力されてしまう。  

# catとechoで対応した方法  
```
# catコマンドで変数にファイルの内容を入れる  
$C=cat (ファイルパス)  

# echoコマンドで挿入したい文字列と$Cを連結させてファイルに入れる
echo "追加テキスト\n${C}" >> (ファイルパス)
```

# まとめ  
sedコマンドで改行を挿入する方法として、gnu-sedを入れるなどの方法があったが、うまく使いこなせなかったのでもう少し調査をしようと思います。
量子ゲート実機で回路深さの限界を調べる (その2)

# 量子ゲート実機で回路深さの限界を調べる
前回の記事
[量子ゲート実機で回路深さの限界を調べる](https://qiita.com/notori48/items/42e635d2c8eabe86fbea)
で、量子ゲート実機における回路の深さを調べました。その際はXゲートとCNOTゲートだけでしたが、
今回はもう少し色々と調べてみます。

# 量子コンピューターの"native"ゲート
量子コンピューター実機には、各実機毎にnative gate (basis gate ともいう) というものが設定されています。
これは実機のHWで実行可能なゲート（と思います）であり、
量子回路を記述した場合、transpileによってこの　native gate に変換されてから実行されています。[^1]

ibmqx2のnative gateを見てみます。

```python
  backend = provider.get_backend('ibmqx2')
config = backend.configuration()
print('basis gate is {0}, sampling period = {1}'.format(config.basis_gates, config.dt))
```

`basis gate is ['id', 'rz', 'sx', 'x', 'cx'], sampling period = 2.2222222222222221e-10`

ということで、native gate はid(単位行列), rz(z軸回り回転), sx (√X), X, cx(=CNOT) です。
sxってなんじゃ？　ですが、量子ゲートの教科書ではゲートの分解でちょこちょこ出てきます。(Vと書かれることもあります）

# native gate 実行における深さと忠実度の関係

今回、ゲートが「どの程度うまくいったのか」をfidelity (忠実度）で表すことにしました。
fidelityは0以上1以下の値を取ります。（要は内積です）
忠実度を計算するには本来は状態ベクトルが必要でしょうが、今回は$Z$基底で測定した結果が期待と同じだった割合で定義します。
今回、単一ゲートについては $16$の倍数、CNOTゲートについては$2$の倍数つなげて実行することで、出力が"0"あるいは"00"となるようにしています。shotsは1024です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/12db4619-448f-4061-e58e-63a0510b8158.png)

(Hゲートはnative gate ではないので、3つのnative gate に分解されています)


青線が実験結果、黒線はワーストケース（ランダム出力の場合）に相当します。

ゲートによって全然挙動が違っており、驚きました。
なかなか考察が難しいです。

- 明らかにCNOTは単一ゲートの10倍ぐらいは厳しそうだということは見て取れます。
- Rzゲートはかなりロバストに見えます。本当でしょうか？
- √XやCNOTでは振動している様子が見えます。

## 追記(20210127)

雑音ありシミュレーターでもやってみました。
いちおう、実機のノイズをモデル化しているそうなのですが・・・

```python
  noisy_simulator = QasmSimulator.from_backend(provider.get_backend('ibmqx2'))
  results = execute(circs,backend=noisy_simulator).result()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/5667b3c3-07d7-ea4f-c2f3-c6cb77e8a548.png)

良く見え過ぎではないでしょうか？
これではあまり参考にならないような。

# 結論

よくわからなかった！
でも面白い結果ですね。
ゲートの挙動については、Qiskit pulse の機能で色々勉強できるようです。
Qiskit pulse では、勝手に新しい(native ?) gateを作れるらしいです。

[^1]: execute コマンドで回路実行した場合も、内部でtranspileを行っています。ちなみにtranspileせずに無理やり実行しようとすると、native gateのみの回路はそのまま通り、native gate 以外が含まれているとエラーで止まります。
【Rails入門】検索機能の作成方法

Ruby on Railsで検索機能の作成方法を記載していきます。
ここでは、レシピ検索のため、入力したキーワードに該当するレシピを一覧表示できるようにします。

#作成手順
1. 検索フォームの作成
2. ルーティング設定
3. モデルにsearchメソッド定義
4. コントローラーにsearchアクション定義
5. ビューで検索結果表示画面を作成

#1. 検索フォームの作成

```ruby
<%= form_with(url: search_recipes_path, method: :get, local: true) do |f| %>
  <%= f.text_field :keyword, placeholder: "レシピ検索", class: "form-control" %>
  <%= f.submit "Search" , class: "btn btn-outline-light" %>
<% end %>
```
######form_with
urlにはこの後ルーティングで設定するsearchのパスを記載します。
ポイントは、methodをgetにすることです。
`local: true`に関しては以下の記事をご覧ください。
https://qiita.com/kmjooh/items/c533b2f72a2f3e5a29a9

#2. ルーティング設定

```ruby:routes.rb
resources :recipes do
  collection do
    get 'search'
  end
end
```
今回はrecipesテーブル内のtitleカラムに該当するレシピを表示するため、recipesコントローラー内にsearchアクション設定します。
生成されるルーティングにidが付かない場合は、`collection do`を使用します。
（idが付く場合は、`member do`を使用します。）

#3. モデルにsearchメソッド定義
```ruby:recipes.rb
class Recipe < ApplicationRecord
  
  def self.search(search)
    if search
      Recipe.where('title LIKE (?)', "%#{search}%")
    else
      Recipe.all
    end
  end
end
```
selfはモデルのRecipe自身です。
ここではwhereメソッドとLIKE句を使用して、検索機能を設定しています。
if文を使用して、titleカラムに`%#{search}%`が該当するRecipeモデルのデータを読み込めるようにしています。該当するデータがない場合は、`Recipe.all`で全てのデータが読み込まれるようになっています。


#4. コントローラーにsearchアクション定義
```ruby:recipes_controller.rb
def search
  @recipes = Recipe.search(params[:keyword])
end
```
ここで記載している`Recipe.search(params[:keyword])`が上記モデル記載の`self.search(search)`に対応しています。
引数のsearchは`params[:keyword]`であり、このkeywordが検索フォーム用のビューに記載の`f.text_field`のname属性のkeywordとなり、入力したキーワードで検索できるようになっています。

#5. ビューで検索結果表示画面を作成
```ruby:recipes/search.html.erb
<% @recipes.each do |recipe| %>
  <%= image_tag recipe.image.url %>
  <%= recipe.title %>
<% end %>
```
`image`と`title`はRecipeモデルのカラムであり、今回は検索結果を一覧表示したいため、`<% @recipes.each do |recipe| %>`で繰り返しを行っています。


以上となります。
補足情報などありましたら、是非コメントお願いします！

#参考
https://qiita.com/yoshi_4/items/71d8b030abf44d70e877
https://qiita.com/mochikichi321/items/5c9630c5d87b47130942
https://qiita.com/yusuko/items/cff4e46aeafbc3beecf2
【Swift】オプショナル超超超入門

swift のオプショナルに苦戦した初心者が調べてまとめたものです。


# オプショナルって何

値が存在しない変数を宣言するときに使うデータ型を**オプショナル**という。

#### 変数のデフォルト値がないとき

```swift
var dinner: String
print(dinner)
```

変数 `dinner` が宣言されているが、空っぽの状態 `nil` のためエラーが発生する。

```swift
Variable 'dinner' used before being initialized
```

変数を宣言したときにあらかじめ値を入れておけばひとまずエラーは発生しないが、宣言時には値を入れておきたくないときにオプショナルを使うとエラーを回避できる。

```swift
var dinner: String?
print(dinner)
```

型の最後に `?` を付けると、オプショナルの String として宣言される。
これにより変数 `dinner` では `nil` の状態が許容され、エラーは消える。（ただこの場合警告が表示される）

#### オプショナルに値を入れたとき

```swift
var dinner: String?
dinner = "Hamburger"
print(dinner)

// Optional("Hamburger")
```

オプショナルの変数に値を入れて出力したとき、`Optional` に包まれた状態で出力される。


# オプショナルをアンラップするには

変数 `dinner` を別の文字列に結合したいとき、例えばこのように書いたとする。

```swift
var dinner: String?
dinner = "Hamburger"
let text = "I eat a \(dinner) for dinner."
print(text)

// I eat a Optional("Hamburger") for dinner.
```

結果、変数 `dinner` の値がオプショナルに包まれている状態で出力される。

演算子で結合してみた場合、通常の String は演算子を使用してオプショナルと結合できないため、エラーが発生する。

```swift
var dinner: String?
dinner = "Hamburger"
let text = "I eat a " + dinner + " for dinner."
print(text)

// Value of optional type 'String?' must be unwrapped to a value of type 'String'
```

### 強制アンラップ

オプショナルの文字列を使用する手段として、文字列をアンラップする方法がある。
強制アンラップは、変数に値が含まれているかどうかに関係なく、名前の通り強制的にアンラップする。

```swift
var dinner: String?
dinner = "Hamburger"
let text = "I eat a " + dinner! + " for dinner."
print(text)

// I eat a Hamburger for dinner.
```

値が入っているときはアンラップされるが、もしオプショナルが `nil` だった場合はクラッシュする。

### オプショナルバインディング

値が `nil` だった場合に発生するクラッシュを回避する方法として、オプショナルバインディングが使用できる。

オプショナルバインディングは、オプショナルの値を一時的に別の変数に割り当て、条件分岐によって処理を変える。
これにより、`nil` でもクラッシュが発生しない。

```swift
var dinner: String?
if let dinnerMenu = dinner {
    let text = "I eat a " + dinnerMenu + " for dinner."
    print(text)
}
```

変数 `dinner` に値がある場合、 `dinnerMenu` に値が割り当てられる。このとき if ステートメントは `true` を返すため、ブロック内の処理が実行される。
もし `dinner` に値がない場合、 `dinnerMenu` に値が割り当てられず、if ステートメントは `false` を返すため、ブロック内の処理が実行されない。

### オプショナルチェイニング

オプショナルのメソッドやプロパティの値を取得するとき、オプショナルチェイニングを使う。
オプショナルのあとに疑問符 `？` を配置するとオプショナルチェイニングとなる。

```swift
struct dinnerMenu {
    let menu = "Hamburger"
}

var dinner: dinnerMenu?
print(dinner?.menu)

// nil
```

変数の値が空っぽのため、結果は `nil` となる。



## nil 結合演算子

変数を宣言するときに、`nil` のときに返すデフォルト値を決めておくことができる。
オプショナルに値が入っているときはアンラップし、`nil` のときはデフォルト値を返す。

```swift
var dinnerMenu: String?
let dinner = dinnerMenu ?? "variable is empty"

print(dinner)

// variable is empty
```




## nil チェック

if 文を使って、`nil` かどうか判定し処理を分岐させる方法もある。

```swift
var dinner: String?
if dinner != nil {
    print(dinner)
} else {
    print("variable is empty")
}

// variable is empty
```
mattermostが起動しない！？原因は公式最新バージョンのエラーだった！

# 立ち上がらないmattermost

slackのコピー版と言われているmattermost。slackの無料版だとスレッドが消えたりしてしまっていたので、乗り換え検討も含めて使いたくなりました。

※この記事は2021年1月26日の記事です。最新版は修正されている可能性があります。

## cannot unmarshal string into Go struct field TeamSettings.
公式に書いているコマンドをなんど実行してもdockerのステータスは```Exited (1) 26 seconds ago```のまま。。。

公式のコマンドはデーモンで起動だったので、試しに```docker run mattermost/mattermost-preview```してみました。

すると、

```
Error: failed to load configuration: unable to load on store creation: parsing error at line 109, character 42: json: cannot unmarshal string into Go struct field TeamSettings.TeamSettings.ExperimentalDefaultChannels of type []string
```

この感じだとどうやらGoのソースコードの部分でエラーを吐いています。「もしや公式のlatestバージョンが悪いのでは？」と思い始めていた最中に、こんなスレッドと出会います。
https://forum.mattermost.org/t/local-machine-setup-using-docker-not-working/11082/5

mattermost公式のフォーラムのようですが、そこでも公式のdockerが動かないという僕と全く同じ内容のエラーに遭遇している人がいました。

開発者っぽい方の返答を簡単に訳してまとめると、
> 報告ありがとう、開発チームに共有します。昔のバージョンが動いてくれて嬉しいです！今後の進捗はここのスレッドに共有します！

とのことらしいです。

今後の修正に期待です。

## Mattermost今すぐ使ってみたい。

そのスレッドによると「最新より下のバージョンは動いたよ」とのことなので、試しにlatestの前のバージョンのdockerイメージを使ってみようと思います。

```
docker run --name mattermost-preview-5-26-0 -d --publish 8065:8065 --add-host dockerhost:127.0.0.1 mattermost/mattermost-preview:5.26.0
```

dockerイメージのローカル名を```mattermost-preview-5-26-0```に（適当です）、後半部分のpullしてくるdockerイメージをバージョン指定してあげてインストールします。

localhost:8065にアクセスすると、、、

![スクリーンショット 2021-01-25 19.34.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269844/7a2e3248-9b4b-8e5c-b5fc-4970697c120d.png)


ぱっぱらー🎉

立ち上がりました。

いままでの苦労はなんだったのかと思うくらいあっさり立ち上がります。😂


## mattermost使ってみてね

いまのところ容量気にせず使えるslackな印象です😊

今度awsにアップしてチームメンバーが使えるようにしようかなと思ってます。

ぜひ使ってみてね！
Hello Dollyはただのプラグインではないのか検証してみた

#Hello Dollyとは
おそらくWordPressでもっとも知名度の高い、プラグイン。
**[”Hello Dolly”](https://ja.wordpress.org/plugins/hello-dolly/)**
このプラグインはWordPressをダウンロードすると初期でインストールされている。
有効化するかしないか・・・むしろ削除していいのか。
頭を抱えたことがある人もいるかも知れない。

ある先生に面白いよと言われ興味をもったのが今回の記事の発端です。

プラグインの詳細にはこう書かれている。
>”This is not just a plugin”  *これはただのプラグインではない*

ということで、プラグインのファイルを覗いてみた。

##hello.php
プラグインを構成するデータはhello.phpのみ。
とてもシンプル。
変数にHello Dollyの歌詞を代入し、ランダムで取り出し、それを管理画面に出力する。
アクションはもちろんだが、ダッシュボードでのheadにCSSを適用するための関数など、
WordPressプラグインを作成するためのヒントがたくさんある。
一部紹介します。

###wptexturize()関数

>```php
return wptexturize( $lyrics[ mt_rand( 0, count( $lyrics ) - 1 ) ] );
```

ランダムに配列のindexを決定し、配列の要素を取り出す。
wptexturize()というwp関数を使用し文字を変換したものを返り値にしている。

###admin_notices関数（アクション）

>```php
add_action( 'admin_notices', 'hello_dolly' );
```

admin_noticesは管理画面を表示する際に実行されるアクションである。
なので管理画面を表示した際、定義したhello_dolly()が呼び出される。
そしてランダムで抽出した歌詞の一部が管理画面上に表示される仕組み。

add_action()は言わずもながwordpessシステムの関数にアクションを追加する関数。

###admin_head関数（アクション）
>```php
add_action( 'admin_head', 'dolly_css' );
```

admin_head関数（アクション）は管理画面のHTMLのheadタグ内に出力することができる。
dolly_css()の中ではstyleタグでcssが記載されている。

##ちょっと改変してみた
どんなプラグインなのか理解したところでちょっとカスタマイズしてみた。
そう、歌詞をお気に入りの曲にしました。
![2021-01-26 21.56.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986728/c8b5cda5-b30b-eb4c-56e2-28a986865d86.png)

##作ってみた
せっかくなのでサクッと先程の関数を利用しプラグインを作ってみた。
インスタントラーメン並みにできたプラグインがこちら、
![スクリーンショット 2021-01-26 23.25.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986728/3bf30f50-a313-1cc7-cccc-c4ecb4277ace.png)

![スクリーンショット 2021-01-26 23.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986728/0166aea9-555f-0369-092e-f44b104ed5d0.png)
このように管理画面上部に文字を出力するプラグインです。

```php
<?php
/*
Plugin Name: notices
Plugin URI: 
Description: 管理画面に注釈を入れます
Author: plammm9
Version: 1.0
Author URI: https://yukari-portfolio.work
*/

function notices() {
    ?>
    <p>これはテストサイトです</p>
<?php
}

add_action('admin_notices','notices');

?>
```

#まとめ
結論は削除してしまってもいいプラグインです。
ですがすこーし自分好みにカスタマイズするとほっこりします。
また、初学者のプラグイン作成やwp関数のお勉強にはちょうどいいんではないでしょうか。
一部のみの抜粋のため気になる方はファイルを覗いてみてね。

そう考えると「ただのプラグイン」ではないですね。
【Rails】通知機能

#はじめに
お店のWebサイトを作成し、お客様がお問い合わせを投稿し管理者側のヘッダーに新規お問い合わせがあれば通知のマークが付くようにしました。
お問い合わせ一覧を見ると通知マークは消えます。

#完成イメージ
![スクリーンショット 2020-12-23 14.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973512/c84eb46c-a53b-6dd0-fd83-7aa2085a34e2.png)

#通知のモデルを作成
お問い合わせ機能(contact)は実装済み前提で進めさせて頂きます。

```
$ rails g model Notification contact_id:integer checked:boolean
```

```ruby:db/migrate/..._create_notifications.rb
class CreateNotifications < ActiveRecord::Migration[5.2]
  def change
    create_table :notifications do |t|
      t.integer :contact_id
      t.boolean :checked, default: false, null: false #追記

      t.timestamps
    end
  end
end
```

checkedカラムにdefault: false,null: falseを追記します。
意味合いとして、通知を確認したかどうかの初期値は、false（通知未確認）に。また、null: falseで指定したカラムが空で保存されるのを防ぎます。

#アソシエーションの設定

```ruby:app/models/contact.rb
class Contact < ApplicationRecord
 has_many :notifications,dependent: :destroy
end
```

```ruby:app/models/notifications.rb
class Notification < ApplicationRecord
  belongs_to :contact

  def self.confirmed
    unchecked_notifications = where(checked: false) 
    unchecked_notifications.each do |un|
      un.update!(checked: true)
    end
  end
end
```

self.confirmedでクラスメソッドを定義しています。
whereメソッドでcheckedカラムがfalse(未読)のデータを全て取得し、
次の行でfalseのデータを変数に渡し、checked: trueにupdateしています。

```ruby:app/controllers/directors/contacts_controller.rb
class Directors::ContactsController < ApplicationController
before_action :authenticate_director!
  def index
    @contacts = Contact.page(params[:page]).per(6) 
    Notification.confirmed
  end
end
```

今回は、管理者(directorモデル)のみログイン機能を持たせているのでその辺りの記述も入ってきています。
Notification.confirmedでモデル内で記述しているクラスメソッドを呼び出します。

#viewに表示
あともう少しです！

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
 before_action :check_notifications
  def check_notifications
    @unchecked_notifications = Notification.where(checked:false)
  end
end
```


```erb:app/views/layouts/application.html.erb
          <li><%= link_to ' About', about_path %></li>
          <li><%= link_to ' Blog', directors_blogs_path %></li>
          <li><%= link_to ' Course', directors_fees_path %></li>
          <li><%= link_to ' Schelule', directors_schedules_path %></li>
          <li><%= link_to ' Contact', directors_contacts_path %>
          <% if @unchecked_notifications.any? %>
          <span style="background-color: gold;width:10px;height:10px;top:14px;left:10px;position:absolute;border-radius:50%;"></span>
          <% end %>
```

ヘッダーの記述です。
htmlの記述に関して、ifとany?を組み合わせると、条件に一致した要素が存在する場合や配列の要素チェックが可能になります。つまり、コントローラーで定義しているcheckedがfalse(未読)であること、が条件となります。
spanタグ内の記述は、通知の◯マークを作っています。fontawesomeを入れていればもうちょっとシンプルだと思いますが...:sweat:

これで、contact一覧を表示すると通知マークが消えるように実装ができました！

#最後に
私は今回の実装で、クラスメソッドやany?メソッドの使い方について学習しました。
より詳しく知りたい方は調べてみてください:relieved:
表現や記述など、拙いところばかりかと思いますがここまで読んで頂きありがとうございます:bow:
java staticイニシャライザとは

#staticイニシャライザとは

クラスのロード時に一度だけ実行されるコードブロックのこと。

例)

```java:staticSample.java

class Sample{
   public static void main( String args[] ){
      System.out.println( "今年で" + Nenrei.age + "歳になる。");
   }
}

class Nenrei{
   static int age = 25;

   static{
      age ++;
   }
}
```

上記の実行結果

```
今年で26歳になる。
```

Nenreiクラスのstaticフィールドであるageが呼び出された際に、
staticイニシャライザに定義されている

```
age ++
```

が実行され、ageが+1される。

**また、staticイニシャライザは１つのみではなく、複数定義する事も可能**
[ MAC ] Vagrantで共有ディレクトリのパス変更したらエラーになった

こんな感じになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88861/91bc7a1d-8562-0e9f-13cb-abdb01b2d620.png)
vagrant と共有しているディレクトリの設定は`/ext/exports`ファイルに書き込まれてしまっているので、そこを手動で変更してあげることで解決できる。

```bash
sudo vi /ext/exports
```
```bash:/etc/exports
# VAGRANT-BEGIN: 501 2d073983-50c8-4390-ba74-0eec783b6ac7
"/xxxxx/xxxxx/xxxxx/xxxxx/htdocs" -alldirs -mapall=501:20 192.168.33.10
"/xxxxx/xxxxx/xxxxx/xxxxx/nginx/conf" -alldirs -mapall=501:20 192.168.33.10
"/xxxxx/xxxxx/xxxxx/xxxxx/nginx/log" -alldirs -mapall=501:20 192.168.33.10
# VAGRANT-END: 501 2d073983-50c8-4390-ba74-0eec783b6ac7

以下略
```

めでたし。
私のSERP、貧弱すぎ⁉

# 私のSERP、貧弱すぎ⁉
※SERPは検索エンジンのページに表示される読者を誘導するための文言・写真等です。

ホームページ作るようになってから2年目ぐらい。
それまで業務用のWebアプリ作成してました。
HTMLわかるしHPぐらいよゆーだろ。
そんな風に思ってた時期が僕にもありました。

## ある日気付く納品物の貧弱さ
特に苦情があったわけでもなくGoogleの匙加減で集客に成功したりまるで成果をあげれなかったりする日々。
お客様のビジネスは順調だけどネットで集客はあまり上手くいってません。

## 認めたくない納品物のダメさ加減

### 遅い
まず気になったのがレスポンスの遅さ。
せっかく貧弱なSERPにもかかわらず来てくれたお客様も閉口して帰るでしょう。
firebaseとNuxtjsでSSRしてましたがSSGに変えました。
一時的に検索順位が上がりましたがすぐ戻りました。

### metaタグがめちゃくちゃ
HPだから人の目で見てまともな状態にすればいいと**練乳**より甘い考えをしてたようです。

#### title / h1タグ
titleもHPのルートのタイトルにトップページとついてます。
お客様に土下座したほうがいいですね。
すぐにお客様のビジネス名＋検索上位に出したいキーワードに変えました。

#### meta description
descriptionもひどいです。
ルートページのdescriptionが全部で20文字とかです。
お客様を歓迎する気なさそうですね。
お客様に確認して文言追加しました。

#### meta thumbnail
競合の結果を見るまでもなくほかのサイトのSERPには画像が付いてます。
あれも順位が上がれば検索エンジンが選んで表示してくれるのかなと**愚か**なことを考え調べもせずにいました。
検索順位が上記対策をした結果検索順位が上がっても一向に表示されないので調べたらmeta thumbnailで制御できるんですね。
すぐに追加しました。

#### canonical link
すぐできることなのに放置していたことを思い出したのでリンクタグを追加しました。

### ld+json
なんとか納品物が最低な状態からまあ見れる状態になってきましたがまだ貧相です。
ld+jsonでリッチにできると昔読んだ記憶があったので追加してみることにしました。

#### パンくずリスト
普通のサイトなら当然あるパンくずリストも形だけあってld+jsonの形ではありませんでした。
ページの種類も少ないのですんなり追加できました。

#### review / aggregateRating
グーグルマップにローカルSEOとして登録していたためレビューが付いているので意味があるかわからなかったですがやるだけやってみようと思い追加しました。

## 俺たちの戦いはこれからだ
金をもらってやる仕事で最低限のことはできたかなと思いましたが肝心の集客が順調とは言えないのでまだまだこれからですね。
ビジターは増えたけどHPの目的のお問い合わせまで進んでくれる人が少ないです。
SEOに気を使った文書編集をお客様にしてもらう必要があるんだろうなと思っています。