OmniAICreator/Qiita-1.07M huggingface dataset:
令和2年3月31日「測量作業規程の準則」一部改正でUAVを利用した測量が追加されました！

#第4編　三次元点群測量
第3編地形測量及び写真測量／第5章UAV写真測量にもUAVを利用した測量の規程があるのですが、空中写真測量をUAVで行うためのもので、以前から飛行機による空中写真測量を行っていた業者でないと作業出来ない内容となっています。

<dl>
  <dt>測量作業規程の準則とは</dt>
  <dd>標準的な作業方法等を定めることにより、その規格を統一するとともに、必要な精度を確保すること等を目的とする。測量法第34条</dd>
　<dd>計画期間（自治体等）は測量作業規程を定め、国土交通大臣の承認を得る必要があります。測量法第33条第1項</dd>
　<dd>国土交通大臣は、公共測量作業規程の一般的な規範（手本）として、測量法第34条に基づく「作業規程の準則」を定めています。公共測量作業規程の作成の際に利用することができます。</dd>
</dl>

<strong>以下、自分たちのドローンで公共測量を行うことが出来るか、その検討のために測量作業規程よりいくつかの項目を抜粋して解説しております。</strong>

##第3章　UAV写真点群測量

###第3節（評定点及び検証点の配置）第515条

|位置精度|隣接する外側評定点 |任意の内側評定点|
|:-:|:-:|:-:|
|0.05m以内|100m以内|200m以内|
|0.10m以内|100m以内|400m以内|
|0.20m以内|200m以内|600m以内|
外側評定点3点以上、内側評定点1点以上の設置が必要です。

検証点は評定点とは別に、第2章現地測量第119条、第120条のTS点設置に準じて行う。

1. 検証点は評定点から出来るだけ離れた場所に均等に配置する。
2. 検証点は設置する評定点の半数以上とする。
3. 検証点は平坦な場所又は傾斜が一様な場所に配置する。

###使用するUAVの性能及びデジカメの性能は第225条、第226条に準じる。
UAV性能
1. 自律飛行機能及び異常時の自動帰還機能を装備していること。
2. 航行能力は、利用が想定される撮影区域の地表風に耐えることができること。
3. 撮影時の機体の振動や揺れを補正し、デジタルカメラの向きを安定させることができること。
カメラ性能
1. 焦点距離、露光時間、絞り、ＩＳＯ感度が手動で設定できること。
2. レンズの焦点の距離を調整したり、レンズのブレ等を補正したりする自動処理機能を解除できること。
3. 焦点距離や露光時間等の情報が確認できること。
4. 十分な記録容量を確保できること。
5. 撮像素子サイズ及び記録画素数の情報が確認できること。

<strong>UAV写真測量では第227条で独立したカメラキャリブレーションを行うことになっているが、UAV写真点群測量ではセルフキャリブレーションを標準としている。第527条</strong>

###撮影計画
| 位置精度 | 地上画素サイズ |
|:-:|:-:|
|0.05ｍ以内|0.01ｍ以内|
|0.10ｍ以内|0.02ｍ以内|
|0.20ｍ以内|0.03ｍ以内|

* 撮影後に実際の写真重複度を確認できる場合には、同一コース内の隣接数値写真との重複度が<strong>８０パ
ーセント以上</strong>、隣接コースの数値写真との重複度が<strong>６０パーセント以上</strong>を確保できるよう撮影計画を立案することを標準とする。撮影後に写真重複度の確認が困難な場合には、同一コース内の隣接数値写真との重複度は<strong>９０パーセント以上</strong>、隣接コースの数値写真との重複度は<strong>６０パーセント以上</strong>として撮影計画を立案するものとする。
* 外側標定点を結ぶ範囲のさらに外側に、少なくとも１枚以上の数値写真が撮影されるよう、撮影計画を立案するものとする。

###地上画素サイズの計算

```math
対地高度=\frac{地上画素サイズ}{使用するデジカメの1画素のサイズ}\times焦点距離\\
使用するデジカメの1画素のサイズ=\frac{撮影素子}{記録画素数}
```
撮影素子　（例）35mmフルサイズ（35.8mm×23.9mm）
記録画素数（例）6000×4000（2400万画素）
レンズ焦点距離（例）30mm

```math
対地高度=\frac{10mm}{0.006mm}\times30mm\div1000=50m\\
使用するデジカメの1画素のサイズ=\frac{35.8mm}{6000}=0.006mm
```

i-Construction土工事の計測業務が発注されておりますが、位置精度5cm以内が多いようです。地上画素サイズは1cm以内となり50mの高度で撮影するには、ざっくり2400万画素以上のカメラ性能が必要になります。（レンズ等によります）

###第5節　三次元形状復元計算
Pix4D、Metashape（SfM）等による点群データ作成がこの部分に相当します。

* カメラのキャリブレーションについては、三次元形状復元計算において、セルフキャリブレーションを行うことを標準とする。第527条第5項


###標定点の残差及び検証点の較差の点検 第529条

1. 三次元形状復元計算で得られる標定点の残差が、Ｘ、Ｙ、Ｚのいずれの成分も、作成する三次元点群データの位置精度以内であることを点検する。
2. あらかじめ求めた検証点の位置座標と、三次元形状復元計算で得られた検証点の位置座標との較差が、Ｘ、Ｙ、Ｚのいずれの成分も、作成する三次元点群データの位置精度以内であることを点検する。
3. 点検のために、必要に応じてオルソ画像を作成することができるものとする。
4. 点検の結果、精度を満たさない場合には、不良写真の除去及び特徴点の修正を行った上で、再度三次元形状復元計算を行い、点検を行うものとする。こうした処理を行っても精度を満たさない場合には、再撮影を行うものとする。
5. 三次元形状復元計算ソフトで直接検証点の位置座標を求めることができない場合は、検証点の位置座標は、次の方法で求めるものとする。
<dl>
  <dd>・平面位置は、第３項で作成したオルソ画像上で検証点の位置を確認し、座標を求める。</dd>
  <dd>・標高は、作成した三次元点群データを用いて、各検証点に対し平面座標上の距離が１５センチメートル以内であるような三次元点群データを抽出し、距離の重み付内挿法で求める。</dd>
</dl>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161655/528657b8-eb2e-85fa-7449-f63a550d8f9c.png)国土地理院ホームページより
『超スマート社会』（Society5.0）ってなに？



# はじめに
最近、『超スマート社会』とか『Society 5.0』っていう単語を目にしたり聞いたりして、
「なんだそれ？」となったので、調べたものをまとめてみました。

# 『超スマート社会』『Society 5.0』ってどこから生まれた言葉？
これらの言葉は、2016年（平成28年）に閣議決定された、『第5期科学技術基本計画』という計画の中で説明されています。
## 第5期科学技術基本計画
これは『科学技術基本法』（法令番号： 平成7年法律第130号）という法律があり、
「技術水準の向上のために、5年ごとに計画を立ててね！」っていう法律です。
1995年（平成7年）から5年ごとに計画が立てられているので、現在は第5期、というわけです。
（つまり来年2021年には第6期の計画が立てられるわけだ…）

話がちょっと逸れましたが、この『第5期科学技術基本計画』では、以下の4つの取り組みを柱として推進していく、と定められています。

> 1. 未来の産業創造と社会変革に向けた新たな価値創出の取組
2. 経済・社会的課題への対応
3. 科学技術イノベーションの基盤的な力の強化
4. イノベーション創出に向けた人材、知、資金の好循環システムの構築

この1つ目『未来の産業創造と社会変革に向けた新たな価値創出の取組』の中で、
『超スマート社会』（Society 5.0）という言葉が出てきます。

# 5.0？じゃあ1.0～4.0もあるの？

はい、政府が以下のように定めています。

> 1. 狩猟社会(Society 1.0)
2. 農耕社会(Society 2.0)
3. 工業社会(Society 3.0)
4. 情報社会(Society 4.0)

そして、第5期科学技術基本計画で
5. 超スマート社会(Society 5.0)
という言葉が生まれました。

# 超スマート社会って具体的にどんな社会？

内閣府では、超スマート社会を以下のように説明しています。

> 必要なもの・サービスを、必要な人に、必要な時に、必要なだけ提供し、
社会の様々なニーズにきめ細やかに対応でき、あらゆる人が質の高いサービスを受けられ、
年齢、性別、地域、言語といった様々な制約を乗り越え、活き活きと快適に暮らすことのできる社会

言葉だけで考えると、なかなか夢のような社会だと思いませんか？
デパートで考えると、需要と供給が完全に１：１になるような感じですかね…？

とまあ、上記で説明されているような社会を実現・またはそれに近づいていくには、
AIやIoTをはじめとした、新しい技術をどんどん取り入れていく必要があるわけです。

# 結論
『超スマート社会』（Society 5.0）とは、
『情報社会』（Society 4.0）に次ぐ、IoTやAIなどをフル活用した未来の社会の姿。

…と結論が2行で終わってしまいましたが、
「へぇー、情報社会の進化系なんだなぁ…」くらいに覚えておけば良いかなと。

# 参考・引用
・[内閣府 - 科学技術基本計画](https://www8.cao.go.jp/cstp/kihonkeikaku/index5.html)
・[内閣府 - 基盤技術の推進の在り方に関する検討会](https://www8.cao.go.jp/cstp/tyousakai/kiban/)
・[Wikipedia - 科学技術基本法](https://ja.wikipedia.org/wiki/%E7%A7%91%E5%AD%A6%E6%8A%80%E8%A1%93%E5%9F%BA%E6%9C%AC%E6%B3%95#:~:text=%E7%A7%91%E5%AD%A6%E6%8A%80%E8%A1%93%E5%9F%BA%E6%9C%AC%E6%B3%95%EF%BC%88%E3%81%8B%E3%81%8C%E3%81%8F,%E3%81%97%E3%81%9F%E3%81%8C%E3%81%84%E7%AD%96%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%80%82)
CodeDeployのデバッグする際にとりあえず見てみるログファイル

## 経緯
CodeDeployでデプロイ失敗した際にAWSのコンソールに出てるエラーをググってみたがよく分からなかったのでEC2インスタンス内のログを調べてみた

その際デバッグするのに役立ったファイル紹介

## 環境
Amazon Linux 2
codedeploy-agent 1.2.1

### CodeDeployスクリプトのログファイル
```
/opt/codedeploy-agent/deployment-root/デプロイグループID/デプロイID/logs/scripts.log
```
appspec.ymlのhooksセクションで実行されるスクリプトのログファイル
このファイルでエラーが見つかればhooksセクションで実行されるシェルスクリプトの見直しが必要

### リビジョンのファイル群保管ディレクトリ
```
/opt/codedeploy-agent/deployment-root/デプロイグループID/デプロイID/deployment-archive
```
ここでのリビジョンとはGitHubやS3などに存在するこれからデプロイされるファイル群を指す
appspec.ymlのfilesセクションの記述に基づき指定のディレクトリにファイルを配置する



###CodeDeploy エージェントの動作ログファイル
```
/var/log/aws/codedeploy-agent/codedeploy-agent.log
```

エラーログ
`InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please check if this instance was started with an IAM instance profile`
などが出ていたらEC2インスタンス適切なにIAMロールがアタッチされているか確認


## 最後に
いちいちsshで入ってログファイルを確認するのも大変！
という方は自動でログを転送することもできるらしいですね。

参考サイト↓
https://dev.classmethod.jp/articles/codedeploy-cloudwatchagent-cloudwatchlogs/
Swift CombineにてFutureで実行している非同期処理をsinkしているのに途中でキャンセルされる

Combineを使用する際にハマってしまったので、備忘録として残します。

# 問題

[Future](https://developer.apple.com/documentation/combine/future)のインスタンスに[sink](https://developer.apple.com/documentation/combine/future/sink(receivecompletion:receivevalue:))してクロージャ(サブスクライバ)を設定し、非同期処理が完了した際にsinkにて設定したクロージャの処理を行いたいのだが、完了する前にSubscribeがキャンセルされてしまう。

```swift
func start() {
        Future<Void, Error>{ promise in
            DispatchQueue.main.asyncAfter(deadline: .now() + 5.0){
                promise(.success(()))
            }
        }
        .handleEvents(receiveSubscription: { _ in
            print("receiveSubscription")
        }, receiveOutput: {
            print("receiveOutput")
        }, receiveCompletion: { _ in
            print("receiveCompletion")
        }, receiveCancel: {
            print("receiveCancel")
        }, receiveRequest: { _ in
            print("receiveRequest")
        })
        // クロージャが実行されない
        .sink(receiveCompletion: { completion in
            print("completion:\(completion)")
        }, receiveValue: {
            
        })
    }
```
```text:デバッグコンソール 
receiveSubscription
receiveRequest
receiveCancel
```

# 解決方法

sinkメソッドの返り値を変数に保持するか、[store](https://developer.apple.com/documentation/combine/anycancellable/store(in:)-6cr9i)メソッドを使用して保持する必要がある。

```swift
func start() {
        cancellable = Future<Void, Error>{ promise in
            DispatchQueue.main.asyncAfter(deadline: .now() + 5.0){
                promise(.success(()))
            }
        }
        .handleEvents(receiveSubscription: { _ in
            print("receiveSubscription")
        }, receiveOutput: {
            print("receiveoutput")
        }, receiveCompletion: { _ in
            print("receiveCompletion")
        }, receiveCancel: {
            print("receiveCancel")
        }, receiveRequest: { _ in
            print("receiveRequest")
        })
        .sink(receiveCompletion: { completion in
            print("completion:\(completion)")
        }, receiveValue: {
            
        })
    }
```
```text:デバッグコンソール
receiveSubscription
receiveRequest
receiveoutput
receiveCompletion
completion:finished
```

# 原因

Future内に実装した処理が完了(promise()がコールされる)前にsinkから返却されたAnyCancellableが破棄されてしまうとキャンセルされてしまうみたい。
公式のリファレンスを読むと「Return Value」の部分にひっそりと書かれていた。

https://developer.apple.com/documentation/combine/future/sink(receivecompletion:receivevalue:)
Excel 2019 for Mac のファイルアクセス権限

#Excel 2019 for Mac のファイルアクセス権限
MacOS Mojave から Mac のアプリはセキュリティが強化され、操作毎にアプリが初めてアクセスするファイルやフォルダに権限を与える作業が必要になりました。

特にVBAを利用される方はDir関数等でフォルダ内のデータをピックアップするや別のブックを参照するなどで初めてアクセスするファイル、フォルダにはVBAが中断され、ファイルアクセス権の付与作業が求められます。

![dir1_mac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965663/01d39f3d-707d-eb14-172b-04f58a6c66c0.png)

例えば、ファイルの移動をするNameステートメントを使っても、初めてアクセスするファイル、フォルダの場合はVBAが中断され、ファイルアクセス権の付与作業が求められます。

~~~
Sub FileMove()

Dim file As String
Dim dir As String

file = Range("B2").value

dir = Range("B3").value & Application.PathSeparator & "sample.csv"

Name file As dir

End Sub
~~~

設定　＞　セキュリティーとプライバシー　＞　プライバシー　でファイルとフォルダのアクセス権を与えても個別に許可する必要があります。ただし、一度アクセス権を付与すると別のExcelファイルでもアクセス権は維持されます。

![access.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965663/72a02334-5cbb-c803-7d38-f78972527045.png)

##回避方法

大変煩わしいだけでなく、別のブックへの参照をするVBAを実行する際はそこで処理が停止してしまうのでできれば避けたいところですが、回避するためにはAppleScriptで同様の機能を実装するしかありません。

VBAからAppleScriptを利用するにはAppleScriptTask関数(Excel2016 for Macから)を利用する必要があります。

詳しい情報は[こちらのブログ](https://the-forme.net/note/spreadsheet/mac2019permission/)にも書いています。もしよかったらご覧ください。
xtextによるvscodeのエクステンションを複製するGradleタスクを書いてみた

#概要
[この記事](https://qiita.com/HiroInTFLab/items/ac8ffc86b5b822aa68b1)でビルドしたVSCode向けエクステンションは、拡張子が```mydsl```のファイルを開いた場合に機能するように実装されています。同僚や仲間内へ開発したエクステンションの配布を考えている、のであれば独自の拡張子に対応しておきたいですよね。
そこで、自身のGradleの習得を兼ねつつ、基本は複製とリネームを使って実現してみました。
これが誰かのお役に立てば幸いです。

#開発環境
- Windows10 Pro 1909
- VSCode 1.47
- JDK 1.8
- Tortoise Git 2.9.0.0

#成果物
ソースコードを[GitHub](https://github.com/tfLabs/xtext-languageserver-example-duplicator)に置きました。
フォルダ構造の第1階層は以下のようになっています。

```
build.gradle
gradle/
gradle.properties
gradlew
gradlew.bat
LICENSE.txt
README.md
xtext-languageserver-example
```

#使い方
##とにかく使ってみたい方は
1. [GitHub](https://github.com/tfLabs/xtext-languageserver-example-duplicator)からcloneを行う
1. コマンドラインウィンドウを開き、cd等でcloneしたディレクトリへ移動
1. ```gradlew duplicateXtextVscode```を実行
1. ```cd xtext-languageserver-example-duplicated```を実行
1. ```gradlew startCode```を実行
1. DEMOフォルダのファイルa.mydslの拡張子をa.dupに変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94018/1eeb6a43-f208-f725-d568-b9e9b6fad117.png)
シンタックスハイライトでHelloに色が付けば、拡張子dupのファイルに対応したExtensionができたことが確認できます。

##拡張子を変えたい？
拡張子がdup固定のままだとオリジナルとは言えませんよね。
拡張子は、

1. gradle.propertiesに定義してある、```ext=dup```の```dup```の部分を変える  
なお、空文字列程度のエラーチェックです。Windowsが受け入れ可能な入力内容としてください
1. ```gradlew duplicateXtextVscode```を実行
1. ```cd xtext-languageserver-example-duplicated```を実行
1. ```gradlew startCode```を実行

の手順で変えることができます。

##複製先のフォルダ名を変えたい？
あまり使わないかと思うものの、複製先フォルダを指定可能にしています。

1. gradle.propertiesに定義してある、```to=xtext-languageserver-example-duplicated```の```xtext-languageserver-example-duplicated```の部分を変える  
こちらも、空文字列程度のエラーチェックです。```..```などを含めた場合などは未確認です
1. ```gradlew duplicateXtextVscode```を実行
1. ```cd xtext-languageserver-example-duplicated```を実行
1. ```gradlew startCode```を実行

の手順で変えることができます。

#終わりに
これで多数のオレオレ言語を簡単に作ってかつvscode上で使ってもらう環境が整いつつあるんじゃないかと、密かに思っていたりします。
残すは、エクステンション導入にvscode上に現れる画面のカスタマイズ。具体的には、

- エクステンション名
- 説明となるREADME.md
- プロジェクト名　末尾だけでもいいかも
- 団体名
- エクステンションの画像

などを定義すれば見た目は元のエクステンションと同じには見えないものになるのですが、ボリュームがあるので、次のネタとして取り組みたいと思っています。

#補足
簡単ですけど、本文中で述べたことの詳細や技術に関して、触れておこうと思います。

##Gradleタスク定義
コマンドラインから指定していないタスクで、かつ、そのタスク内のコードが勝手に実行する、というGradleの動作が書いたコードから理解できませんでしたが、[こちら](https://www.kannon.link/fuku/index.php/2016/09/28/01-10/)に書いてあるとおり、

- 初期化
- 設定時
- 実行時

の設定時に実行されていたのですね。
フォルダやファイルの有無といったタスク開始時に前提となるチェック処理は設定時に書いておく、が定石でしょうか？書き分ける基準までは検索で見つけられませんでしたが、設定時でないと困る場面はそう多くないと思うので、タスク内の処理はdoFirstまたはdoLastブロック内にのみ書くこととする、といった設計基準を設けても良いかもしれません。
なお、[GitHub](https://github.com/tfLabs/xtext-languageserver-example-duplicator)に置いたコードには未反映です…。

##Gradleでファイルコピー
ファイルやフォルダをコピーする例を検索すると、コピータスクを使う例がたくさん出てくるものの、隠し属性のファイルやフォルダがコピーされないことに気づきました。[こちら](https://issues.gradle.org/browse/GRADLE-1883)を参考に、```org.apache.tools.ant.DirectoryScanner```を使って実現することにしました。
なお、excludeでコピー対象に含めたくないファイルやフォルダを指定できるので、.gitフォルダは除く設定としています。

##Gradleタスクでのエラー処理
[こちら](https://stackoverflow.com/questions/10312259/recommended-way-to-stop-a-gradle-build)を参考にしました。
ロールバック等が不要な簡単なタスクなので、エラーの場合は例外をスローして中断、でいいと思っています。

##作ったbuild.gradle
上記のようにつまづきながらもどうにか実現できたものの、時間をかけすぎないことを念頭に置いていたので、作ったbuild.gradleはかなり泥臭い感じとなっています。Gradleの習得にはまだまだ時間がかかりそうです。次に取り組むときは、もっと効率的かつ可読性にも考慮した書き方を目指したいものです。
WordPressのタクソノミーアーカイブのパーマリンクを変更する

ワードプレスのテーマtwentytwentyoneを基盤に、タクソノミーのアーカイブページのパーマリンクからタクソノミー名を削除する実装を行ったので、備忘録的にこの記事を残す。

# 環境情報

PHP：version 7.3.12
WordPress：version 5.5.3
WPテーマ：twentytwentyone

# ゴールの確認

カスタム投稿タイプでオリジナルのタクソノミーをカテゴリーのように使い、そのタクソノミーのアーカイブページをそれぞれ作成したい場合に起こる問題です。

※ポストタイプ名が topic 、タクソノミー名が topic_category 、ターム名が news で今回 news のアーカイブページを作りたい想定です。

今回のゴールはアーカイブページのリンクが /topic/news/ になることです。

# カスタム投稿タイプ作成時の設定

register_post_type の args に入れる配列に以下の二つを指定します。
特に 'with_front' => false は忘れてはいけない！

```functions.php
$args = array(
    'has_archive' => true,
    'rewrite' => array( 'with_front' => false )
);
```

# プラグイン Custom Post Type Permalinks の導入

Custom Post Type Permalinks というプラグインをインストールし、管理画面->設定->パーマリンク設定から topic のパーマリンク設定を /%topic_category%/%post_id%/ または /%topic_category%/%postname%/ などにします。

そして忘れてはいけないのが、「カスタマイズされたカスタムタクソノミーのパーマリンクを使用する。」にチェックを入れることです！

この時点でデフォルトのパーマリンクが /topic/topic_category/news/ になっているはずです。

# topic_category の部分を削除する

後は functions.php からリンク設定を行って、リライトで設定を書き換えれば完成です！

```functions.php
// topic_category のアーカイブページのパーマリンクを変更する
function my_custom_post_type_permalinks_set($termlink, $term, $taxonomy){
    return str_replace('/'.$taxonomy.'/', '/', $termlink);
}
add_filter('term_link', 'my_custom_post_type_permalinks_set',11,3);
// ページネーションがある場合▽▽
add_rewrite_rule('topic/([^/]+)/?$', 'index.php?topic_category=$matches[1]', 'top');
add_rewrite_rule('topic/([^/]+)/page/([0-9]+)/?$', 'index.php?topic_category=$matches[1]&paged=$matches[2]', 'top');
// ページネーションがある場合△△
```
Java PDFをExcelで保存   

<p> </p>
<p>前にJavaでExcelをPDFに変換する方法を紹介しましたが、逆にPDFをExcelで保存したいと思うならどうしますか？今回はSpire.PDF for Javaを通して見せて差し上げましょう。</p>
<h4>下準備</h4>
<p>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/pdf-for-java.html">Free Spire.PDF for Java</a>無料版をダウンロードしてください。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201223/20201223153847.png" alt="f:id:lendoris:20201223153847p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.PDF.jarを参照に追加してください。</p>
<p> </p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201223/20201223153900.png" alt="f:id:lendoris:20201223153900p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4>元のファイル</h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201223/20201223153936.png" alt="f:id:lendoris:20201223153936p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>

```JAVA
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;

public class ToXLS {
    public static void main(String[] args) {
        //PdfDocumentを作成します。
        PdfDocument pdf = new PdfDocument();
        //PDFファイルをロードします。
        pdf.loadFromFile("C:\\Users\\Test1\\Desktop\\Sample.pdf");
        //Excelで保存します。
        pdf.saveToFile("output/ToXLS.xlsx", FileFormat.XLSX);
    }
}
```


<h4> 完成例</h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201223/20201223153959.png" alt="f:id:lendoris:20201223153959p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
【Java, Scala】ImageIOで画像のリサイズ

## コード全体

```scala
import java.io.File
import java.awt.image.BufferedImage
import javax.imageio.ImageIO

object ImageUtil {
  def resize(file: File): Unit = {
    val original = ImageIO.read(file)

    // 元ファイルの縦横サイズ(pixel)を取得
    val originalWidth = original.getWidth.toDouble
    val originalHeight = original.getHeight.toDouble

    // 長辺を1とした縦横比を取得
    val (widthScale, heightScale) =
      if(originalWidth > originalHeight) (1d, originalHeight / originalWidth)
      else (originalWidth / originalHeight, 1d)

    // 長辺を200pxとして、縦横比を保ちリサイズ後の画像サイズを決定
    val width = (200d * widthScale).toInt
    val height = (200d * heightScale).toInt

    val image = new BufferedImage(width, height, original.getType)

    val scaled = original.getScaledInstance(width, height, java.awt.Image.SCALE_AREA_AVERAGING)

    image.getGraphics.drawImage(scaled, 0, 0, width, height, null)

    ImageIO.write(image, "jpeg", new File("/tmp/resized.jpeg"))
  }
}
```

## ざっくり解説
画像サイズの計算は問題ないと思うので、画像生成部分だけ。

```scala
val image = new BufferedImage(width, height, original.getType)
```

ここで画像サイズが決まる。まっさらなキャンバスを作るイメージ。
例ではリサイズ後の画像の大きさに合わせているので、余白なしの画像になる。
もし余白ありの正方形にしたい場合はこんな感じ。

```scala
// 長辺の長さを1辺とした正方形を作る
val scale = Math.max(width, height)
val image = new BufferedImage(scale, scale, original.getType)
```

次に、元画像をリサイズした画像データを取得する。

```scala
val scaled = original.getScaledInstance(width, height, java.awt.Image.SCALE_AREA_AVERAGING)
```

そして最初に作ったキャンバスにリサイズ後の画像を貼り付ける。

```scala
image.getGraphics.drawImage(scaled, 0, 0, width, height, null)
```

`0, 0`はそれぞれキャンバスのx座標とy座標。指定座標を基準にリサイズ後画像をペーストするイメージ。
余白がある時は座標を調整すれば画像を左右上下に寄せたり中央にしたりできる。

最後にファイル出力して終わり。

```scala
ImageIO.write(image, "jpeg", new File("/tmp/resized.jpeg"))
```

## おまけ: 余白の色を変える
余白がある場合、余白部分の色はデフォルトだと黒になる。
色を変える場合は、`drawImage`の前に全体を好きな色で塗ってやればよい。

```scala
// 余白を白にする
image.getGraphics.setColor(Color.WHITE)

// 座標(0, 0)から、画像の縦横幅いっぱいに指定色で埋める
image.getGraphics.fillRect(0, 0, image.getWidth, image.getHeight)
```
Java  PowerpointをXPSに変換

<p><strong>今日はJavaでPowerpointをXPSに変換する方法を紹介します。今回はSpire.Presentation for Javaというライブラリが必要となります。これは無料でMicrosoft Office系のソフトをダウンロードせずに使用できます。</strong></p>
<p><strong>では、行きましょう</strong></p>
<h4><strong>下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/presentation-for-java-free.html">Free Spire. Presentation for Java</a>無料版をダウンロードしてください。</strong></p>
<p><strong>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire. Presentation.jarを参照に追加してください。</strong></p>
<h4><strong>元のファイル</strong></h4>
<p><strong> </strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201223/20201223152051.png" alt="f:id:lendoris:20201223152051p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
```JAVA
import com.spire.presentation.*;

public class PPTtoXPS {
    public static void main(String[] args) throws Exception{

    //presentation objectを作成します。
    Presentation ppt = new Presentation();

    //ファイルをロードします。
    ppt.loadFromFile("Sample.pptx");

    //XPSで保存します。
    ppt.saveToFile("toXPS.xps", FileFormat.XPS);
ppt.dispose();

    }
}
```

<h4>完成例</h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201223/20201223152106.png" alt="f:id:lendoris:20201223152106p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
国産オープンソースのローコード開発プラットフォーム「プリザンター」

この記事は [Pleasanter(プリザンター) Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pleasanter) の25日目の、そして、今年のアドベントカレンダーの締めくくりとなる記事です。

# はじめに

Pleasanter(プリザンター) Advent Calendar 2020は、多くの皆様のご協力のもと、25日すべてを埋め、無事に最終日を迎えることができました。
"中の人"として、心より感謝申し上げます。ありがとうございました。

よろしければ、他の記事も含めてLGTMして頂けるととても嬉しいです。よろしくお願い致します。

# 2020年と、プリザンターの"位置づけ"

2020年は、私達にとって、世界中のほとんどがそうであったように激動と言いえる1年でした。
ニューノーマルと呼ばれるライフスタイルへの変化が求められ、ビジネスの有り様も大きく変わりました。
広くテレワークが浸透したことで、自宅などオフィス外からチームメンバーと情報を共有しコミュニケーションを取るための基盤が不可欠となり、その一翼を担うとまでは言えないまでも、プリザンターも少なからず注目されました。
そして、日本中が新しい生活への変化が求められるようになったタイミングで、Pleasanter for PostgreSQLが正式リリース。
待望の正式リリースながら、タイミング的には正直かなり悩ましい時期のリリースとなりましたが、今になって思えば、万事塞翁が馬という気もします。
ライフスタイルの変化に合わせて、当然のようにビジネスにも変化が求められ、業務の目まぐるしい変化に迅速に対応するためのツールとして情報システム界隈では「ローコード」というキーワードをよく聞くようになりました。
それまでは「Webデータベース」を謳ってきたプリザンターでしたが、今後は「ローコード開発プラットフォーム」としての方向性へシフトして行くことが決まったのもこの時期でした。
そして、今回のアドベントカレンダーでも度々登場しました「サーバスクリプト」機能が満を持して実装され、ローコード開発プラットフォームとしての位置づけは、より確固たるものとなったように思います。

# 業務アプリ開発プラットフォームとしての進化

2020年は、機能的な意味でも大きく進化した年でもありました。
上述したPostgreSQLへの対応、サーバスクリプト機能の実装も大きな進化と言えますが、それ以外でも様々な機能が追加されています。

中でもタブの追加やセクションの折り畳みといった画面レイアウトを自由に変更できる機能の追加は、管理する項目の多い業務では非常に有用だと思います。

[ユーザーマニュアル：タブ追加やセクション折り畳みなどを使って画面を整理する](https://pleasanter.net/fs/publishes/1396811/edit)
![項目多数アニメ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/ef2eaa1c-ab71-e603-2517-8a9d24a5121e.gif)

プリザンターの場合、各項目それぞれ26個まで配置して業務アプリを作成できますが、業務によっては26個では全然足りないというケースもあります。
1レコードで何百個という項目を扱う業務でも、多くの場合は復数部署・複数人でそれぞれ担当の情報項目を入力していくというケースが多いので、自分の担当外の情報も含めて何百個もの項目がズラーーーーーっと並んでいるのは効率的な作業を行ううえでは弊害でしかありません。
しかし、このタブ追加や折り畳みなどをうまく使うと効率的なレイアウトで項目を配置することができます。

上の画面動画では敢えて使っていませんが、スタイル機能を使うことで各項目の横幅を変更することも可能ですし、スクリプト機能でログインしているユーザや所属部署を判別し必要の無い項目を非表示にしておくといったことも可能ですので、項目数は多くても効率的に操作できる画面レイアウトを作ることが可能です。

項目の拡張については、年間サポートサービスの上位プランを契約する必要がありましたが、多くのご要望に応えて年間サポートサービスのすべてのプランで項目の拡張が利用可能となりました。
ビジネスでプリザンターを使っている皆様にとっては新プラン対応は大きな朗報だったのではないでしょうか。

[900個まで項目数を拡張できるエンタープライズエディション](https://implem.co.jp/enterprise-edition/)

拡張HTMLや項目ごとにCSSクラスを指定できる機能など、見た目のカスタマイズはかなり柔軟に対応できるようになり、APIの拡張によって他の業務システムとも、よりパワフルに連携することが可能となりました。
これらの機能によりプリザンターは、更に多くの様々な業務でお使い頂けるようになったのではないかと思います。
プリザンターを使うことで、皆様のマネジメント業務がもっと快適になりますように。
そして、それによって皆様の貴重な時間が、もっとクリエイティブなことに使えるようになれば嬉しい限りです。

# おわりに

今年1年でのプリザンターの進化が、少しでも皆様のご要望を叶えるものになっていれば幸いです。
来年はさらなる飛躍を目指し、業務で求められるローコード開発プラットフォームとしての確固とした位置に立てるよう、2021年に挑みたいと思います。

2020年は、大きな変化/進化を迎えた年でしたが、皆様のお陰で大変に明るい新年を迎えられそうな期待でいっぱいです。
今年1年、本当にありがとうございました。来年も引き続きプリザンターを、インプリムをよろしくお願い致します。

それでは皆様、Merry Christmas!🎄 & Happy New Year!🗻 

and....
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/834556/9f7148dd-3338-c7fe-338e-463735f48fbb.png)
expo-web(react-native-web)でFCMの実装

今回は、expo-webでFCMを実装したのでその備忘録としてこの記事を書きます。
##offline supportを有効にする
expoでwebアプリを開発する場合ほとんどの場合PWAになると思います。
デフォルトではoffline supportが無効になっているので手動で有効にする必要があります。
コマンドで<code>expo customize:web</code>を打つと５つくらいのファイル名が表示されます。
その中で<code>webpack.config.js</code>を選択してください。
そして<code>webpack.config.js</code>を以下のように編集します。

```javascript:webpack.config.js
const createExpoWebpackConfigAsync = require('@expo/webpack-config');

module.exports = async function (env, argv) {
  const config = await createExpoWebpackConfigAsync({...env,offline:true}, argv);
  // Customize the config before returning it.
  return config;
};
```
4行目に<code>offline:true</code>を加えました。

ここは以下のサイトを参考にしました。
https://docs.expo.io/guides/progressive-web-apps/

https://github.com/expo/fyi/blob/master/enabling-web-service-workers.md
##service-workerの登録,push通知の受取処理
これは、海外の人で全く同じことをしていた人を見つけたのでその方のコードを有難く使わせてもらいました:relaxed:
参考にしたブログ↓
https://dev.to/gabrielnsd/push-notifications-using-firebase-in-pwas-built-with-expo-2elm

この方のブログを参考にすると、FirebaseConsoleからpush通知を送信するところまでできるようになります。
##Cloud Functionsで自動的にpush通知を送信する。
上記までの方法だと、手動でその都度操作する必要があります。
例えば、チャットが届いたときやユーザーが一定の行動をとったときに通知が送信できません。
これには、①送信先ユーザーのtokenと②FCMのサーバーキーが必要です。
②は、FirebaseConsoleから設定→Cloud Messagingタブの一番上にサーバーキーから確認できます。
今回はFireStoreの<code>messages/{messagesID}/message/{messageID}</code>にメッセージを保存し、これを起点に都度push通知を送信するようにします。
適時都合のいいように置き換えてください。

```javascript
//受け取ったメッセージ
var message = data.message
//保存したユーザーのtoken
var token = user.token
//requestするjson
//今回は簡単にしています。
var message = JSON.stringify({
　　　　　"notification": {
                //push通知のタイトル
                "title": '新着メッセージです。',
                //push通知の本文
                "body": message,
            },
            //送信先のtoken
            "to": token
        })

const res = await fetch('https://fcm.googleapis.com/fcm/send',
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    //server-keyのところを先ほど取得した各自のものに置き換えてください。
                    'Authorization': ['key', 'server-key'].join('='),
                },
                body: message
            })

```
これでメッセージが届いたら通知が行くようになります。
あくまでこれは簡単なものなので自分たちのサービスの合わせてカスタマイズする必要があると思います。
下は、bodyに含められるparameter一覧です。
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?hl=ja#Message

これで一通りFCMを扱えるようになると思います。
##おわりに
service-workerとは何ぞやというところから始まり、コピペさせて頂いたブログを見つけるのさえかなり時間がかかりました:pensive:
expo-webのpush通知の実装については情報が少ないと思うので皆さんの参考になればうれしいです。
##引用・参考にしたサイトまとめ
//expo-webのoffline-supportの設定
https://docs.expo.io/guides/progressive-web-apps/
https://github.com/expo/fyi/blob/master/enabling-web-service-workers.md
//service-worker,push通知の受信処理
https://dev.to/gabrielnsd/push-notifications-using-firebase-in-pwas-built-with-expo-2elm
//FCMで設定できるパラメータ一覧
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?hl=ja#Message
やる気の出ない開発に向き合うTips


こんにちは
この記事は、Phone Appli Advent Calendar の23日目です。
全然書くこと思いつかなかったので、今日はポエムです。

働いてるとどうにもやる気が出ない案件ってありませんか？
わたしもまあ、よくあるんですが、そんな時どうやってモチベーションを保っているかをざらざらと書いてみました。
個人的な意見ばかりですが、参考程度に。

## 今回のスコープ

やる気が出ない要因について、大きく以下の2通りくらいありそうな感じですが、今回は外的な要因によるものとして書きました。

### 内的なもの
- 言語やフレームワークがいけてない
- そもそも仕事やりたくなーいみたいなやつ

など

### 外的なもの
- これから作る機能に意味が感じられない
- 仕様が丸投げ

など

## やってること

### ステークホルダーと会話をする

最近はスクラムなどのフレームワークもあり、ステークホルダーとのコミュニケーションが全く取れない、という状態はあまりないんじゃないかなーとは思いますが、これはマストでやっています。
これができないと、そもそもどうしてこれを作る必要があるのか、とか、そういうのがわからなくて、正直、やる気を出す方が難しいです。
開発は基本的にカロリーが高いですし、おいそれと依頼されても背景とか熱意とかがないと、燃えないというか、燃やしたくても燃やすものがない状態になります。

### やる・やらないの話をする

早い段階で、やる・やらないの話をしておくことで、後でやる気が削がれるのを防いでいます。
また、「この内容ならやらない（できない）」、「これならやれる（できる）」、のような話をしておくことも、双方の関係を維持する上で大事だと思います。

後述する、「タスクを持ち続けない」もそうですが、認識のずれは全体的な死を招くので、このあたりは慎重かつ大胆に行います。
よくある話ですが、こっちは実現可能のできる、で返事をしたつもりが、向こうは実施可能のできる、で返事をした、と認識されて、あとであの件っていつ開発終わる？みたいなことにならないようなハンドリングは必須です。
＊？？？「できますが、開発するとは言っていない」

### 細かくコミットしてフィードバックをもらう

これはかなり重要だと思います。
細かくコミットすることで方向性のブレを減らし、かつ、フィードバックをもらうことで、自身のモチベーションが維持できます。
コミットできるような状態でなくても、進捗連絡は1ｗ程度で行い、案件自体の熱量を下げないようにすることも効果的です。
また、進捗連絡は必ずこちらから行い、急かされている、と思わないようにします。

### タスクをなるべく持ち続けない

タスクは持たないに越したことはないと思っています。
タスクを持っている最大のデメリットは、外から見ると「何かしら進んでいるように見える」ことだと思います。
基本的には自分の持てる範囲でタスクを持ち、キャパシティを超えそうな場合は、優先度の再評価や小さいタスクの消化、タスクの再分配を行って、持ち続けないようにコントロールし、仮に持ち続けるしかない場合でも、定期的にやっていないことの報告をやればいいんじゃないかな、といった感じです。


## おわり

以上です。
色々書きましたが、もちろんこれ以外にもやりようはありますし、最終的にはクライアントやステークホルダーのことが好きか、とか、関係が良好か、に尽きる気がします・・・。

あ、今やってる仕事がモチベ上がらない、とかじゃないです、ねんのため！！
KaggleのCorsesを受講する (矛盾したデータ入力)

## 入力されたデータに表記ゆれがある場合

１つ１つ手で修正するのが思いつく方法だが、もう少し賢いやり方がある

```python
# 値のバリエーションすべてを洗い出す
countries = professors['Country'].unique()

# アルファベット順にソート
countries.sort()
countries
```

Out

```
array([' Germany', ' New Zealand', ' Sweden', ' USA', 'Australia',
       'Austria', 'Canada', 'China', 'Finland', 'France', 'Greece',
       'HongKong', 'Ireland', 'Italy', 'Japan', 'Macau', 'Malaysia',
       'Mauritius', 'Netherland', 'New Zealand', 'Norway', 'Pakistan',
       'Portugal', 'Russian Federation', 'Saudi Arabia', 'Scotland',
       'Singapore', 'South Korea', 'SouthKorea', 'Spain', 'Sweden',
       'Thailand', 'Turkey', 'UK', 'USA', 'USofA', 'Urbana', 'germany'],
      dtype=object)
```

たとえば`Germany`と`germany`などで表記ゆれがあることが分かる

次にすべてを小文字にして、セルの先頭と末尾の空白を削除

```python
# convert to lower case
professors['Country'] = professors['Country'].str.lower()
# remove trailing white spaces
professors['Country'] = professors['Country'].str.strip()
```

#### ファジーマッチングを使用して矛盾したデータ入力を修正する

> ファジーマッチング:
> 対象の文字列に非常に似ているテキスト文字列を自動的に見つけるプロセス。
> 一般的に、ある文字列を別の文字列に変換する場合、変更する必要のある文字数が少ないほど、文字列は別の文字列に「近い」とみなされる
> ファジーマッチングに100%頼ることはできないが通常は少なくとも少しは時間を節約できるでしょう。

Fuzzywuzzyモジュールを利用することで簡単にファジーマッチングが可能

```python
# "south korea"に近いトップ10の単語を取得
matches = fuzzywuzzy.process.extract("south korea", countries, limit=10, scorer=fuzzywuzzy.fuzz.token_sort_ratio)

matches
```

Out

```
[('south korea', 100),
 ('southkorea', 48),
 ('saudi arabia', 43),
 ('norway', 35),
 ('austria', 33),
 ('ireland', 33),
 ('pakistan', 32),
 ('portugal', 32),
 ('scotland', 32),
 ('australia', 30)]
```

上から2つが"south korea"と同じと思われるので、スコアが47のものを「"south korea"」に置き換える
なんども使う処理になるので、関数化する

```python
def replace_matches_in_column(df, column, string_to_match, min_ratio = 47):
    # 入力値のカラムに格納される値の全種類を取得
    strings = df[column].unique()
    
    # 入力値にマッチする上位10件を取得
    matches = fuzzywuzzy.process.extract(string_to_match, strings, 
                                         limit=10, scorer=fuzzywuzzy.fuzz.token_sort_ratio)

    # 比率が90以上のマッチ結果を抽出
    close_matches = [matches[0] for matches in matches if matches[1] >= min_ratio]

    # DataFrameから近いマッチ結果の行を取得する
    rows_with_matches = df[column].isin(close_matches)

    # マッチ結果に値を置き換える
    df.loc[rows_with_matches, column] = string_to_match
    
    print("All done!")
```

関数呼び出し

```python
replace_matches_in_column(df=professors, column='Country', string_to_match="south korea")
```

#### エクササイズ（実装例）

https://www.kaggle.com/mandokawauso/exercise-inconsistent-data-entry/edit
Ubuntuの環境をvmwareで作ろう

本記事は、[Code Polaris Advent Calendar 2020](https://qiita.com/advent-calendar/2020/code-polaris)用の記事です。

はじめまして、ITの会社で働いて8年目になる知咲です。
特にこれといって得意分野があるわけではないのですが、プログラミングからサーバ保守までつまみ食いのようにやっています。
（上流は経験なし！！）

#そもそものきっかけ
何年か前にLLVMの環境が作りたくなって自分のノートPCにUbuntuの環境を作ったことがありました。
今回は日経LinuxでUbuntuが特集されているのを見かけたので、（ちょうど記事になりそうだし）もう一度作成してみようと思ったのが始まりです。

#用意するもの
- vmware Player（今回は無償版であるVMware Workstation 16 Player）
- Ubuntuのisoファイル（今回はUbuntu 20.10）

なお、isoファイルはサイズが大きいので、先にダウンロードしておくことをお勧めします。

#Ubuntuのダウンロード
[Ubuntuの日本語コミュニティ](https://www.ubuntulinux.jp/home)から日本語版を入手することができます。

#vmwareのダウンロード・インストール
[vmwareのサイト](https://www.vmware.com/jp.html)からインストーラをダウンロードします。
インストール自体は流れに乗っていけばOK。

初回起動時に商用か聞かれますが、商用利用しないのでここは上の選択肢を選びます。

#VM作成
1.vmware Playerを起動し、一番上の「新規仮想マシンの作成」をクリックします。
![VM初期画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/4cad40b2-d23f-91ea-0f7e-e92cb2880212.png)
2.仮想マシンウィザードが起動され、OSのインストールについて聞かれます。
　今回はisoイメージを事前にダウンロードしているので、2つ目を選び、isoファイルを指定します。
![仮想マシンウィザード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/b6442f57-bc9d-fb7a-730a-f5132431f590.png)
3.Linuxパーソナライズの画面が出るので、適当なユーザ名・パスワードを入力します。
![パーソナライズ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/1539e107-90e6-9291-0637-bac2a5962e99.png)
4.仮想マシンの名前を入力します。
![仮想マシン名入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/11e9f073-d2de-49b2-2ce7-13f14d93578a.png)
5.ディスク容量指定ダイアログが表示されますが、ここはデフォルトのままにします。
![ディスク容量指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/c74e6eec-16a9-ec02-7079-820ebee29d6f.png)
6.準備完了画面が表示されるので内容を確認し、問題なければ「完了」をクリックします。
![仮想マシン準備完了画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/64830b0c-8b19-30b5-bbea-0f3db90a706f.png)
7.自動的にVMが起動されます。
8.ユーザ名を入力する画面がもう1回出ます。
　※3でadminと入力しましたが、予約語だったので変更しています。
　　同じにするべきでしたね・・・
![ユーザ名入力（2回目）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/af6ce1ba-e3c1-f7b7-da13-fef7171ab7ad.png)
9.OSのインストールが実行されるのでしばらく待ちます。
10.インストールが完了し、ログイン画面になったら完了です。(画像はログイン後の画面です)
![インストール完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/950927/b25610ef-4447-5b9d-8634-50c36f836e94.png)

#最後に
簡単な内容ではありますが、読んでくださってありがとうございます。
今回せっかくVMを作成したので、色々やってみようと思います。
また記事にするかもしれないので読んでいただけると嬉しいです。

皆さんの2021年が良い年になりますように☆
herokuでback-ground-imageを表示させたい。


## 環境
ruby 2.6.5
rails 6.0.0
mysql 5.6

## 問題
ローカル環境では問題なく表示されていた背景画像が本番環境（heroku)では表示されていなかった。

## 試したこと

```config/environments/production.rb
# Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false
```

から

```config/environments/production.rb
# Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false
```

に変更
参照記事→https://qiita.com/___xxx_/items/fa15f358beba2b9389da
  
しかし期待された挙動はうまく行かなかった。
  
他の記事でも大概この内容で本番環境で挙動がうまく行っている傾向にあるものの、自分はダメだった。

## 解決策
  
2015年の少し古い記事を発見→https://www.cotegg.com/blog/?p=189
試してみる。

①cssからscssに変更
 
②合わせてscssの内容も変更

```main.css
.main {
  display: flex;
  background-image: url("../main-bg.png");      /* 画像のURLを指定       */
  background-size:cover;
  background-repeat:  no-repeat;
  background-attachment: fixed;
}
```

から

```main.scss
.main {
  display: flex;
  background-image: image-url("main-bg.png");      /* ここの記述を変更       */
  background-size:cover;
  background-repeat:  no-repeat;
  background-attachment: fixed;
}
```

に変更
ローカル環境で不具合がないことを確認

③プリコンパイル実施

```
% bundle exec rake assets:precompile RAILS_ENV=production
```

ここでコミットして本番環境にpushすることを忘れないこと。

```
% git push heroku master
```

本番環境にて挙動を確認。
  
うまく行った。
README.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# qiita\\\_links

-   [R5](https://qiita.com/satokikono/items/960eb39cdf0c2fbd3b93)
-   [R6](https://qiita.com/satokikono/items/4d56549b7fb85a936375)
-   [R7](https://qiita.com/satokikono/items/fc032c2ea7db454bac7d)
-   [R8](https://qiita.com/satokikono/items/d5322d99925797ab277d)
-   [R9](https://qiita.com/satokikono/items/31cb1efdf1900132edf4)
-   [R10](https://qiita.com/satokikono/items/8928d3006f064361cd7a)
-   [R11](https://qiita.com/satokikono/items/20cfac30798d56c9d6cc)



------
 - **source** ~/grad_members_20f/members/skona/README.org
超絶単純明快！！Pythonにおけるシングルクォーテーションとダブルクォーテーションの違い

結論：違いなし


サンプルコード等で意味ありげに使い分けてくるので気になっていましたが特にシステムに関与する差異は生じないようです。

JISキーボードを使用している為シングルクォーテーションの入力方法を毎度ググっていましたがもう辞めます。お疲れ様でした。

暗黙のルール的なものはあるのかもしれませんが初学者各位はシングルクォートの入力法をググるだけ時間の消費につながりますので使いやすい方で統一してはいかがかと。
R10.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 第１０回

チャート式Rubyの第５回目


## Fibonacci数列

    fib(n) = fib(n-1)+fib(n-2)
    0 1 1 2 3 5 8 13 21 ...

上記のようなFibonacci数列を再帰で求める。

assert\_equal.rb

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.blue
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
assert_equal(1, 2)
```

```ruby
def fib(n)
  return 0 if n==0
  return 1 if n==1
  return fib(n-1) + fib(n-2)
end

require './assert_equal'
[[0,0],[1,1],[2,1],[3,2],[4,3],
 [5,5],[6,8],[7,13],[8,21],[9,34]].each do |index, expected|
  puts assert_equal(expected, fib(index))
end
```

上記のコードを実行してみる

     ruby fib.rb
    true
    false
    true
    
    true
    
    true
    
    true
    
    true
    
    true
    
    true
    
    true
    
    true
    
    true


## 参考サイト

[チャート式ruby-Ⅴ](https://qiita.com/daddygongon/items/1bb27b8920c201d5c520)



------
 - **source** ~/grad_members_20f/members/skona/memo/R10.org
R7.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 第７回

チャート式Rubyの第３回目


## 条件分岐とArray.each

```ruby
def leap?(year)
  return case 
    when year % 400 == 0 ; true
    when year % 100 == 0 ; false
    when year % 4 == 0   ; true
    else                 ; false
    end
end

[2000, 1900, 2004, 1999].each do |year|
  p year
  p leap?(year)
end
```

上記のコードを実行してみる

    > ruby check_leap_year.rb
    2000
    true
    1900
    false
    2004
    true
    1999
    false

年数とうるう年か否かが判定されている。三項演算子でもスマートに書くことが出来るがcase文の方が理解しやすく感じる。


## 参考サイト

[チャート式ruby-lll](https://qiita.com/daddygongon/items/a550bde1ed6bff5217d8)



------
 - **source** ~/grad_members_20f/members/skona/memo/R7.org
RustのテストのTIPS

# 目次
1. [Rustは最初からテストが利用可能](#rustは最初からテストが利用可能)
1. [標準出力を出す](#標準出力を出す)
1. [テストを外す](#テストを外す)
1. [指定のテストだけ実行](#指定のテストだけ実行)
1. [シングルスレッドで動作](#シングルスレッドで動作)
1. [async/awaitのテスト](#asyncawaitのテスト)

---

#### Rustは最初からテストが利用可能

```rust
#[cfg(test)]
mod tests {
    #[test]
    fn test_calc() {
        assert_eq!(2, 1+1);
    }
}
```

\#[cfg(test)]は条件付きコンパイルでテストの時のみコンパイルされます。
\#[test]はそれがテストコードであることをしまします。
以下でテストを実行します。

```sh
$ cargo test

running 1 test
test tests::test_calc ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
---

#### 標準出力を出す
テストでは通常、標準出力は出ません。

```rust
#[cfg(test)]
mod tests {
    #[test]
    fn test_calc() {
        println!("Hello World!");
        assert_eq!(2, 1+1);
    }
}
```

nocaptureオプションをつけると出ます。最初の--はcargoのオプションでは無く、testのオプションを示すための区切り文字です。

```sh
$ cargo test -- --nocapture

running 1 test
Hello World!
test tests::test_calc ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```

またはshow-output。こちらの方が見やすいです。

```sh
$ cargo test -- --show-output

running 1 test
test tests::test_calc ... ok

successes:

---- tests::test_calc stdout ----
Hello World!


successes:
    tests::test_calc

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
---

#### テストを外す

\#[ignore]で外せます

```rust
#[cfg(test)]
mod tests {
    #[test]
    #[ignore]
    fn test_calc() {
        assert_eq!(2, 1+1);
    }
}
```

```sh
$ cargo test

running 1 test
test tests::test_calc ... ignored

test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
```

逆にignoreだけテストすることも可能です。例えば重い処理やローカルでは動かないテストは#[ignore]にしてCIなどでのみテストさせます。

```sh
$ cargo test -- --ignored

running 1 test
test tests::test_calc ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
```
---

#### 指定のテストだけ実行

テストの引数に文字列をつけると、その文字列にマッチしたテストだけ実行されます。ここは--はいらないです。

```rust
#[cfg(test)]
mod tests {
    #[test]
    fn test_calc1() {
        assert_eq!(2, 1+1);
    }
    
    #[test]
    fn test_calc2() {
        assert_eq!(3, 2+1);
    }
}
```

```sh
$cargo test

running 2 tests
test tests::test_calc1 ... ok
test tests::test_calc2 ... ok

$ cargo test 2

running 1 test
test tests::test_calc2 ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out
```
---

#### シングルスレッドで動作

テストは複数スレッドを使って実行されます。しかしDBアクセスなど共通リソースにアクセスするテストでは実行する順番によっては失敗する可能性があります。実行するスレッド数を1にすることで、防ぐことができます。ちなみに無指定の時は何スレッドで動作するかわかりませんでした。多分CPUのコア数と同じなんだと思います。

```sh
cargo test -- --test-threads=1
```

---

#### async/awaitのテスト
async/awaitを使った場合通常の\#[test]ではコンパイルできません。async/awaitの実行環境が無いと動かないので、ここではtokioを使ってテストします。

```rust:Cargo.toml
[package]
name = "calc"
version = "0.1.0"
edition = "2018"

[dev-dependencies]
tokio = {version="~0.2", features=["macros", "rt-core"]}
```

```rust
async fn acalc(a: i64, b: i64) -> i64 {
    if a > b {
        a - b
    } else {
        a + b
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_calc() {
        assert_eq!(2, acalc(5, 3).await);
    }
}
```
R9.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 第９回

チャート式Rubyの第４回目


## assert\_equal

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.blue
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
assert_equal(1, 2)
```

上記のコードを実行してみた

    true
    false

colorizeしたため結果として(1,1)のとき青文字でtrue(1,2)のとき赤文字でfalseと出力された。


## rubular

正規表現を使用して文字情報を取り出せるらしい。テスト文字列

    #+qiita_id : daddygongon

正規表現として(.+)と入力すると

    #+qiita_id : daddygongon

と出力され取り出すことが出来る。


## 参考サイト

[assert\_equal](https://qiita.com/daddygongon/items/f6cea87314ee26e130ea)

[rubular](https://qiita.com/daddygongon/items/5e2de543400fe56be768)



------
 - **source** ~/grad_members_20f/members/skona/memo/R9.org
R8.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 第８回


## rake

rubyでいうmakeやantにあたるらしい。ちょっとしたタスクを便利にしてくれるもののようだ。

```ruby
desc 'git pull'
task :pull do
  p comm = "git pull origin main"
  system comm 
  exit
end

desc 'git push'
task :push do
  p comm = "git add -A"
  system comm
  p comm = "git commit -m ＼'hoge＼'"
  system comm
  p comm = "git pull origin main"
  system comm
  p comm = "git push origin main"
  system comm
  exit
end

```

いつもの作業をRakefileに覚えさせることが出来るようだ。

    > rake

rakeの後に続けてpullやらpushを入力すると上記で覚えた作業をこなしてくれる。


## 参考サイト

[チャート式ruby-appendix](https://qiita.com/daddygongon/items/1c2d6d2895333ccf5e62)



------
 - **source** ~/grad_members_20f/members/skona/memo/R8.org
R6.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 第６回

チャート式Rubyの第２回目変数とメソッドについて


### 受け取った引数を変数に代入し表示するプログラム

```ruby
name = ARGV[0]
puts "Hello, #{name}"
```

上記のコードを実行してみる

    > ruby name_variable.rb Rudy
    Hello, Rudy


## メソッド

```ruby
def hello(name)
  puts "Hello #{name}."
end
name = ARGV[0]
hello(name)
```

こちらのコードも実行してみる

    > ruby hello_methd.rb Rudy
    Hello Rudy


## TDD

こうしたcoding方法はTDD（テスト駆動開発）というらしい手順としては・テストを作る・エラーバーを出す・エラーをなくす・リファクタリング


## 参考サイト

[チャート式ruby-ll](https://qiita.com/daddygongon/items/c51f3e0695174bb3c508#clean-code-that-works)



------
 - **source** ~/grad_members_20f/members/skona/memo/R6.org
Macの不調にはSMCリセットが効くぞぉ・・・(Intel Mac)

# はじめに
買って2ヶ月程経つ私のお気に入りMacbook Pro（16インチ)。
途中でM1 Macbookの登場とかありましたが、別に欲しくないもん・・・(欲しい)
で、まぁ2ヶ月間不調無くしばらく動作していたのですが、急遽初期化をしなければならない事情が出てきたので初期化を行ないました。
すると・・・
初期化が終了し、起動後キーボード向かって右上のUSB Type-C端子が効かんやん！！って状態になって大焦りしたのでここに対処法をメモ書きしておきます。
買って2ヶ月、Apple Careにも加入していないのでマジで顔が真っ青になりました。

# 症状
キーボード向かって右上のTypeC端子だけが反応しない。逆に言うと他は反応する。
ケーブルが壊れているのかと思い、AnkerのUSBハブを取り付けるも反応せず。
コネクタ側が故障しているのかとも思ったが、大してコネクタに対し負荷のかかる使い方をしていないので不思議だなぁと思いながら、高額な修理代を思い浮かべながら顔が真っ青になっていった（俺の症状言ってどうするんダ）

# SMCリセットという魔法
intel系Macには、System Management Controllerと呼ばれるシステム管理機能が搭載されています。
これらは主に電源管理やバックライトなどを管理しているもので、これに何らかの異常が発生すると各パーツとの連携が取れなくなり、給電を停止したりファンを高速回転させたりという措置をとるようです。
どうやらこれは「電源周りが故障したまま給電をして火災発生などのトラブルが起きないようにする」「ファンを停止させてCPUが異常加熱するのを防ぐ」というように連携が取れなくなれば必ず安全な方に転ぶようなシステムになっているからだそうです。

で、大抵は本当に壊れているわけではなく、システム構成から変な動作になっているだけなので、この類のトラブルはSMCをリセットすると治ることが多いようです。
以下ではMacbookを例にご紹介します。

## Apple T2チップが搭載されているMacでは
+ Macを終了（電源を落とす）
+ Shift(右)とOptionとcontrolを7秒間押し付ける
+ 追加で電源ボタンも加え、さらに7秒間押し続ける
+ キーを離してMacを普通に起動

簡単ですね。
## T2チップ非搭載のMacでは

+ Macを終了（電源を落とす）
+ ShiftとOptionとcontrolと電源ボタンを同時に10秒間押し付ける
+ キーを離してMacを起動

デスクトップでは手順が異なるようなので、詳しくは[こちらのサイト様](https://www.capa.co.jp/archives/23432)が非常に分かりやすいです。

# nvram/PRAMリセット
SMCリセットでも治らない場合はnvram、またはpramのリセットにより改善する可能性があります。
nvramとpramは設定を保存しているメモリだそうで、古い言い方がPRAM、最近のMacでの呼び名がnvramだそうです。

## nvram/PRAMリセット方法
Optionとcommandと「P」「R」キーを同時に20秒くらい長押しすると完了します。
この間Macは2回再起動します。起動音が鳴るMacや鳴る設定にしているMacでは、起動音が2回流れるので、それを合図に手を離します。

## 補足
nvram/PRAMをリセットすると、一部設定情報もリセットされるので、起動後に画面の輝度等が変わっている場合があります。

# まとめ
今回の事件で学んだことは

+ USBが効かなくなったりファンが高速回転し出しても慌てず騒がず落ち着いて
+ 顔青ざめるな
+ nvram/PRAMのリセットとSVCリセットを試してみるのだ。

ということでした。
これでもだめなら・・・青ざめるしか無い・・・
【Python】Requestsモジュールのプロキシ，リダイレクト，SSL認証の設定方法

やりたいこと


- Proxyの設定
- オートリダイレクトOFF
- SSL認証OFF
- SSL認証OFF時でリクエストする際に表示されるWarningの非表示


```python
import requests
import ssl
import sys

#Warningの非表示
if not sys.warnoptions:
    import warnings
    warnings.simplefilter("ignore")

#プロキシ設定
proxies = {
  "http(またはhttps)": "<プロキシサーバ>:<ポート番号>",
}

url = "<URL>"
#引数にプロキシ設定，オートリダイレクトOFF，SSL認証OFFを指定してリクエスト
r = requests.get(url,proxies=proxies,verify=False,allow_redirects = False)
print (r)
```
R5.org

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 

LGTMお願いします^\_^


# 第5回

チャート式Rubyの第1回目


## Ruby

    Hello world.

という文章を出力するプログラムを作成する。

Rubyで文字を打ち出すには様々な種類がある

| print | 要改行   |
|:------|:---------|
| puts  | 自動改行 |
| p     | debug    |

その他にもいくつかあるらしい

putsでコードを書いて実行してみた                 

    > ruby Hello.rb
    What's your name?
    KONO
    HELLO, KONO


## 参考サイト

[チャート式ruby-Ⅰ](https://qiita.com/daddygongon/items/1b0f0ff3fb9d60418289)



------
 - **source** ~/grad_members_20f/members/skona/memo/R5.org
USBカメラを使って、なるべく楽にラズパイでタイムラプスを作る。



# 動機
- 寒さが厳しくなってきた2020年12月下旬、布団を蹴って寒くて目が覚めることがよくある。
- 寝ている間、自分がどんな動きをしているのか知りたい。
- 寝ている自分をタイムラプスで撮影しよう。
- 細かいところは一旦気にしない。
- 可能ならコードは書かずに実現したい。

# 流れ
## 機器の購入
- Raspberry Pi 4を購入
    - Raspberry Piを触るのが初めてだったのでスターターキットをRSで購入。1万円くらい。
    - https://jp.rs-online.com/web/generalDisplay.html?id=raspberrypi

<img width="500" alt="Screen Shot 2020-12-23 at 13.26.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/7ec7e5e4-7f12-b7f2-db2a-ec78c405a4be.png">

- USBカメラを購入
    - Raspberry Pi カメラモジュールが4000円以上したのでこれを使うのは断念。
        - https://www.switch-science.com/catalog/2713/
    - 安そうなUSBカメラをビックカメラで購入。1000円ちょっと。設置も簡単そう。
        - https://www.biccamera.com/bc/item/1526273/

<img width="500" alt="Screen Shot 2020-12-23 at 13.29.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/e7b4638b-1d98-2697-0160-47c6676f49e0.png">


## Raspberry Pi 4のセットアップ
- スターターキットの案内に従い、下記のサイトを参考に組み立てる。
    - https://www.okdo.com/getstarted/
    - 付属のSDカードから簡単にOSをインストールできた。
- 細かい設定はイチケンさんの動画を参考に。
    - https://youtu.be/zTOXdULHNsA

## sshとVNCを可能にする
- ラズパイとモニターを直接繋げておくのは面倒なので、別端末からラズパイを操作できるようにする。
- 下記の記事を参考に。
    - ssh
        - https://blog.ko31.com/201803/raspi-ssh-setup/
    - VNC
        - https://blog.ko31.com/202004/steps-to-configure-the-raspberry-pi-raspberry-pie-to-connect-to-vnc/

## USBカメラの確認
<img width="300" alt="IMG20201223133823.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/4c210f23-70c5-2c95-1ba1-0892caa0a8e1.jpeg">

- ラズパイにUSBカメラを繋げ、USBカメラが動作しているか確認する。
- guvcviewというものを使用
    - 参考
        - https://www.hiro345.net/blogs/hiro345/archives/18787.html

```
# インストール
sudo apt-get -y install guvcview

# 起動
guvcview
```

- VNCでラズパイに繋ぎ、guvcviewでUSBカメラを試しているところ。
    - カメラ設置の際に写り具合を確認できる。

<img width="400" alt="Screen Shot 2020-12-23 at 13.45.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/a98a6d49-306d-7b56-58a2-1d961b01941a.png">


## 定期的に撮影する
- 撮影はuvccaptureを使用。
    - 参考(先のリンクと同じ): https://www.hiro345.net/blogs/hiro345/archives/18787.html

```
# インストール
sudo apt-get -y install uvccapture

# サイズとファイル名を指定して撮影。ファイル名が重複しないようUNIX時刻を使用。
uvccapture -m -x1280 -y720 -o$(date +\%s).jpg
```

- cronで定期実行する。とりあえず5分間隔。画像サイズは適当。
    - 5分ごとにUSBカメラで撮影された画像ファイルが生成される。

```
# crontab -eを実行して次のように記述
*/5 * * * * uvccapture -m -x1280 -y720 -o$(date +\%s).jpg
```

## 画像からライプラプスに変換する
画像がある程度溜まったら、それらを使ってタイムラプスに変換する。

- mencoderを使用。
    - 参考: https://www.raspberrypi.org/documentation/usage/camera/raspicam/timelapse.md

```
# インストール
sudo apt-get install -y mencoder

# 対象となる画像ファイル一覧をテキストファイルに落として
ls *.jpg > stills.txt

# タイムラプスに変換(参考サイトのコマンドそのまま)。timelapse.aviという動画ファイルが生成される。
mencoder -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=16/9:vbitrate=8000000 -vf scale=1920:1080 -o timelapse.avi -mf type=jpeg:fps=24 mf://@stills.txt
```


# 寝ている自分を撮ってみて
プライバシーの観点から動画のアップロードはしないが撮影には成功した。
ただ、分かっていたけど真っ暗で何も映らず。朝日が差し込んでから2時間分くらいは写っていた。
布団を蹴っている自分はまだ撮影できていない。

# 最後に
機器購入は別にして、試しながらで大体1時間半くらいでできた。
USBカメラは設置が楽だった。
コードは書かずにコマンドだけで一応できた。
[Xcode 12] [Swift] guard節で複数条件を判定する時の推奨コーディングスタイル

Xcode 12でguard節の自動フォーマットが変わりました。
Xcode 12以降でのコーディングスタイルについての考察です。

# Xcode 11以前の自動フォーマットと、私個人のコーディングスタイル

```swift
func foo() {
    // Xcode 11の自動フォーマット。letの位置がズレていて読みづらい…
    guard let hoge = hoge,
        let fuga = fuga else {
            print("guarded")
            return
    }
    print("\(hoge) - \(fuga)")
}

func bar() {
    // 上だと読みづらいので、Xcode 11ではこう書いてました。
    guard
        let hoge = hoge,
        let fuga = fuga
        else {
            print("guarded")
            return
    }
    print("\(hoge) - \(fuga)")
}
```

# Xcode 12以降の自動フォーマット

```swift
func foo() {
    // Xcode 12の自動フォーマット。letの位置が合って読みやすくなりました。多分これが推奨のスタイル。
    guard let hoge = hoge,
          let fuga = fuga else {
        print("guarded")
        return
    }
    print("\(hoge) - \(fuga)")
}

func bar() {
    // Xcode 11以前のスタイルだと、elseの位置が変わりました。
    // 別にこれでも悪くはないけど、Xcodeが上の自動フォーマットをしてくれるなら、このスタイルで書く必要性はなくなりました。
    guard
        let hoge = hoge,
        let fuga = fuga
    else {
        print("guarded")
        return
    }
    print("\(hoge) - \(fuga)")
}
```

[Xcode 12のリリースノート（英語）](https://developer.apple.com/documentation/xcode-release-notes/xcode-12-release-notes)では、前者 `func foo()` のスタイルが例示されていますので、Xcode 12以降では前者のスタイルで書くのが良さそうです。

番外：

```swift
func foo() {
    // returnするだけならこれでも良いかと思われます。
    guard let hoge = hoge else { return }
    guard let fuga = fuga else { return }
    print("\(hoge) - \(fuga)")
}
```