OmniAICreator/Qiita-1.07M huggingface dataset:
.NETCore×WPFアプリのMain関数をカスタマイズする

##はじめに
WPFのMain関数を書き換えたく色々調べてたのですが
少し手こずったのでメモ

##環境
- WPF
- .Net Core 3.1
- Visual Studio 2019

##WPFアプリのMain関数について

WPFのプロジェックトにおいて、一番最初に呼ばれる関数はApp.xaml.csファイルのMain関数です。
ただし、App.xaml.csファイルにはMain関数の記載はありません。
コンパイル時に自動で生成されるのです。

WPFのプロジェクトを実行し、App.xaml.csファイル上でメソッド一覧を確認すると`Main()`が存在するかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/282a23e4-8ffd-c514-6c23-e91ed6d16c7f.png)

これをクリックすると、Main関数の中身が確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/211356af-1285-ff34-b1f6-86761e8fb31a.png)

ただしこのMain関数はビルド時に自動で生成されるものであり、このApp.g.i.csファイル内で書き換えてもビルド時に上書きされてしまいます。
このMain関数を書き換えたい！カスタマイズしたい！という要求も当然のようにあり
以下のような記事がたくさん見つかります。

[WPF：Mainメソッドを書き変えるには？](https://www.atmarkit.co.jp/ait/articles/1511/04/news027.html)

##Main関数を書き換えてみる

上記のようなサイトを参考にすると、App.xamlファイルのビルドアクションを**アプリケーション定義**から**ページ**へと変更すればOKと書いてあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/c48f5242-2dd6-2ac4-2624-5b6d56764ca0.png)

ただ、現状の環境では**ページ**に変更しようとすると以下のようなエラーが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/ac9cd1e3-9943-111c-2839-220060673f87.png)


##解決策

解決策を色々と探したところ、以下のページにたどり着きました。
[change App project to DLL problems](https://github.com/dotnet/wpf/issues/2812)

> .xaml are all treated as Page items by default, unless they are named App.xaml (C#) or Application.xaml (VB).
> App.xaml/Application.xaml is treated as ApplicationDefinition by default.
> To change this default behavior, you have to override the implicit behavior.

雑に訳すと
App.xamlはデフォルトてアプリケーション定義として扱われているから直すならオーバーライドして。という感じですね。

ということで、wpfプロジェクトのプロジェクトファイルを開き、`<PropertyGroup>`にEnableDefaultApplicationDefinitionの要素を追加します。

```wpfapp.csproj

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
    <EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>
  </PropertyGroup>
```

一度ソリューションをクリーンした後に、再度App.xamlのビルドアクションを**ページ**に変更します。
今回はエラーが発生しないはずです。

その後、App.xaml.cs内にMain関数を追加してあげるとアプリ起動時に追加したMain関数が呼ばれるようになるかと思います。

Main関数の書き方は上で紹介したリンクを参照ください。

##最後に
最近のバージョン変更によるものか、紹介されたサイトの通りではうまくビルドアクションを変更できなかったので少し手間取りました。
同じような人の参考になれば幸いです。
MetricFireでHerokuアプリの監視＆ダッシュボード　アドオンのインストール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/86dd1905-29d6-3f98-56bc-dfc81288052d.png)

MetricFireのHostedGraphite（通称HG)は、一連のオープンソース監視ツールから完全なインフラストラクチャおよびアプリケーション監視プラットフォームを提供します。 設定に応じて、[Hosted Prometheus](https://www.metricfire.com/?_ga=2.226393370.1450283034.1605507820-2038175526.1567400116#)または[Hosted Graphite](https://www.metricfire.com/?_ga=2.226393370.1450283034.1605507820-2038175526.1567400116#)のいずれかを選択し、必要なすべてのメトリックを美しいGrafanaダッシュボードにリアルタイムで表示できます。 HostedGraphiteは、アプリケーションに関する大量のデータを簡単に測定、分析、および視覚化できるようにするさまざまなツール、アドオン、およびプラグインを提供します。



[HG Heroku Monitoring＆Dashboardsアドオン](https://elements.heroku.com/addons/hostedgraphite)をHerokuアプリにインストールし、プラットフォームアドオンヘッド内でダッシュボードに移動して、[Import Dashboard]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/1d86be1c-ce1f-c4e3-209c-17e9c25adfa7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/29370a6f-f8a8-fb70-e56d-66f63a147412.png)

次に、このjsonファイルをダウンロードして、ダッシュボードにインポートします。 Herokuモニタリングダッシュボードがすぐに読み込まれるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/ee02aa05-a019-bb1d-ed24-dd9ca58a2afc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/805edb52-0cf3-5a0f-23ee-0fdfb816eb2f.png)

このアドオンをHerokuアプリで使用する方法について詳しく知りたい場合は、エンジニアの1人と一緒に[デモを予約](https://www.metricfire.com/demo-japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Installing%20the%20HG%20Heroku%20Monitoring%20%26%20Dashboards%20Add-on.)してください。
CORSの簡単な確かめ方 curl

```ruby
$ curl "https://your-site.com"  -H "origin:test.com" -v 2>&1 | grep Access-Control-Allow
< Access-Control-Allow-Origin: test.com
< Access-Control-Allow-Methods: POST, GET, OPTIONS
< Access-Control-Allow-Headers: Accept-Encoding, Origin, Authorization, Accept, If-Modified-Since
< Access-Control-Allow-Credentials: true
```
Mac に RISC-V の開発環境構築

# Mac に RISC-V Toolchain をインストール

Mac に RISC-V の クロスコンパイラ等が含まれる、RISC-V Toolchain をインストールする。

## インストール

### homebrew をインストールする。
homebrew は大抵の人が入れていると思うのでここはスキップ。

### tap する

```bash
$ brew tap riscv/riscv
```
  - tap について
    - 公式ではないリポジトリをHomebrewに追加するもの。
    - install, uninstall, update ができるようになる。
    - github で `<user>/homebrew-hoge` となっているリポジトリは `brew tap <user>/hoge` で tapできる。

### ToolChain をインストールする
**64bit** だけでいい人

```
# brew install riscv-tools
```

**32bit** も欲しい人

```
# brew install riscv-gnu-toolchain --with-multilib
```

## アップデート

- アップデートは以下のコマンド
   `brew reinstall --build-from-source riscv-gnu-toolchain`

## インストールでエラーが出ました
```
fatal: Needed a single revision
Unable to find current revision in submodule path 'qemu/roms/u-boot'
Failed to recurse into submodule path 'qemu'
Error: Failed to download resource "riscv-gnu-toolchain"
Failure while executing; `git submodule update --init --recursive` exited with 1. Here's the output:
fatal: Needed a single revision
Unable to find current revision in submodule path 'qemu/roms/u-boot'
Failed to recurse into submodule path 'qemu'
```

- とりあえずqemuを削除してもう一回手動でやってみる

```
$ cd ~/Library/Caches/Homebrew/riscv-gnu-toolchain--git
$ rm -rf qemu
$ git submodule update --init --recursive
$ brew install riscv-gnu-toolchain --with-multilib
```

できた

## Big Sur の人

### エラーが出て make に失敗します！！！
VSCodeで文字コードを変える

#### 1

![截圖 2020-11-18 11.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392332/203571ff-cec6-21f3-248c-78265a458f1b.png)

VSCode右下の文字コード（画像ではutf-8）をクリックする

#### 2

![截圖 2020-11-18 11.40.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392332/0d43580d-bcf3-cf31-dfd6-55e74f571016.png)

VSCode真ん中上にドロップダウンメニューが開く。そこのReopen with Encodingをクリックする

#### 3

![截圖 2020-11-18 11.40.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392332/223adc91-021e-e28d-f959-fe5ec62f0b15.png)

好きな文字コードを選ぶ。
C#エクセルの印刷方法

<p><strong>エクセルの印刷方法がエクセルで行われるなら、簡単だそうですが、プログラマー達はC#で作業したいと思っているなら、どうするかしら？今日はSpire.XLSというライブラリを紹介することにします。そして、「通常使うプリンターで印刷」「指定するプリンターで印刷」「サイレント印刷」という三つの方法でエクセルを印刷する方法を見せてあげましょう。</strong></p>
<h4>下準備</h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/download-presentation-for-net-free.html">Free Spire.XLS</a>無料版をダウンロードしてください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201118/20201118110355.png" alt="f:id:lendoris:20201118110355p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>2.Visual Studioを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.XLS.dllを参照に追加してください。</strong></p>
<p><strong>（Net 4.0を例としたら、デフォルトパスは“Bin→NET4.0→XLS.dll”というようです。）</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201118/20201118110552.png" alt="f:id:lendoris:20201118110552p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>通常使うプリンターで印刷</strong></h4>
<p><span style="color: #d32f2f;"><strong>ただworkbook.PrintDocument.Print()メソードを使ってOKです。</strong></span></p>
```c#
using Spire.Xls;

namespace ConsoleApplication26

{

class Program

{

static void Main(string[] args)

{



Workbook workbook = new Workbook();

workbook.LoadFromFile("Sample.xlsx");

workbook.PrintDocument.Print();

}

}

}
```
<h4>指定するプリンターで印刷</h4>
<p> </p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20201118/20201118110649.png" alt="f:id:lendoris:20201118110649p:plain" title="" class="hatena-fotolife" itemprop="image" /><br /><span style="color: #d32f2f;"><strong>ページ設定で印刷の向き・用紙サイズ・印刷範囲などを設定することができます。</strong></span></p>
<h4> サンプルコード </h4>
```c#
//印刷範囲を設定します。

sheet.PageSetup.PrintArea = "B2:F8";



//タイトルを印刷します。

sheet.PageSetup.PrintTitleColumns = "$A:$B";

sheet.PageSetup.PrintTitleRows = "$1:$2";



//印刷の順を設定します。

sheet.PageSetup.Order = OrderType.DownThenOver;

sheet.PageSetup.Order = OrderType.OverThenDown;



// PrintDialogを設定します。

PrintDialog dialog = new PrintDialog();

dialog.AllowPrintToFile = true;

dialog.AllowCurrentPage = true;

dialog.AllowSomePages = true;



//片面印刷します。

dialog.PrinterSettings.Duplex = Duplex.Simplex;



//印刷範囲を設定します。

dialog.PrinterSettings.FromPage = 0;

dialog.PrinterSettings.ToPage = 8;

dialog.PrinterSettings.PrintRange = PrintRange.SomePages;



//部数を設定します。

dialog.PrinterSettings.Copies = 5;



//プリンターの名前を設定します。

dialog.PrinterSettings.PrinterName = "HP LasterJet P1007";



//印刷します。

workbook.PrintDialog = dialog;

PrintDocument pd = workbook.PrintDocument;

if

(dialog.ShowDialog() == DialogResult.OK)

{

pd.Print();

}
```
<p> </p>
<h4>サイレント印刷</h4>
```c#
using Spire.Xls;

using System.Drawing.Printing;

namespace ConsoleApplication26

{

class Program

{

static void Main(string[] args)

{



//Excelをロードします。

Workbook workbook = new Workbook();

workbook.LoadFromFile("Sample.xlsx");



//サイレント印刷します。

workbook.PrintDocument.PrintController = new StandardPrintController();

workbook.PrintDocument.Print();

}

}

}
```

<p> </p>
<p> </p>
<p> </p>
[CSS]background-size:cover;とbackground-size:contain;の違いとポイント

# background-size:`cover`;

`デザイン`　＞　画像情報

画像が全て入らなくてもいいので、余白なく背景を画像で埋めたいときに使用。
余白を埋めるために画像を伸ばすのではなく、`等比率で伸縮。`

![スクリーンショット 2020-11-18 11.14.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/67e7e7e0-0f02-99fc-71e6-a7366b26ca1a.png)

# background-size:`contain`;

`画像情報`　＞　デザイン

背景色が見えてもいいので、画像が切れることなく全体を見せたいときに使用。
画像全体を見せるための`伸縮は等比率。`


![スクリーンショット 2020-11-18 11.17.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/6dd6ac64-4872-6183-7b1f-e5af2bb014c7.png)
※水色は余白

> 上記のようなレイアウトにするには以下３つの注意が必要
1. 余白は親要素の背景色が表示されるので、親要素に`background-color:xxxx;`が必要
2. `background-repeat: no-repeat;`を入れないと余白を埋めるために画像が繰り返され変な感じになる
3. 画像をセンタリングするために`background-position:center;`が必要

# ソースコード

```html
<!-- 画像部分のみ抽出 -->

<!-- coverの方 -->
<div class="card__picture">
   <div class="card__imge card__imge--1"></div>
</div>                                             
    
<!-- containの方 -->                 
<div class="card__picture">
   <div class="card__imge card__imge--2"></div>
</div>             
```

```css
/* ------- 画像 スタイル ------- */

/* サイズと背景色 */
.card__picture{
    width: 500px;
    height: 250px;
    background-color: aquamarine; 
}

/* センタリングと繰り返しなし */
.card__imge{
    height: inherit;
    background-position:center;
    background-repeat: no-repeat;
}

/* 各設置画像とsizeの設定 */
.card__imge--1{
    background-image: url(../img/coverSample.jpg);
    background-size: cover;
    
}
.card__imge--2{
    background-image: url(../img/containSample.jpg);
    background-size: contain;    
}
```
# 参考記事
https://gimmicklog.com/css3/747/
https://developer.mozilla.org/ja/docs/Web/CSS/background-size
# 次回
[[CSS]画像の上に単色フィルター](https://qiita.com/nakamurashun0621/items/abce76fd82219f475fdd)
FileMaker引数2個以上の受渡し

FileMakerスクリプトの引数の受け渡しについて書こうと思います。

よく見かけるのは、
スクリプト実行[指定:一覧から;「TEST」;引数:＄A & ¶ & ＄B]
のような改行区切り。

これってすごい面倒だなと思うんですよ。
順番は固定しておかないといけないし、そのために変数も分かりやすくとか
後々面倒だったり。
受け取る側もGetValue ( Get ( スクリプト引数 ) ; 1 )になって
何を受け取ったか分からない。（変数名で大体分かるがおおよそ属人化に繋がる）
まぁ作るのは楽だからどうのこうのいうつもりはないですが。

そこで目を付けたのはJSON関数
（大袈裟に書いてますが、大体の人が分かってると思う。）

スクリプト実行[指定:一覧から;「TEST」;引数:JSONFormatElements ( 
 JSONSetElement ( $JSON ;
 [  "Layout" ; "レイアウト1"  ; JSONString] ;
 [  "Record" ; "TEST::主キー"  ; JSONString] ;
 [  "Script"     ; "移動" ; JSONString] 
))

上記で受け渡せば、受け渡すスクリプトは1個で済むし、JSONGetElement ( $JSON ; "Layout" )のように見たまんまわかりやすいって思うんですよ。

最近はスクリプトも名前で指定できるからスクリプト名を指定すれば思うスクリプトも動くし、
もっと汎用的になると思う。
汎用的っていいよね。一個作っておけばいいんだから。

だからなんだと言われるとそこまでなのですが...


JSONなんて使った事ないって方がいれば是非試して欲しい。


まぁ社内的に自分の思うようにシステム作ったら怒られるからあんまり使えないんだけどね。
自分だけが使うシステムはこればっかりなんだけど。
理解して欲しいよ。少しは。
はじめてのWSUSの導入

##経緯
自社のサーバを確認していたところ、何も使用していないサーバが一つ存在していた。
その為、今までWSUSの導入がされていなかったので、このサーバをWSUSサーバに仕立てようと奮闘した議事録を記します。

##本記事について
WSUSを導入するにあたり、「WSUS」、「IIS」のインストールが必要になる。
詳細な方法は参考URLにある記事に詳しく記載されている為、ここでは、**躓いたり苦戦した内容**を記載する。
またAD環境下の為、ADで配布できるように対応した。


###・GPOでWSUSサーバに切り替える設定
　GPOの設定内容は、参考サイトに詳しく記載されてる『コンピュータの構成』から設定を有効するのだが、グループポリシーの管理にて、『ユーザーアカウント』に対してグループポリシーオブジェクトを割り当てたので、ポリシーの反映がされていなかった。。。
　正しくは、
**『コンピュータの構成』のグループポリシーオブジェクトに対しては、『コンピューターアカウント』**
**『ユーザーの構成』のグループポリシーオブジェクトに対しては、『ユーザーアカウント』**
に割り当てる必要があった。

###・GPOの確認
　正しくGPOが当たっているか確認するために以下のコマンドをコマンドプロントで実行して確認した。
また、実行する際には管理者権限で起動したコマンドプロントでないと正しく表示されない為、そこも注意するところだ。

```
gpresult /r
```


　ADでのGPO設定をあまり理解していなかった為に躓いた。

##今回のインストールで大変お世話になった参考サイト
#####▼こしぞーのひとり情シス　
　https://www.hitoriit.com/entry/2019/03/26/000000

#####▼文系インフラSEの勉強日記
　https://pknk.hatenablog.com/entry/2019/02/03/145552

#####▼（）のブログ
　https://mitomoha.hatenablog.com/entry/2019/05/06/014331
CloudFormationでEC2を構築した時にEBSにTagsを付与できない

かゆいところに手が届かない。

```yaml

BlockDeviceMappings:
  - DeviceName: /dev/sda1
    Ebs:
      VolumeSize: 50
    Tags # 不可能
      -  Key: "keyname1"
         Value: "value1"
```
公式が情報を[ナレッジセンターに出している](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-instance-tag-root-volume/)が、余計な情報が多すぎる、ここだけでいい。

```yaml
UserData:
  Fn::Base64: !Sub |
     #!/bin/bash
     AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone)
     AWS_REGION="`echo \"$AWS_AVAIL_ZONE\" | sed 's/[a-z]$//'`"
     AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
     ROOT_VOLUME_IDS=$(aws ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId)
     aws ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=Name,Value={つけたい名前}
```

`aws ec2 create-tags`するためにはIAMロールとポリシーが必要だから、IAMを書いているとここまでする必要あるのか？ともやもやする。
ちなみに新規にVolumeを作るときは[普通に対応](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-ebs-volume.html)している。

```yaml

Type: AWS::EC2::Volume
Properties: 
  AutoEnableIO: Boolean
  AvailabilityZone: String
  Encrypted: Boolean
  Iops: Integer
  KmsKeyId: String
  Size: Integer
  SnapshotId: String
  Tags: 
    - Tag # だよね～
  VolumeType: String
```
CloudFormationで必要なだけインスタンス立ててから、LambdaでEC2のTagから拾ってきて一括付与でもいいんだけど、めんどくさ過ぎるからそもそも対応してほしい。
ransackでの検索機能


##検索機能の実装(ransack)


**したいこと**
投稿の一覧ページ(services_index)に検索機能の追加
サービス名、エリア名、カテゴリーでの検索
いいねの多い順、投稿順での並び替え

**環境**
Rails 5.2.4.4

**前提**

```service.rb
belongs_to :user
belongs_to :category
has_many :likes
```

```category.rb
has_many :services
```

```like.rb
belongs_to :user
belongs_to :service
```

###手順
**gemの追加**

```SQL:Gemfile
gem 'ransack'
```
追加したら`bundle install`


**controllerの変更**

```services_controller.rb
def index
#省略
    @categories = Category.all
    # 検索フォームからアクセスした時の処理
    if params[:q].present?
      @search = Service.ransack(search_params)
      @q = Service.ransack(params[:q])
      @services = @q.result(distinct: true)
      @services = @q.result.page(params[:page]).per(9)
    # 検索フォーム以外からアクセスした時の処理
    else
      params[:q] = { sorts: 'id desc' }
      @search = Service.ransack()
      @services = Service.all.page(params[:page]).per(9)
    end
end

#省略

private
  #省略
  def search_params
    params.require(:q).permit(:name, :category_id, :area, :price, :introduction, :user_id, :image)
  end
end
```
**viewの変更**

```services/index.html.erb
<!-- 省略 -->

<%= search_form_for @search, url: services_path do |f| %>
  <%= f.label :name, "サービス名" %>
  <!-- "name_cont"はnameカラムの単語の一部分を含むものを検索するという意味 -->
  <%= f.search_field :"name_cont" %>
  <%= f.label :area, "対応エリア" %>
  <%= f.search_field :"area_cont" %>
  <%= f.label :category_id, "カテゴリー" %>
  <%= f.collection_select :category_id_eq, @categories, :id, :name %>
  <%= f.label :category_id, "並べ替え" %>
  <%= f.select( :sorts, { '指定しない': 'id desc', 'いいねの多い順': 'likes_count desc', '出品の古い順': 'updated_at asc', '出品の新しい順': 'updated_at desc' } , { selected: params[:q][:sorts] }) %>
  <%= f.submit "検索" %>
<% end %>
```
<!-- 省略 -->


いいねの多い順での並び替えにはransackerを使い
検索機能を拡張しないといけないみたいなのでモデルに以下を追記
これで`likes_count`という条件でいいねの多い順に並び替えできるようにする

```app/models/service.rb
#省略

ransacker :likes_count do
  query = '(SELECT COUNT(likes.service_id) FROM likes where likes.service_id = services.id GROUP BY likes.service_id)'
  Arel.sql(query)
end
```

これで検索機能といいね順、投稿順の並べ替えができました！
Laravel-ExcelでCSV出力したら文字化けしたのでUTF-8（BOM有り）で対応した

#### 失敗例

src/config/excel.php

```php

'use_bom' => true
```

BOM有りの設定に変更してみたが文字化けしたまま。

どうやら、このファイルではデフォルトを使用するらしいので変更しても駄目だった。

#### 解決

エクスポートクラスにgetCsvSettingsメソッドを追加する。

src/app/Exports/HogeExport.php

```php

use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;

class HogeExport implements WithCustomCsvSettings
{
    public function getCsvSettings(): array
    {
        return [
            'use_bom' => true
        ];
    }
}

```

##おまけ

excelでCSV(UTF-8)を作成した場合、BOMありUTF-8ファイルとして作成される。
作成したCSVファイルをインポートすると、一行目の一列目を正しく認識できない事象が発生する。
そんなときは、BOMを削除してあげればいい。

```
preg_replace('/^\xEF\xBB\xBF/', '', $hoge); // $hogeは一行目一列目の変数
```
3分アジャイル XPの価値（1）

- コミュニケーション
- シンプリシティ
- フィードバック
- 勇気
- リスペクト

---
## コミュニケーション
- チームによるソフトウェア開発で最も重要
- ユーザーの見解をすべての開発者に与えること
- 頻繁な口頭でのコミュニケーション

---
## シンプリシティ
- 物事をシンプルに考えること
- YAGNI（You ain't gonna need it）
- シンプリシティを達成し、必要なコミュニケーションを減らす

---
## フィードバック
- システムからのフィードバック（テスト）
- 顧客からのフィードバック（機能）
- チームからのフィードバック（計画と見積り）
- 変化の受け入れ

---
## 参考
https://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%A0%E3%83%BB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0

https://ja.wikipedia.org/wiki/YAGNI

ＫｅｎｔＢｅｃｋ,ＣｙｎｔｈｉａＡｎｄｒｅｓ. エクストリームプログラミング (Japanese Edition) (Kindle Location 504). Kindle Edition.
MkDocs encountered as error parsing the configuration file

# 事象 : while parsing a block mapping
- 環境
    - Windows10 Pro バージョン1909
    - Python 3.8.5
    - MkDocs 1.1.2
    - Material for MkDocs 6.0.2


```bash
$ mkdocs build

MkDocs encountered as error parsing the configuration file:
  in "C:\git\reponame\docs\mkdocs.yml", line 18, column 7
expected <block end>, but found '-'
  in "C:\git\reponame\docs\mkdocs.yml", line 19, column 7
```

```yml:mkdocs.yml
# テーマはMaterial for MkDocs
theme: 'material'

nav:
  - 仕様:
    - ツール: 'tool.md'     # << line 18
      - 詳細: 'detail.md'   # << line 19
```

## 原因 : 不明
Ymlの書き方に違反しているのか、MkDocsの書き方に違反しているのか・・・Material for MkDocsの書き方に違反しているのか・・・何もかも初心者すぎてわからない。

### 対応 : ページの配下にページを配置するのをやめる
```yml:mkdocs.yml
nav:
  - 仕様:
    - ツール:
      - 仕様: 'tool.md'
      - 詳細: 'detail.md'
```


# 事象 : while parsing a block collection
- 環境
    - Windows10 64bit バージョン1909
    - Python 3.8.5
    - mkdocs, version 1.1.2

```bash
$ mkdocs build

MkDocs encountered as error parsing the configuration file: while parsing a block collection
  in "C:\path\to\mkdocs\docs\mkdocs.yml", line 56, column 3
expected <block end>, but found '<block mapping start>'
  in "C:\path\to\mkdocs\docs\mkdocs.yml", line 61, column 7
(mkdocs)
```

```yml:mkdocs.yml
# ...省略...
markdown_extensions:
  - admonition
  - toc:
      permalink: '#'
  - footnotes # 注釈機能
  - pymdownx.highlight # コードシンタックス
      linenums: true
```

## 原因 : `:`がないから

### 対応 : `:`をつける

```yml:mkdocs.yml
  - pymdownx.highlight: # コードシンタックス
```

```bash
$ mkdocs build
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: C:\path\to\mkdocs\docs\site
INFO    -  Documentation built in 0.86 seconds
(mkdocs)
```
# 事象 : mapping values are not allowed here
- 環境
    - Windows10 64bit バージョン1909
    - Python 3.8.5
    - mkdocs, version 1.1.2

```bash
# ビルドしたらmkdocs.ymlのページ設定で怒られた
$ mkdocs build

MkDocs encountered as error parsing the configuration file: mapping values are not allowed here
  in "C:\path\to\mkdocs\docs\mkdocs.yml", line 16, column 18
(mkdocs)
```

```yml:mkdocs.yml
# ...省略...
nav:
  - はじめに: index.md
  - 概要
    - ぽんすけの旅の日記: ponsuke.md
# ...省略...
```

## 原因 : `:`がないから
エラーの`line 16`(「ぽんすけの旅の日記」行)の上の行(「概要」行)に`:`を入れ忘れている

### 対応 : `:`をつける
```yml:mkdocs.yml
# ...省略...
  - 概要:
    - ぽんすけの旅の日記: ponsuke.md
# ...省略...
```

```bash
$ mkdocs build
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: C:\path\to\mkdocs\docs\site
INFO    -  Documentation built in 0.15 seconds
(mkdocs)
```
PowerVS IBM i 日記(27): PTF 入手は SNDPTFORD で OK! (Docs に「正常に動作しない」とあるけど)

# PTF 入手は SNDPTFORD で OK! (Docs に「正常に動作しない」とあるけど)

「[PTF をオーダーして適用する](https://qiita.com/6onoda/items/be50c9d1fe8d0acb7360)」の回で、SNDPTFORD で PTF を入手しました。

オンプレの IBM i を持たず、シリアル番号に紐付いた SWMA が無いために FixCentral での入手ができない状況で、どのように PTF を入手するか、というのを踏まえた記事です。

## IBM の資料では「SNDPTFORD は PowerVS では正常に稼働しない」

その後、IBM Cloud のドキュメントに、こんな記述があるのに気が付きました。

* 英語版「[Downloading fixes and updates](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-downloading-fixes-updates&locale=en)」

> Note: The SNDPTFORD command does not currently work as expected within the Power Systems Virtual Server service.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/dcb51239-59f7-515b-fcc3-7c4dce3f052b.png)

* 日本語版「[フィックスおよび更新のダウンロード](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-downloading-fixes-updates&locale=ja)」

> 注記：現時点では、SNDPTFORD コマンドは Power Systems Virtual Server サービス内では正常に動作しません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/397c7abb-d3fc-22f0-41eb-b2d7753f77d7.png)

これは、まずいです。


## IBM i ネットワーク・インストール・サーバーの記述はあるが...

SNDPTFORD の他に「IBM i ネットワーク・インストール・サーバー」からの導入の記述も資料にはありますが、その場合でも、ネットワーク・インストール・サーバーへ、どのように PTF を入手するかという問題は解けません。

## CASE で問い合わせたところ、資料の誤り

考えても仕方がないので、CASE で問い合わせました。

SNDPTFORD が実行できている実績があるので、どのように正常稼働しないのか聞いてみました。
(恥ずかしい英語ですが、この程度でも理解してもらえます。)

***質問***

> I am using PowerVS IBM i.
>
Docs states "The SNDPTFORD command does not currently work as expected within the Power Systems Virtual Server service."
>
https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-downloading-fixes-updates
>
How SNDPTFORD  does not currently work as expected  ?

回答は「資料の誤りで、できるだけ早く修正する」とのことでした。

***回答***

> YASUHIRO-san:
>
We have talked with the Developer and had him reviewed. Post review he told that might be an incorrect statement to be published in the Documentation. We have informed the Information Developer to update it at the earliest. We will be closing this case. Thanks!  
>
Power IaaS Support.

## 結論

IBM i の PTF は SNDPTFORD で入手が可能です。

これで IBM i がオンプレからなくなり PowerVS だけになっても SNDPTFORD で安心して PTF を入手できます。

疑問があれば、面倒くさがらずに、CASE で問い合わせるべきですね。

## 2020/11/19 追記

2020/11/19 に確認したところ「Note: The SNDPTFORD command does not currently work as expected within the Power Systems Virtual Server service.」の記述は削除されていました。

ただし「Last updated: 2020-04-10」と更新されていませんでした。
最終更新日で資料の更新があったか判断するのは、危険なようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184930/cb20af2a-6893-aec5-2fa0-e4bf10fc8389.png)

---
当日記のIndexは[こちら](https://qiita.com/6onoda/items/f146c78c0c1bbe905a42)です。

---
許可の無い転載を禁じます。
この記事は筆者の個人的な責任で無保証で提供しています。
当記事に関してIBMやビジネスパートナーに問い合わせることは、固くお断りします。
SPSS Modelerのレコード追加ノードをPythonで書き換える。

SPSS Modelerでデータを縦方向に追加するのが、レコード追加ノードです。
SQLでいうUNION ALLにあたる加工処理です。
これをPythonのpandasで書き換えてみます。


#0．元データ
以下の２つの時系列のセンサーデータをつかって行います。
似たデータ項目ですが、列名が違っていたり、片方にしかない列が含まれています。

■データ１：Cond4n_e104.csv
M_CD: マシンコード
UP_TIIME: 稼働時間
POWER: 電力
TEMP: 温度
ERR_CD: エラーコード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/31557734-e112-a118-3808-8ad8c33e49ae.png)

■データ２：COND2n.csv
Time:稼働時間
Power:電力
Temperature:温度
Pressure:圧力
Uptime:起動時間
Status:状態コード
Outcome:エラーコード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/054f75c7-7125-e234-a8de-61d7dcf2e227.png)


#1m．レコードの追加　Modeler版

データ１「Cond4n_e104.csv」の列に合わせて、データ２「COND2n.csv」を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d0e47683-33f6-89b2-7b2d-9702e12e61c2.png)
まずフィルターノードを使って、データ２の列をデータ１の列名に合わせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7540f380-1ff1-34d9-7175-17bd066f9c87.png)

次にレコード追加ノードを接続します。
M_CDに当たる列がデータ２のCOND2n.csvには存在しないのでNULLが入ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/c9334cfe-0535-741b-d586-56b471e64fd5.png)

以下のようにデータ１にデータ２が追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7a8e2dfd-0d48-ce34-f08a-2ad2e39c6e71.png)

ちなみにレコード追加ノードでは、フィールド一致基準のデフォルトは「名前」ですが、名前が違っていても、列位置を基準に追加することもできます。
また、追加するデータ２にしか含まれていないPressureなども追加したい場合はフィールド入力元で「すべてのデータセット」を選ぶと追加ができます。
さらにどちらのデータから来たかを示すタグ列をつけたりすることも可能です。

#1p．レコードの追加　pandas版

フィルターノードに当たる処理をrenameとdropを使って行います。renameでデータ１と列名をそろえ、dropで不要な列を削除します。

```python
#データ２の列をデータ１の列名に合わせます。
df2_1=df2.rename(columns={'Time': 'UP_TIME', 'Power': 'POWER', 'Temperature': 'TEMP', 'Outcome': 'ERR_CD'})\
    .drop(['Pressure','Uptime','Status'],axis=1)
df2_1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/70b244fc-d7f4-7a32-2f6c-0e79a41e6cca.png)

次に、レコード追加ノードにあたるレコード追加処理を行います。
方法は二つあってappendとconcatがあります。
どちらでも結果は同じです。3つ以上のデータを結合する場合はconcatの書き方の方がわかりやすくてよいと思います。

```python
#appendを使う方法
df1.append(df2_1)
```

```python
#concatを使う方法
pd.concat([df1,df2_1])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/549e2d01-ad95-1de4-ce76-3dfe087128c2.png)


* 参考
 * pandas.DataFrame, Seriesの重複した行を抽出・削除 | note.nkmk.me 
 * https://note.nkmk.me/python-pandas-duplicated-drop-duplicates/
 * pandas.DataFrame.append — pandas 1.1.4 documentation
 * https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.append.html#pandas.DataFrame.append

#2. サンプル
サンプルは以下に置きました。

ストリーム
https://github.com/hkwd/200611Modeler2Python/raw/master/append/append.str
notebook
https://github.com/hkwd/200611Modeler2Python/blob/master/append/append.ipynb
データ
https://raw.githubusercontent.com/hkwd/200611Modeler2Python/master/data/Cond4n_e104.csv
https://raw.githubusercontent.com/hkwd/200611Modeler2Python/master/data/COND2n.csv

■テスト環境
Modeler 18.2.2
Windows 10 64bit
Python 3.7.9
pandas 1.0.5

#4. 参考情報

重複レコード・ノード
https://www.ibm.com/support/knowledgecenter/ja/SS3RA7_18.2.1/modeler_mainhelp_client_ddita/clementine/distinct_settingstab.html
ESP-WROOM-02 と DHT11, MH-Z19 で温湿度＋CO2センサーを作る

[ESP\-WROOM\-02 と DHT11 で温湿度センサーを作る \- Qiita](https://qiita.com/takke/items/307cf6183ec144da4e29) の続編です。

![2020-11-18 10.13.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39221/515b7a8b-722f-9089-b4e9-8dfb7cdbbcff.jpeg)

仕事部屋は [Amazon \| カスタム \(CUSTOM\) CO2モニター CO2\-mini \| 光学機器・計器 \| 産業・研究開発用品 通販](https://www.amazon.co.jp/%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0-CUSTOM-CO2-mini-CO2%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC/dp/B00I3XJ9LM) で CO2 を測定していますが、クラウドでも見られるように ESP-WROOM-02 で測定できるようにしてみました。

CO2濃度センサーは温度センサーや湿度センサーと違い比較的高価(￥2,000くらい～)ですが、市販のCO2モニター自体が数千円するので作ることに意義はありそうです。

今回は `MH-Z19` を [Amazon](https://www.amazon.co.jp/Lanfy-%E3%83%A9%E3%83%B3%E3%83%95%E3%82%A3%E3%83%BC-MH-Z19-0-5000PPM-CO2%E5%AE%A4%E5%86%85%E7%A9%BA%E6%B0%97%E8%B3%AA%E3%83%A2%E3%83%8B%E3%82%BF%E7%94%A8%E8%B5%A4%E5%A4%96%E7%B7%9ACO2%E3%82%BB%E3%83%B3%E3%82%B5UART-PWM/dp/B07B3VGGNL/ref=as_li_ss_tl?ie=UTF8&linkCode=ll1&tag=takkejp-22&linkId=36c19a3d70e7c98a11bfa37f10ad44ed&language=ja_JP) で購入しました。￥2,999 とそこそこ高価です。届いたのは MZ-Z19B という型番でした。


# 配線

[朝の眠気にも影響\!? ESP\-WROOM02\( ESP8266\)とCO2センサー\(MH\-Z19\)でCO2濃度を測定してみる – ど素人電子工作](http://toccho.xsrv.jp/2018/05/05/esp-wroom02-mh-z19-measurement/) を参考に、下記の配線にしました。PWM 方式と迷いました。

|MH-Z19|ESP-WROOM-02の接続箇所|
|---|---|
|V+|5V(+)|
|V-|GND(-)|
|Tx|IO4|
|Rx|IO5|

# スケッチ

DHT11 の温湿度センサーも付けているので、MH-Z19 と両方を計測するスケッチになりました。

また、DHT11 のみの端末も作るので、#define, #ifdef, #endif などでコンパイル時に切り替えられるようにしました。

(スケッチは省略)
ファイルで定義したメソッドの一覧を取得する

Railsのモデルなど、各ファイルのメソッドの調査をirbで行いたかったので、以下のようなスクリプトを作成した。

```ruby
methods = []
File.foreach("foo.rb") { |line|
  methods << line.chomp.gsub(/^\s*def\s/, '').gsub(/\(.+\)/, '') if /^\s*def\s/ =~ line
}
```

趣旨からは外れるがアプリの挙動をコンソールで確認できるのであれば、クラスメソッドとインスタンスメソッドを分けるのは以下でできる。

```ruby
instance_methods = Foo.instance_methods(false)
private_instance_methods = Foo.private_instance_methods(false)
class_methods = Foo.methods(false)
private_class_methods = Foo.private_methods(false)
```
湯婆婆.bat

# はじめに
はい、すでに出落ち感あるんですけど流行に乗りたかったので他にやってる人があまりいなくてパッと作れそうな奴で作ってみました
湯婆婆です
元ネタ→ [Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2 )
以下簡単な仕様

* 名前を入力させる
* 名前を読み取る
* 0 <= n < 名前.Length　の乱数を生成する
* 生成した乱数をインデックスとして使用し、名前から一文字抽出
* 抽出した文字を新たな名前として与える
* 働かせる

# コード
(encodeはshift-jisです。実行できないなどの場合はencodeがutf-8などshift-jis以外になっていないか確認してください)

```scrypt:Yubaba.bat
@echo off
setlocal enabledelayedexpansion
cd %~dp0
echo "契約書だよ。そこに名前を書きな。"
SET /P name=
set cname=%name%
set /a len = 0
:LOOP
if not "%cname%"=="" (
     set cname=%cname:~1%
     set /a len=%len%+1
     goto :LOOP
)
echo "フン。%name%というのかい。贅沢な名だねぇ。"
set /a sindex=%random%%%len
call set newName=%%name:~%sindex%,1%%
echo "今からお前の名前は%newName%だ。いいかい、%newName%だよ。分かったら返事をするんだ、%newName%^!^!"
pause 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684820/a5d1a9f7-ccd2-a783-4aa6-104718c8865f.png)

# 解説
まあ解説するような部分も無いですが一応、まずは頭の3行、

```
@echo off
setlocal enabledelayedexpansion
cd %~dp0
```
これは知ってる人多いというか常識ですが、デフォルトの状態では何か実行する度に発行されたscryptがコマンドラインに吐き出されるんですね。それを`@echo off`と記述することでechoを無効化しています
そして2行目の`setlocal enabledelayedexpansion` 。これを利用することで変数を読み込むタイミングを遅らせることができます。詳しくはググってください。
そして3行目の`cd %~dp0`はカレントディレクトリを現在実行しているバッチファイルのディレクトリへ移動してくれます。
この3つはバッチファイルを記述する上でお約束みたいなもんですね。
では実際に処理を行っている部分の解説へ入っていきます。

```
echo "契約書だよ。そこに名前を書きな。"
SET /P name=
set cname=%name%
set /a len = 0
:LOOP
if not "%cname%"=="" (
     set cname=%cname:~1%
     set /a len=%len%+1
     goto :LOOP
)
echo "フン。%name%というのかい。贅沢な名だねぇ。"
set /a sindex=%random%%%len
call set newName=%%name:~%sindex%,1%%
echo "今からお前の名前は%newName%だ。いいかい、%newName%だよ。分かったら返事をするんだ、%newName%^!^!"
pause 
```

ではまずは原作通り契約書を渡して名前を書いてもらいましょう

```
echo "契約書だよ。そこに名前を書きな。"
SET /P name=
```
ここでは`SET /P name=`でコマンドラインに入力された文字列を`name`という変数に入れています。
そして入力された名前の桁数を数えましょう。これは乱数の上限値に使います。4文字の名前から5番目の文字を抽出するなんてことにならないように。

```
:LOOP
if not "%cname%"=="" (
     set cname=%cname:~1%
     set /a len=%len%+1
     goto :LOOP
)
```

この処理はIT初心者がお世話になるササキマコトさんのサイトにあった処理をまるまるパクらせていただきました。↓
[Windowsバッチファイル（.bat）、文字数を取得する](http://piyopiyocs.blog115.fc2.com/blog-entry-898.html)
処理の流れとしては文字列を1文字ずつ削って空文字になるまでの回数をカウントするというシンプルな処理です。
では取得できた文字数を上限とする乱数を生成しましょう

```
set /a sindex=%random%%%len
```

乱数の生成には`%random%`を使用しました
`%random%`で生成した値を先ほど取得した桁数で割ってあまりを求めます
あまりを求める計算は`数値%%数値`のように%二つでできます

そして生成した乱数をインデックスとして使用し、コマンドラインに入力させた名前から1文字抽出します

```
call set newName=%%name:~%sindex%,1%%
```

文字列の抽出は↓を参考にしました
[Windowsバッチ(.bat)で文字列の切り出しを行う(Substrみたいな)](https://web.plus-idea.net/2016/09/windows-bat-substr/)
m文字目から、n文字分というように文字列を抽出する場合は

```
%STR:~m,n%
```

という風に記述するようです。わかりにくい。
ちなみに変数を利用する場合は`set`の前に`call`を記述する必要があります。

ということで無事名前も奪えたので後は新しい名前を言い渡して働かせるだけです

```
echo "今からお前の名前は%newName%だ。いいかい、%newName%だよ。分かったら返事をするんだ、%newName%^!^!"
```

!などの文字は^でエスケープする必要があります。それ以外は特になんかやってるわけではない普通のechoですね。
以上がバッチファイルで動く湯婆婆です。
解説することないと言いながら結構解説長くなってしまいましたね。
忘れていましたが、もちろん名前を空文字にすると落ちます。仕様なので。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684820/d6f0edf2-2e57-1cff-4f06-ff8b98bd1ddf.png)
# 最後に
ここまで読んでくださってありがとうございました。
初投稿でしたが、今後もいろいろ書いていこうと思います。
VirtualBoxでdebianを構成してホストPCから通信を行う手法

#開発環境

* ホストOS：Windows10 Pro（Ver.1909）
* 仮想OS：debian_jessie64_armhfcross.ova
* 仮想化ソフト：ORACLE VM VirtualBox 6.1.2
* エミュレーター：Tera Term (Ver.4.105)

#概要
　以前参加したセミナーで学んだ開発環境構築方法を自身の環境で再現しようと模索。

セミナーでは

　「ホストOS(Win)」⇔「仮想OS(Linux)」⇔「ターゲットマシン(Linux)」

という環境での相互接続方法を学び、仮想OSのネットワーク設定ではアダプター１に「ブリッジアダプター」を選択。
ターゲットマシンとは有線（USB）で直接接続していた為、そのLANを選択した。

しかし、自身の環境にはターゲットマシンがないので仮想空間に構築するしかない。また、社内での個人的な開発となるので、ネットワーク面でもセキュアに実施する必要もあった為、以下の構造に変更する必要があった。

#ネットワーク設定
　社内ネットワークにさらされ、それを通じて仮想OSにまで外部アクセスされると面倒。ネットでいろいろ探してみたところ、以下の記事が参考になった。

[今さらながらVirtualBoxネットワーク設定のベストプラクティスと解説](https://qiita.com/aki3061/items/ea35094c5dc4699d2a6b)

それによると、今回の環境で最も有効なネットワーク設定はアダプタを２つ用意し、アダプター１を「NAT」、アダプター２を「ホストオンリーアダプター」に設定するというものだそうだ。

早速試してみた。

#実際にやった操作
手順　debianを起動してcdコマンドにて /etc/network/ディレクトリへ移動し、その中の「interfaces」を編集する。
※ちなみに、今回はeth1の項目がデフォルトでは定義されていなかったので追記した。

![interfaces.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703537/7f4af5c8-310d-ffc6-24ea-e667ac3c029c.png)

但し、ここで定義するIPアドレスのホスト部はホストオンリーアダプタに対応したものにしておくことが重要。
ホスト部は「VirtualBox マネージャー」の上部タブのある「ファイル」から「ホストネットワークマネージャー」を展開すれば確認が可能。
また、ここで指定したIPアドレスのホスト部は、ホストOS（win10）のIPアドレスを確認してから設定すると良い。コマンドプロンプトで「ipconfig」コマンドを実行すれば確認できる。今回は「192.168.208.1」となっていたので、debianでの設定はこれ以外の「192.168.208.XXX」を使えばよい。今回は「192.168.208.30」を使用した。
#トラブル回避
　今回の操作で２点トラブルが発生したのでそれをまとめておく。
##ホストオンリーアダプタが機能しない
　接続できていたのに突然使えなくなったり、そもそも機能していないというときは以下の操作が有効だそうだ。

![ホストオンリーアダプタの追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703537/27fde926-6622-545e-0e09-8427a0292646.png)

あとは画面下部の「IPv4アドレス」に表示されているIPアドレスを参照してdebian内の「interfaces」を同様に書き換えてやればいい。

##Tera Termで接続ができない
　これが今回泥沼に嵌ったやつ。原因としてはdebian内の「interfaces」におけるアダプタの設定を間違えていたことだった。（先ほど記載した設定は正しいもの）

　アダプター１（eth0）にはNATを、アダプター２（eth1）にはホストオンリーアダプタを定義しているにも関わらず、IPアドレスやinetの設定を逆にしてしまっていたために何度接続を試みても繋がらなかった。必ず、上で説明した画像通りに設定することが重要。

　ちなみに、Tera Termに接続するときは以下の方法で行う。
![TeraTerm接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703537/7d845371-edf1-e0ad-c2be-7a704ee2866c.png)

#その他
IPアドレスやネットワークの構成について、以下の記事が参考になったので載せておく。
[VirtualBoxのネットワーク設定を絵で説明する](https://qiita.com/feifo/items/0fde474005589afcff68)

今回はこの辺で。
炎上している件とは関係ないけどforとforeachの違いをまとめてみた

前回の記事 → [転生できないからVimで2つのファイルの差分を確認してみた](https://qiita.com/daikin/items/84b669b44a4c8053b45d)

### ほんと炎上とは何も関係ないです←
forとforeachって何が違ってどう使うのかややこしくなった時期が
過去あったなぁと思ったのでまとめました
因みに個人的な好みとしてforeachの方が使うことが多いです^ - ^

#### for
公式 → https://www.php.net/manual/ja/control-structures.for.php

```PHP
for ($i = 1; $i <= 10; $i++) {
    echo $i;
}
```

基本的な使い方は上記の通りで
$iが1からカウント?スタートして10になるまで{}の中の処理を繰り返します。
自分で繰り返す回数を指定出来る様なイメージで解釈しています。

#### foreach
公式 → https://www.php.net/manual/ja/control-structures.foreach.php

```PHP
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr は array(2, 4, 6, 8) となります
```

foreachは配列の中の要素やオブジェクトなど
要するに配列の中に入るものであればその配列の数だけ{}の中の処理を
繰り返していきます。
個人的にはこれが工夫して使えると
俺ってプログラマーじゃね？って勘違いできるので是非とも使いこなしてみてください。

#### forとforeachの違い
比べてみて大きな違いは数字の値分ループするのか
配列の数だけループするのかといった違いが大きいでしょうか

どういうときに使うの？と問われると
内容次第ですが多分どちらも使おうと思えば使えるのかなと思います。
これまでの経験の中で言わせてもらうと
forやforeachの中で変にifでネストしまくったコードは
読みづらいなぁと思うので僕はそんなコードを書かない様に意識をしています。
全く使わないことは無理なので適度な加減が必要ですね！
Vue.jsでHello World!を表示させる

#①Vue.jsのインストール
・[Vue.js公式サイト]
(URL "https://jp.vuejs.org/index.html")右上の「学ぶ」のタブの中から「ガイド」を選択
![スクリーンショット_2020-11-18_7_38_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/06bd6663-2b3c-7175-0486-417ceb21e997.png)
・ガイドの中のインストールを選択
![スクリーンショット_2020-11-18_7_39_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/2aff42d8-32a5-e2ce-a6f9-ed28b08729e4.png)

インストール画面の中で、CDN(Content Delivery Network)の中から一番上の最新バージョンを使用します。
![スクリーンショット_2020-11-18_7_41_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/0c9eece0-c17e-c355-5999-e8871855de95.png)

CDNによって、HTMLファイルに下記のコードをコピー＆ペーストするだけでVue.jsがインストールされます。

```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
```
#②Vue.jsを使う準備

今回は「Hello World!」と表示するだけなのでjsfiddle.netというオンラインサービスを利用します。
ローカルに開発環境を用意しなくても、HTML・CSS・JavaScriptの簡単なコードの実行・動作確認、編集したコードの保存・共有を行うことができます。
https://jsfiddle.net/



jsfiddleのHTMLのエディタ内に先程のコードをペーストします、これでVueがインストールされました。
![スクリーンショット 2020-11-18 8.43.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/90b68c8b-6849-ed19-ac25-0b2905b11728.png)


Vueを書く前に一旦HTMLだけで「Hello World!」を書いてみましょう。

```html
<div id="app">
  <p>Hello World!</p>
</div>
```

左上の▷Runを押して右下のResult画面に「Hello World!」が表示されればOKです。
![スクリーンショット 2020-11-18 8.30.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/65149d95-557c-57e9-d7e7-eb09e84e8ade.png)
#③Vueを使ってHello World!を表示させる
###Vueインスタンスを宣言
JavaScriptのエディタ内で```new Vue()```と書くことでVueインスタンスを宣言します。
その中にelプロパティを書くことで、このVueインスタンスがHTMLのどこのタグに対応しているかを指定することが出来ます。

```vue.js
new Vue({
 el: '#app'
})
```

これでVueを使うという宣言が出来ました。
![スクリーンショット 2020-11-18 8.32.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/04c204d8-207e-8c45-6147-24578d8c5a59.png)
###Vueインスタンスにデータをもたせる
次にdataオブジェクトをつなげて書き、messageプロパティに「Hello World!」というデータをもたせます。

```vue.js
new Vue({
	el: "#app",
  data: {
  	message: "Hello World!"
  }
})
```

pタグにVueのmessageに対応したものを表示させるためには、二重中括弧{{ }}で囲むことでVueのデータとｐタグを対応付けることが出来ます。
先程と同様に左上の▷Runを押して右下のResult画面に正しく「Hello World!」と表示されればOKです。

```html
<div id="app">
  <p>{{ message }}</p>
</div>
```
![スクリーンショット 2020-11-18 8.28.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502115/5e156317-2ae9-da7d-39ff-47bac88d1f34.png)
JmeterでSOCKS Proxyを経由して負荷試験を行いたいとき

実行時の環境変数にSOCKSプロキシサーバとPortの指定を行うだけ

# JVM_ARGS='-DsocksProxyHost=HOST_NAEM or IP Adress -DsocksProxyPort=PortNo' apache-jmeter-5. 3/bin/jmeter -n -t 実行シナリオ -l 実行結果ファイル
【Rails】Viewの共通化について

<h1>本投稿の目的</h1>
・Rails学習の議事録です。

---
<h1>学習に使った教材</h1>
Udemyの ["はじめてのRuby on Rails入門-RubyとRailsを基礎から学びWebアプリケーションをネットに公開しよう"](https://www.udemy.com/course/the-ultimate-ruby-on-rails-bootcamp/) を教材として使用しました。

---
<h1>①viewの共通化</h1>
・全てのviewの共通箇所を1箇所に集約する方法
・集約ファイル (app/views/layouts/application.html.erb)

```ruby:application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>

```

【解説】
・html.erbファイル共通フォーマットがここに記載
・大抵は,htmlのheadのcss,js読み込みテンプレ文を記載する
・<%= yield %>の部分には,他のhtml.erbが読み込まれる

<h1>②partialについて</h1>
・共通部分を記載したファイルをpartialファイルという
・例えば,new と edit など共通のviewなどが該当する

【やり方①】
・パーシャルファイルを _partial名.html.erb として保存 
・(*　" __ " から始めるのに注意)
・viewファイルの共通部分を削除

・下記を記載 
・(*名前に" _ "を外すことに注意)

```ruby:partialを呼び出す側のファイル名.html.erb
<% render partial '名前' %>
```

【やり方②】
・①のやり方はメンテナンス性が悪い
・(controllerのインスタンス変数に気付き辛い)

記載を下記に修正

```ruby:partialを呼び出す側のファイル名.html.erb
<% render '名前', locals: {ローカル変数: インスタンス変数} %>
```

・これによりパーシャルのhtmlにはインスタンス変数ではなくローカル変数が渡される

```ruby:_partialファイル名.html.erb
<%= form_for ローカル変数 do |f| %>
  共通の内容をここに記載
<% end %>
```

【やり方③】
・記載を下記に修正

```ruby:partial導入側のファイル名.html.erb
<% render '名前', locals: {object: インスタンス変数} %>
```

・objectとすることで,パーシャル名と同様のローカル変数を作成
・これにインスタンス変数を渡す

【やり方④】
・記載を下記に修正

```ruby:partial導入側のファイル名.html.erb
<% render インスタンス変数 %>
```
・これは partial名 = ローカル変数 時に使用可能
・インスタンス変数の@を除去した変数=ローカル変数=partial名
ISO8601 形式を日本表記に変換して表示 JavaScript

## 前提・やりたいこと
Amazon DynamoDB に日付がISO-8601 形式の文字列として格納されていて、さらにUTCでした。
日本時間かつ、日付だけ表示したい。

## これ
```typescript
const dateFormatter = (dateIso8601: string) =>
  new Date(Date.parse(dateIso8601))
    .toLocaleDateString('ja-JP')
    .replace(/\//g, '.');
```
```
// 結果
2020.11.17
```

## 参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

## 追記
↑認識間違っていました。コメントいただきありがとうございます。
【Rails】コールバックについて

基本的な事項ですが忘れやすいので備忘録かつ、まとめとして記事にすることにしました。

【参考記事】
[Railsのコールバック](https://skillhub.jp/courses/139/lessons/987)

# コールバックとは？
モデルを保存、更新、削除後や削除前のタイミングで実行されるメソッドのこと指す。
例) 記事を投稿し保存後には〜をする。

```ruby:
before_save => #保存前
after_save => #保存後
after_update => #更新後
before_destroy => #削除前
after_destroy => #削除後
```

# コールバック使用例
before_save(保存前)コールバック後にメソッド実行する例を挙げる。

```ruby:user.rb
class << self
  before_save :downcase_email
  def downcase_email
     self.email = email.downcase
  end
```
上記コードはemail保存前に、大文字のローマ字がある場合、小文字に変換するメソッド。
他の分かりやすい例としては、

```ruby:posts_controller.rb
class ShopsController < ApplicationController
　　before_action :logged_in_user
```

上記はpostsコントローラーの各アクション前にログインユーザーであることを指定している。
通販で何か購入する時、ログインしていない場合はログインまたは会員登録を促されると思われるが、ログインユーザーでないため、弾かれる(before_action :logged_in_user)のもコールバックによりログインを要求しているものと言える。

# 学び
普段何気なく上記のメソッド(before_action)等は使用していると思われるが、改めて「Railsにおけるコールバックを端的に説明せよ」と言われるとビシッと答えられない初学者の方が意外に多いと思います(自分もそうです)。意味のないコードなどなく、それぞれが意味を持っているので、普段から自分が書いたコードについて自信を持って説明できるように学習を励んでいきたいと思いました。Railsはとっつきやすいと言われていますが、本当に理解して使いこなそうとするとかなり奥が深いものであることを学びました。
rundll32から呼び出すDLLを作ってみた

#はじめに
- [コマンドラインからマウスを操作する方法　（rundll32.exeで動くDLLの作成法）]
(https://language-and-engineering.hatenablog.jp/entry/20081117/1226943698)

を参考にさせて頂きました。圧倒的感謝……！

#環境
- Windows 10 Home (64bit)
- Visual Studio Community 2019

#手順

##プロジェクトの作成
プロジェクト テンプレート：空のプロジェクト [C++]
プロジェクト名：rdtest

プロジェクトのプロパティ
全般
構成の種類：ダイナミック ライブラリ (.dll)

##ソースの記述

```rdtest.cpp
#include <Windows.h>
#include <stdio.h>

extern "C" __declspec(dllexport)
void CALLBACK test1(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
	MessageBoxA(nullptr, lpszCmdLine, "rdtest", MB_OK);
}

extern "C" __declspec(dllexport)
void test2(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
	printf("dlltest[%s]\n", lpszCmdLine);
}
```

##エクスポート名の確認

[ツール]→[コマンド ライン]→[開発者コマンド プロンプト]

`dumpbin /exports rdtest.dll`

          1    0 00001040 _test1@16 = _test1@16
          2    1 00001060 test2 = _test2

##動作確認

`rundll32 rdtest.dll _test1@16 hello, world`

`rundll32 rdtest.dll test2 hello, world  > a.txt`
`dlltest[hello, world  ]`
コンソールには出力されないがリダイレクトは可能。
[Unity初級]デバッグをひと工夫（Debug.Logの応用）

#概要
手軽にログの見た目を変えて、気を付けるべき箇所に注意を向けやすくなります。
#本文
```cs

        if (a < 4) {
            Debug.Log("普通のデバッグログ");
        } else if(a<100) {
            Debug.LogWarning("異常を知らせるログ(LogWarning)");
        } else {
            Debug.LogError("異常を知らせるログ(LogError)");
        }
```

![スクリーンショット (1222).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/321401d1-7a52-d318-0d82-968d3b5ac475.png)
GoogleDriveの画像をwebに表示させる方法 

GoogleDriveの画像リンクをimgタグに貼り付けて、web上で表示させる方法！！！
---


①画像の共有を『リンクを知っている人全員にする。』 

②画像リンクを取得する。
　　『画像を右クリック->画像リンクを取得する』

③コピーした画像リンクを加工する

```
加工前
https://drive.google.com/file/d/画像により異なる文字列/view?usp=sharing
↓
加工後
https://drive.google.com/uc?export=view&id=画像により異なる文字列


uc?export=view&id=　　　これを追加するだけ！

```

これでweb上でGoogleDriveの画像が表示される。

リンクの先頭はhttpsでもhttpでも可能だけど、個人的には警告出ないhttps推奨。
Blockcertsのcerts-issuerをethereumで動かしてみる

Blockchainを使用したブロックチェーン証明書は発行したことがあったのですが、Ethereumチェーンを使用したことがなかったので使ってみました。

# 環境構築

1.docker のインストール

`git clone https://github.com/blockchain-certificates/cert-issuer.git && cd cert-issuer
`

2.cert-issuerのディレクトリでコンテナをビルド

`docker build -t bc/cert-issuer:1.0 .
`

3.dockerコンテナをコミット

`docker ps -l
docker commit <container for your bc/cert-issuer> my_cert_issuer
`

4.dockerを走らせる

`docker run -v <cert-issuer>:/cert-issuer -it bc/cert-issuer:1.0 bash
`

5.今回はethereumを選択

`python setup.py experimental --blockchain=ethereum`

```
python setup.py experimental --blockchain=ethereum
Traceback (most recent call last):
  File "setup.py", line 6, in <module>
    from setuptools import find_packages
```

おっと？？

dockerファイル内にsetuptools記述あったような気がしたのですが確認。

`pip3 install setuptools --upgrade`

```
Requirement already up-to-date: setuptools in /usr/lib/python3.6/site-packages (50.3.2)
```
やっぱり。。。

REAMD.meのコマンドではなくpython3で試してみたところ以下のエラーが出たのでrequirement.txtをpysha3==1.0b1に変更。


```
ERROR: After October 2020 you may experience errors when installing or updating packages. This is because pip will change the way that it resolves dependency conflicts.

We recommend you use --use-feature=2020-resolver to test your packages with the new resolver before it becomes the default.

cert-issuer 2.0.24 requires pysha3==1.0b1, but you'll have pysha3 1.0.2 which is incompatible.
```

再度以下コマンド実行。
`python3 setup.py experimental --blockchain=ethereum`

成功！！


#issueしてみる


conf_ethtest.iniを編集して以下のコマンドで発行。

`python3 cert_issuer -c conf_ethtest.ini
`

```
・・・
INFO - Your Blockchain Certificates are in /cert-issuer/data/blockchain_certificates
```

うまく行ったみたいです。
discord.py でよく躓くとこ（随時更新）

# はじめに

これは[teratail](https://teratail.com)とか[Discord Bot Portal JP](https://discord.gg/FWw6VqQ
)の質問に回答していって「こういうの多いなぁ」って感じたり、自分が躓いたとこを貼るだけのやつです。
[discord.py公式のよくある質問](https://discordpy.readthedocs.io/ja/latest/faq.html)とかを見てからこの記事を読むのをおすすめします。

# 一般
**Q. add_reactionがHTTPException吐く！ちゃんと`:thinking:`って書いたのに！**
A. add_reactionで標準の絵文字を使うには🤔みたいにUnicodeの絵文字を引数に渡す必要があります。
🤔みたいなのをもってくるのに１番手っ取り早い方法はDiscordで\\を絵文字の前につけて送信する方法です。（`\:thinking:`みたいに書いて送信すると、Unicodeの絵文字が送信されるからそれをコピペ）
「絵文字をソースコードに書きたくない！」って人は[R.Danny](https://github.com/Rapptz/RoboDanny)のcharinfoとかで`\U0001f914`みたいなやつをもってくるとか、[emojiライブラリ](https://github.com/carpedm20/emoji)の`emoji.emojize(":thinking_face:", use_aliases=True)`を使うとかしましょう。

**Q. TextChannel.history、チャンネルID指定したのにAttributeエラー吐く！なんで！？**
A. チャンネルIDはそのままだとただのクソデカ数値（正確にはsnowflakeっていう特殊なやつだけど）です。
`client.get_channel(チャンネルID)`(`bot.get_channel(チャンネルID)`の人もいるかも)でTextChannelオブジェクトを持ってきましょう。
（変えたら`AttributeError:'NoneType' object has no attribute〜`を吐くときは、チャンネルIDが間違ってる可能性があります。）


# Embed
**Q. timestampの時間ずれる！なんで！？**
A. EmbedのtimestampはUTC指定です。
- [datetime.datetime.now](https://docs.python.org/ja/3/library/datetime.html#datetime.datetime.now)(datetime.timezone.utc)
- [datetime.datetime.utcnow](https://docs.python.org/ja/3/library/datetime.html#datetime.datetime.utcnow)()
- [datetime.timedelta](https://docs.python.org/ja/3/library/datetime.html#datetime.timedelta)(hours=9)をマイナスする（PCの時刻が日本なら）
でUTCになります。


# commandsフレームワーク

**Q. コマンド動かない！ちゃんと[on_message を使うとコマンドが動作しなくなります。どうしてですか。](https://discordpy.readthedocs.io/ja/latest/faq.html#why-does-on-message-make-my-commands-stop-working)のやつ入れたのに！ or process_commands入れたらグローバルチャット（とかあいさつとか）動かない！**

A. グローバルチャット（とかあいさつとか）用とprocess_commands用でon_messageを2個おいてませんか？
最後に定義した方**だけ**実行されます。
process_commandsのon_messageを消して、
もう片方のon_messageに`await bot.process_commands(message)`
(それか`await client.process_commands(message)`みたいな）を書きましょう。

**Q. よくある質問の`bot.process_commands(message)`入れたら`NameError: name 'bot' is not defined`出たんだけど！？**
A. botではなくclientっていう名前の変数にcommands.Bot入れてませんか？（`client = commands.Bot(色々)`）

```python
await client.process_commands(message)
```
にしてみましょう。


# coroutine関係
**Q. `time.sleep`したらBot全体が止まるんだけど！**
A. [`asyncio.sleep`](https://docs.python.org/ja/3/library/asyncio-task.html#asyncio.sleep)を使ってみましょう。

```python
import discord
import asyncio # ← 重要
# ~~~~~
@client.event
async def on_message(message):
  if message.author.bot:
    return
  # ~~~~~
  if message.content == "起きろ":
    msg = await message.channel.send("(｡-ω-)zzz")
    await asyncio.sleep(5)
    await msg.edit(content="(｡ﾟωﾟ) ﾊｯ!")
```


# 最後に
ここで解決できなくて、[teratail](https://teratail.com)とかで質問しようと思っているそこのあなた。
１つだけ覚えておいて欲しいことがあります。
**「tracebackとコードは全文貼って。」**
teratailが用意しているテンプレートを使えば回答率が結構上がります。（多分）
これを忘れないようにしておきましょう。

最後まで読んでくれてありがとうございました。
~~もしここで解決したならLGTMしてね（）~~
【CSS3】立体的なボタンの作成方法

#完成形
今回は下記のような立体感のあるボタンを作成します！
![btn.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640274/f4097b11-28f6-03b8-d61f-a9ea09e8b8bc.gif)


#HTMLで\<button>\</button>タグを追加しボタンを作成する
```html:index.html
    <!-- CSSでスタイルを設定するためclass="btn"を追加しておく -->
    <button class="btn">ボタン</button> 
```
下記のようなボタンが作成されます
![スクリーンショット 2020-11-18 6.01.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640274/24a10a73-4c7a-3a36-9347-ed41e2aa9ea5.png)

#CSSでボタンにスタイルを追加する
```css:style.css
.btn {
    border-radius: 2px; 
    padding: 15px 40px;
    background-color: #60daf0;
    cursor: pointer;
    box-shadow: 0 4px #2693b4;
    border: none;
    outline: none;
}
```
すると下記のようなボタンが作成できます！
![スクリーンショット 2020-11-18 5.39.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640274/1b78507a-56ae-5156-b0c7-ad7fb5e05bd0.png)

#ボタンを押下した際の動きをつける
先ほどの手順ではボタン自体は作成できましたが、押下した際の動きはまだありません。
「*active*」ディレクティブで押下している間適用されるスタイルを追加しましょう！

```css:style.css
.btn {
    border-radius: 2px; 
    padding: 15px 40px;
    background-color: #60daf0;
    cursor: pointer;
    box-shadow: 0 4px #2693b4;
    border: none;
    outline: none;
}

/* ボタンを押下している間のスタイルを追加 */
.btn:active {
    box-shadow: none;
    position: relative;
    top: 4px;
}
```



#★Point　ボタンを押下した際にボタンの位置を下げる
①box-shadowの2番目に指定している「4px」で影の高さを指定
②押下時は4px位置を下げるというスタイルを適用することで、押下時の立体感を出すことが可能
　※「position: relative;」とセットで適用してください。

```css:style.css
.btn {
    border-radius: 2px; 
    padding: 15px 40px;
    background-color: #60daf0;
    cursor: pointer;
    box-shadow: 0 4px #2693b4; /* ①2番目に指定している4pxで影の高さを指定 */
    border: none;
    outline: none;
}

.btn:active {
    box-shadow: none;
    position: relative; /* position: relative;とセットで適用してください。 */
    top: 4px; /* ②押下時は4px位置を下げるというスタイルを適用することで押下時の立体感を出すことが可能*/
}

```
色の変化や、影の高さをアレンジするなど使い道がありそうです！