OmniAICreator/Qiita-1.07M huggingface dataset:
【競技プログラミング】AtCoderの練習問題やってみた

なにか趣味が欲しいと思っていたところ、**AtCoderという競技プログラミング**のサイトを見つけました。
与えられたお題に対して早く正確に回答する競技である競技プログラミングでは、**最適なアルゴリズムの構築能力**や**プログラミング能力**が問われるみたいです。

たのしそ〜〜

ということで、公開されているビギナー向け問題をちょっとやってみました。

※処理スピードも問われるみたいなので、C++を用いて回答しました。（最近PythonとかGASばかり書いていたので、一番の敵はコンパイルエラーでした笑）

#練習問題1
【問題文】
連続した3つの値を入力して、そこに'1'がいくつ含まれているのかを返すプログラム。
各桁の入力値は1か0の二値である。
##回答
3つの値が入力されて、それぞれの値は1か0。要は$2^3$種類の出力パターンがある問題です。
( 000, 001, 010, 011, 100, 101, 110, 111 )

なので8つの全パターンをifで区切って判断すれば・・・

とはならず、**各桁の数字を見てカウントしていけば3回の処理**で終わります。

全パターンを探索するとそれこそ、**n桁に対して$2^n$回**の試行が必要になりますが、
上記の処理であれば**$n$回**の処理で終わります。

```C++:Answer1
#include <iostream>
using namespace std;

int main() {
  string s;
  cin >> s;

  int count = 0;
  for(int i=0;i<3;i++){
    if(s[i] == '1'){count++;}
  }

  cout << count << endl;
  
  return 0;
}
```
コードが汚いとか言わないで！
必要なのは3回のチェックだけなので、forすら使わない方がメモリリソース的にもエコかもしれませんね。
文字列型で入力して各桁の文字を見るだけの処理です。

#練習問題2
【問題文】
N個の正の整数$A_1,…,A_N$を入力する。
これらの整数がすべて偶数であるとき、次の操作を行うことができる。
・**整数すべてを2で割ったものに置き換える。**
入力値に対して何度上記の操作を行ったかを出力する。

【制約】
$1≤N≤200$
$1≤A_i≤10^9$

【例】
入力が以下の時

N = 3
A = 16, 8, 36

出力は以下となる

2回
※ (一回めの処理で A = [8, 4, 18] となり、二回目の処理で A = [4, 2, 9] となる)

##回答
ちょっとややこしい問題文ですが、複数の値が入力され、その中に奇数が含まれていなければ入力値全部を2で割る。
奇数が含まれていれば処理を終了し、入力値全部を2で割る処理を何回行ったかを出力するというものです。
もう少しまとめると・・・

①値の入力
②入力値の中に奇数が含まれている？
③含まれていれば入力値全部を2で割る
④奇数が出てくるまで②~③を繰り返す
⑤奇数が含まれれば、②~③を繰り返した回数を出力

となります。


```C++:Answer2
#include <iostream>
using namespace std;

int main() {
  int n;
  cin >> n;

  int a[n];
  bool odd = false;
  int result = 0;

  for (int i=0;i<n;i++){
    cin >> a[i];
    if(a[i]%2 != 0){odd = true;}
  }

  while(odd == false){
    for(int j=0;j<n;j++){
      a[j] = a[j]/2;
      if(a[j]%2 != 0){odd = true;}
    }
    result++;
  }

  cout<<result<<endl;

  return 0;
}
```
こんな感じで書いてみました。
最初のforで入力処理をして、ついでに奇数を含んでいるかを判定します。
そして、もし含んでいなければwhileに突入し、各入力値を2で割っていきます。この段階でも奇数が含まれているかを判断していきます。

全体の処理を終えれば(forを抜けると)実施回数を保持しているresultをインクリメントします。
whileの継続条件は奇数判定のbool型変数であるoddがfalseの間(奇数が含まれていない間)繰り返すとなっているので、奇数が含まれた時点で終了し、resultを出力します。

あ〜〜〜これハマルわ〜〜〜
ちゃんとしたコンテストにも参加して、趣味として確立していきたいです。
【エンジニア知識不要】スプシで簡単に一括でカレンダー招待する方法

今回はGoogle Calendarで招待を送る時、業務効率化したいなと思い、
エンジニアじゃない人でもできる、簡単な方法を考えてみましたので、皆さん参考にしてみてください✨

####`今回したいこと`

![スクリーンショット 2021-12-19 11.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/98025a90-7490-b5ca-a279-619965af9cac.png)

C列に必要事項を入力して、生成リンクをクリックすると…


![スクリーンショット 2021-12-19 11.15.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/d034a4df-dd53-2660-5f7f-9df49f58b3fa.png)

このように、入力されて表示！
保存を押せば簡単にGoogle Calendar を作成できます🙆‍♀️


このシートの作り方について、今回は簡潔に説明していきたいと思います。✨
難しい人のために、最後に**コピーすれば使えるスプレッドシートのテンプレート**を置いておきます。

##作り方

####`B列（固定列）`

1. スプレッドシート作成 

2.予定タイトルに　「 **https://www.google.com/calendar/render?action=TEMPLATE&text=** 」を入れる

3.予定開始日時に　「**&dates=**」を入れる

4.予定終了日時に　「**/**」を入れる

5.詳細に　「**&details=**」を入れる

6.参加者メールアドレスに　「**&add=**」を入れる

####`C列（入力欄）`

1.予定タイトルに
![スクリーンショット 2021-12-19 11.28.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/a8a972dd-25a8-9b17-232e-d8b6b2f01c73.png)

ここに入力したいものを入れる。

2.予定開始日時、終了日時は
YYYYMMDDTHHMMの形式で入れる。「T」をいれるのを忘れずに！
（ex,2021年12月3日12時　→　20211203T1200）

3.詳細に

![スクリーンショット 2021-12-19 11.32.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/82660659-0716-0f05-fe43-5f7c50b2fe58.png)

ここに入力したいものを入れる。

4.参加者メールアドレスに
招待するメールを入れる。複数いれば、 「**,**」で区切る

####`最後に`
1.B2に「**=B2&C2&B3&C3&B4&C4&B5&C5&B6&C6**」を入力
2.生成されたリンクをクリックすると出来上がり！！！

後は保存を押せばOKです💖


招待をたくさん送らないと行けない、PMの方はゲシュタルト崩壊を起こすと思います。
そんな時には、このやり方でやってみてください🙆‍♀️


上のやり方で意味わかんないって方はチートに
→「https://docs.google.com/spreadsheets/d/1QHNtUhV2adJls6YPzSHPzG557iiXWsSPBe95PZE_5X8/edit?usp=sharing」　
このリンクを共有しておきます。コピーして使ってみてください。

-----

ここまで読んでいただき。ありがとうございました。
本当は上のやつをLINE Botでする方法を記事で書きたかったんですが、、、
ちょっとエラーに苦しめられて間に合いそうになかったので、今回は誰でも分かる、記事を書かせていただきました。
また、リベンジでLINE Botでできる方法書かせて頂きます…（多分）
【ABC226】C - Martial artist  をC++で解説 <Atcoder>

#初めに
　皆さんこんにちは！ 競プロの問題の理解を深めるために解説記事を書いていこうと思います！今回は **ABC226 C** です！
 気に入っていただけたら**LGTM**して頂けるとうれしいです！
何かあれば**コメント**や[Twitter](https://twitter.com/python05238919)からお願いいたします!

#[C - Martial artist](https://atcoder.jp/contests/abc226/tasks/abc226_c)
####問題概要
 $N$個の技において$1 \leq i \leq N$について技$i$での習得時間は$T_i$である．さらに技$i$を習得するには開始時点で技$A_{i,1}, A_{i,2}, ..., A_{i,K_i} $必要である．このときに技$N$を習得するのに必要な最小の時間を求めてください．

####制約
・$1 \leq N \leq 2 × 10^5$
・$1 \leq T_i \leq 10^9$
・$0 \leq K_i < i$
・$1 \leq A_{i,j} < i$
・$\sum^N_{i=1}K_i \leq 2×10^5$
・$A_{i,1}, A_{i,2}, ..., A_{i,K_i} $はすべて異なる
・入力はすべて整数
##考察
####ポイント
　・**技$N$が習得するのに必要な技を探索しましょう**
####解説
 ポイントにも書いた通り，$N$を習得するために必要な技を習得すればいいので，$A_{N,1}, A_{N,2}, ..., A_{N,K_N} $を習得する必要があります．さらに$A_{N,1}$を習得するときに必要な技があるのでその技も習得する必要があります．
　このように奥に深く探索していくので**DFS(深さ優先探索)**で最小の時間が求められると考えられます．
　実際に入力例2のときの5に必要な技は1, 2, 3, 4なのでこれをグラフにすると以下の図になります．
![無題の図形描画.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1836240/bb99c4e9-80dc-12fd-f52f-a1a7b080b333.jpeg)
それでは実装していきましょう．
#実装
 DFSの始点は$N$です．順番に見ていってDFSし終わった後に訪れた技の取得時間を足せばそれが答えとなります．計算量は$O(N)$となります．

##正解コード

```C++:
#include <bits/stdc++.h>
using namespace std;

vector<bool> seen;
//DFSの関数の定義
void dfs(const vector<vector<int>> &G, int v){
    seen[v] = true;
    for(auto next_v : G[v]){
        if(seen[next_v]) continue;
        dfs(G, next_v);
    }
}

int main(){
    //入力
    int N;
    cin >> N;
    vector<long long> T(N);
    long long ans = 0;
    seen.assign(N, false); //seenの初期化
    vector<vector<int>> G(N); //グラフの宣言

    for(int i = 0; i< N; i++){
        cin >> T[i];
        int k; cin >> k;
        for(int j = 0; j < k; j++){
            int a;
            cin >> a;
            a--;
            G[i].push_back(a);
        }
    }

    //DFSの開始
    dfs(G, N-1);

    //最後に訪れた技の取得時間を足す．
    for(int i = 0; i< N; i++){
        if(seen[i]) ans+= T[i];
    }

    cout << ans << endl;
}

```

##類題
[ABC231 - Neighbors](https://atcoder.jp/contests/abc231/tasks/abc231_d)(DFSやBFSで解くことができます)
Rubyで画像からテキストを認識する

# はじめに
テキストでいっぱいの画像があり、わからなくても意味はまだ知りたいと想像してください。その時にどうすれば良いですか。翻訳ツールを利用すると思い付きますね。翻訳したいのにどのように書かれているのかわからないので、その際に画像からテキストを取得する方法が必要になります。
それで今日はRubyで画像から文字を認識するを紹介したいと思います。
# 実装

画像からテキストを認識するため、`ImageMagick`と`Tesseract`を使います。
**ImageMagick**: Rubyに画像処理ツールです。

```
# インストール(MacOS)
brew install imagemagick
```

**Tesseract**: 光学式文字認識を使用してテキスト認識ツールです。現在、多くの言語をサポートしています。

```
# インストール(MacOS)
brew install tesseract
# training dataはどこで保存しているか確認するコマンド
brew list tesseract
```
training dataフォルダで画像からテキスト認識する言語の保存が必要です。今回は英語(`eng.traineddata`)を使います。他の言語を利用する場合は[サポート言語](https://github.com/tesseract-ocr/tessdata)を参考してください。


### 画像からテキストを認識する手順

仮に以下の画像からテキストを取得したいなら、
![test_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548029/b17d2172-7368-5281-e599-489a09ea3f04.png)

#### 1. 画像を白黒に変換（グレースケール）

2段階と3段階に利用するために、まずは画像を白黒に変換するのが必要です。

```ruby
require 'pathname'
require 'open3'
require 'mini_magick'

INPUT = '/Users/duong.nguyen/Desktop/input'.freeze    # 元の画像を保存するフォルダ
OUTPUT = '/Users/duong.nguyen/Desktop/output'.freeze  # 処理した画像を保存するフォルダ

Pathname.new(INPUT).children.each do |f|
  src_path = f.realpath
  tmp_path = "#{OUTPUT}/#{f.basename}"

  img = MiniMagick::Image.open(src_path)
  img.colorspace('Gray')
  img.write(tmp_path)
end
```
上記のコードを実行すると、元の画像から白黒にしました。
処理した画像：
![test_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548029/cf2311a7-27cd-cdc8-a9b7-5c07deb36a4e.png)
#### 2. 画像のクリーニング

不要なものを消すため画像を黒色にします。 これは、`Tesseract`がテキストをもっとよく認識するのに役立ちます。

```ruby
# ...
Pathname.new(INPUT).children.each do |f|
  # ...
  MiniMagick::Tool::Convert.new do |magick|
    magick << tmp_path
    magick.negate
    magick.threshold('007%')
    magick.negate
    magick << tmp_path
  end
end
```
処理した画像：
![test_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548029/0a5d949a-1467-d739-e5ec-08aa0ad38518.png)

#### 3. テキストの認識
`tesseract`を使用してテキストを認識し、`open3`を使用して返されたテキストを`capture`します。

```ruby
# ...
Pathname.new(INPUT).children.each do |f|
  # ...
  text, _xxx, _yyy = Open3.capture3("tesseract #{tmp_path} stdout -l eng --oem 0 --psm 3")
  puts text.strip
end
```

#### 認識したテキスト

```text
We would all be
living there together.
```
### 全てのコード

```ruby
require 'pathname'
require 'open3'
require 'mini_magick'

INPUT = '/Users/duong.nguyen/Desktop/input'.freeze
OUTPUT = '/Users/duong.nguyen/Desktop/output'.freeze
Pathname.new(INPUT).children.each do |f|
  # Step 1
  src_path = f.realpath
  tmp_path = "#{OUTPUT}/#{f.basename}"
  img = MiniMagick::Image.open(src_path)
  img.colorspace('Gray')
  img.write(tmp_path)
  # Step 2
  MiniMagick::Tool::Convert.new do |magick|
    magick << tmp_path
    magick.negate
    magick.threshold('007%')
    magick.negate
    magick << tmp_path
  end
  # Step 3
  text, _xxx, _yyy = Open3.capture3("tesseract #{tmp_path} stdout -l eng --oem 0 --psm 3")
  puts text.strip
end
```
# 終わりに
テキスト認識の正確的は画像の種類によるとか、画像のクリーニングが良いかどうかなどと思います。それで、いくつかのケースで上の方法で文字を認識できない可能性があるため、テキスト認識のレベルが完全に正確ではないですね。
上記は、Rubyで基本的で画像からテキストを認識する手順です。
画像関連の処理が必要な場合に役立つと願っています。:grin:

**参考**：https://aonemd.me/posts/extracting-text-from-images-using-ruby/
VBScript版Dir関数

VBScript には、ワイルドカードでファイルの存在を検索できる Dir関数がないので、ファイル名を正規表現で検索できる VBScript版Dir関数を作ってみる。

```vb:VbsDir
'// ファイル名に正規表現の使用が可能
'//［opt:0］見つかった最初のファイル名を返す（無い場合は "" を返す）
'//［opt:1］見つかったファイル名の配列を返す
'//［opt:2］見つかったファイル名のリストを改行区切りで返す

Function VbsDir(ByVal name_pattern, ByVal opt)

    Dim regx, namesAry, fl, getNames: getNames = ""

    Set regx = CreateObject("VBScript.RegExp")

    '// 大文字・小文字を区別しない
    regx.IgnoreCase = True

    With CreateObject("Scripting.FileSystemObject")
        regx.Pattern = .GetFileName(name_pattern)
        For Each fl In .GetFolder(.GetParentFolderName(name_pattern)).Files
            If regx.Test(fl.Name) Then getNames = getNames & fl.Name & vbCrLf
        Next
    End With

	If getNames = "" Then
		namesAry = Array("")
	Else
    	namesAry = Split(getNames, vbCrLf)
    End If
    
    Select Case opt
    	Case 0
    		VbsDir = namesAry(0)
    	Case 1
    		VbsDir = namesAry
    	Case 2
    		VbsDir = getNames
    	Case Else
    		VbsDir = namesAry(0)
    End Select

End Function
```

テスト結果：

```vb
Dim namePattern
namePattern = "C:\Program Files\Microsoft Office\root\Office16\.*exe$"
Msgbox VbsDir(namePattern, 0)
' ⇒ ACCICONS.EXE
Msgbox VbsDir(namePattern, 2)
' ⇒ ACCICONS.EXE CLVIEW.EXE CNFNOT32.EXE EXCEL.EXE・・・
```
UnrealEngineのコンパイル/リンクオプションについて

2021アドベントカレンダーの記事です。

#はじめに
UnrealEngineはエディタやアプリケーションの実行ファイルを作るためにC++を用いてビルドを行います。
ビルドは対象のプラットフォームに向けたバイナリを生成できるコンパイラにソースファイルをコンパイルしてもらうことで行われます。このときコンパイラに向けてデバッグ情報の有無や関連するソースファイルやヘッダファイルの指定、最適化オプション、言語に対する指定などを **コンパイルオプション** として渡していますが、UnrealEngineでは[UnrealBuildTool](https://docs.unrealengine.com/4.27/ja/ProductionPipelines/BuildTools/UnrealBuildTool/)がコンパイラに関する操作を包括して制御するため、個々のコンパイルオプションを操作する必要はありません。

が、
「最適化用に設定を変更したんだけど本当に適用されているのかな？」
とか
「謎のリンクエラーがでてしまった。。。リンクされているライブラリがなにかおかしい？」
といった、コンパイラの動作に確信がもてなくて困ったり、環境に依存したビルドエラーなどに遭遇して頭を悩ませることがあります。
本記事ではこれらの確認方法などについて解説したいと思います。

#オプションは一旦ファイルに出力されてコンパイラに渡される

UBTのソースコードの内部でこれらを制御するコードを見つける事ができます。

```VCToolChain.cs
					FileReference ResponseFileName = new FileReference(TargetFile.AbsolutePath + ".response");
					FileItem ResponseFileItem = Graph.CreateIntermediateTextFile(ResponseFileName, SharedArguments.Concat(FileArguments).Concat(AdditionalArguments).Select(x => Utils.ExpandVariables(x)));
					CompileAction.CommandArguments = " @\"" + ResponseFileName + "\"";

```
".response"という文字列が見えますね！UBTはコンパイルオプションを配列にまとめたあと、 **"[出力ファイル名].response"ファイル** に一旦出力し、それをコンパイラに渡しています。
responseファイルは単純なテキストファイルなのでビルドした後にこのファイルを確認することでコンパイラに渡されているオプションを確認することができます。


##ファイルの配置位置
###cppファイル-コンパイルオプション
Intermediateフォルダ以下で、`*.cpp.obj.response` ファイルを探します
ターゲットプラットフォームフォルダの下のフォルダは、エディタをビルドする場合はUE4Editorフォルダ、モノシリックビルド(いわゆるパッケージビルド)の場合はプロジェクト名のフォルダに置かれます。


`[プロジェクトフォルダ]\Intermediate\Build\[ターゲットプラットフォーム]\[UE4Editor or プロジェクト名]\[コンフィギュレーション]\[モジュール名]\[ソースファイル名].cpp.obj.response`

####例
`D:\dev\UE427projects\myproject\Intermediate\Build\Win64\myproject\Development\mymodule\hogehoge.cpp.obj.response`
最適化オプションやコンパイラから渡すマクロ定義、警告抑制オプション、インクルードパスなどが確認できます

```hogehoge.cpp.obj.response
/Zc:inline
/nologo
/Oi
/c
/Gw
/Gy
/Zm1000
/wd4819
/D_CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1
/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1
/D_WINDLL
/D_DISABLE_EXTENDED_ALIGNED_STORAGE
/source-charset:utf-8
/execution-charset:utf-8
/Ob2
/Ox
/Ot
/GF
/errorReport:prompt
/EHsc
/Z7
/MD
/bigobj
/fp:fast
/Zo
/Zp8
/we4456
/we4458
/we4459
/wd4463
/we4668
/wd4244
/wd4838
/I .
/I ..\Intermediate\Build\Win64\UE4Editor\Inc\Engine
/I Runtime
/I Runtime\Engine\Classes
/I Runtime\Engine\Public
以下略
```


###exeファイル-リンカオプション
Intermediateフォルダ以下で、`*.exe.response` ファイルを探します。

`[プロジェクトフォルダ]\Intermediate\Build\[ターゲットプラットフォーム]\[UE4Editor or プロジェクト名]\[コンフィギュレーション]\[プロジェクト名].exe.response`

####例
`D:\dev\UE427projects\myproject\Intermediate\Build\Win64\myproject\Development\myproject.exe.response`

#まとめ

コンパイラが変わったりエンジンのバージョンをあげた時に単純なコンパイルエラーではない問題が出た時や、特定の開発環境でのみビルドエラーが起きる場合などに、今回ご紹介した*.responseファイルを調査することで解決につながる可能性があります。
ターゲットのプラットフォームが違ってもおおざっぱに同じ仕組みを使っているので "\*.lib.response"  , "\*.dll.response" , "\*.self.response" , "\*.nss.response" などの名前で検索してみるとよいかもしれません。
herokuで急にrailsがdeployできなくなった

# 起こった事象

- 急にherokuでrailsがdeployできなくなった
- メールで「Automatic deployment of app名 failed.」とくる
- 構成は下記
  - rails6
  - webpacker 4.3.0

# 対処

結論から言うとherokuのnodeのversionが上がってwebpackerで使っていたnode-sassのversionが対応しなくなってdeployできなかった

対処法としては下記

- webpackerのversionを上げて現在のherokuのnodeに対応したものにする
- herokuのnodeのbuild packを入れてversionを指定する

後者が楽だがwebpackerが古すぎたのとwebpackerで使っているnode-sassがもう非推奨になっていたためこの機会にwebpackerをversionアップしてnode-sassも消そうと思った。


## webpackerのversionアップ手順

苦しんで覚えるwebpackerのバージョン更新
https://zenn.dev/teitei_tk/articles/cd20ff6b66c51b

上記記事を参考にアップデート。

下記３つを更新

- yarnで@rails/webpackerを5.4.3に
- gemのwebpackerを5.4.3に
- webpack-dev-serverを最新に

webpackerは最近6が出たが

https://github.com/rails/webpacker/blob/master/CHANGELOG.md

あまりにも新しいのと6は結構変わってそうなので5.4.3に。

## gemfile

```gemfile
gem 'webpacker', '~> 5.4'
```

```
docker-compose run web bundle update --conservative webpacker
```

conservativeをつけて他は更新されないように

```
docker-compose run web yarn upgrade @rails/webpacker@5.4.3
```

```
docker-compose run web yarn upgrade webpack-dev-server --latest
```

上記でwebpack-dev-serverも更新


# nodeのbuildpackを入れてversion指定

https://zenn.dev/junki555/articles/400589974d3034

今回はやらなかったが上記でversion指定するやり方もあり
Vim Meme

[Vim advent calendar 2021](https://qiita.com/advent-calendar/2021/vim) 19日目の記事です。

# 概要
Redditを眺めていたり海外のサイトででてくる Vim Meme たち。
その多くは、ほとんどが同じような内容の揶揄で構成されています。
その操作性や難解さについて人々は常に錯乱しているようです。
正直終わらせ方についてのネタが多すぎます。
__*Vimに比べてVimMemeのクリエイティビティは低く、Vimより敷居が低いです。*__

# Vimドヤ
## プーさんVimのコピーに興奮
![notepad-c-copy-vim-y-yeet-how-i-remember-copying-63476708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/2150fcd6-4999-5fb3-1464-6bee2be26adf.png)

yeetで覚えたことについて興奮を表しています

## Vimの魔力
![vim-ide-devs-cast-it-into-the-fire-destroy-it-62740435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/7b0675a6-98fb-2dba-8443-bd71034653f6.png)

リングの魔力と同じ

## 終了の仕方を知っただけでこれ
![scientist-vim-meme.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/eba53ae2-7731-d43a-6552-fa75f2087e10.png)


# Vimの難解さを揶揄
## vimが終わらない
https://twitter.com/iamdevloper/status/435555976687923200

定番中の定番

## Vimネタでスタンダップコメディにでるカラス
![one-joke.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/3a0e64c3-c89b-28f8-a9c9-dcdeaf6edbb1.png)
カラスが見ているのはカンペ(ネタ帳）です

## 全能ムーブ
![3e88c2d114591bb621d00298544562dc.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/7ec0ff05-ed1c-74c2-6842-913c6b07d539.jpeg)
ちなみによくみるこれはここでつくれます
https://mat3e.github.io/brains/

## Vimの終わらせ方
https://twitter.com/brunns/status/941320476894334977

ロンドン、Vimイングランド代表のツイート

## He's Not Your Man Meme
https://twitter.com/cassidoo/status/1067576992101412864

リプライ欄の方が味わい深い

## Vim Exit% Speedrun (動画)
https://youtu.be/TLbfqZBL8t8

最初に見た時バカらしすぎて笑ってしまった。

# Vimを使うとマッチョになっちゃう(操作性について)
## I Do One Push-up の vimネタ
![9i5y5qplvc171.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/4b42947d-45cc-eefb-3c96-7e6ad08a0ddf.png)

## マッチョネタ2
![vim-user-problems-71455420.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185747/027cbac8-a9ce-f8da-89ef-9091ba06590f.png)

# 最後に
英語とスペイン語のネタはよく見るのですが、日本語はかなり少ないです。
もしかしたらこういったネタにすることがVimの利用者上昇に起因するかもしれません。
Vimを勉強すればこのネタがわかるよというのがVim入門のパワーワードになるとかならないとか！？

日本語だとミルクボーイ風のがあります。

https://youtu.be/P7LNU9HYr7M
logモジュールについて

[新しいPythonエディタのαリリース](https://python.microbit.org/v/alpha)で使える最新の MicroPython (執筆時点では 2.0.0-2021-10-25)で使える新機能 第２弾です。

# `log` モジュールとは

MakeCode の拡張機能 Data Logger に相当するものです。micro:bit 内のストレージにセンサー値などのデータを溜め込んで、後で参照したり、CSV形式で取り出したり、グラフ表示できます。

![スクリーンショット 2021-12-19 10.05.32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/bf0152fe-d233-6903-8435-d3c45cc697f5.jpeg)

# `log` モジュールのAPI



## `log.set_labels(*args)`

ログのヘッダを設定します。MakeCodeの`set columns`ブロックに相当します。

ヘッダの項目を文字列で並べて指定します。たとえば温度センサーと光センサーの値を記録するつもりであれば、次のように設定しておきます。

```python`
set_labels('temperature', light')
```

オプションでタイムスタンプの単位を `timestamp` 引数で指定できます。これはMakeCodeの`set timestamp`ブロックに相当します。`timestamp`引数に指定できる値は次のとおりです。

|timestamp|説明|
|---|---|
|log.MILLISECONDS|ミリ秒単位。デフォルト。|
|log.SECONDS|秒単位|
|log.MINUTES|分単位|
|log.HOURS|時単位|
|log.DAYS|日単位|

## log.add(log_data)

データを記録します。MakeCodeの `log data` ブロックに相当します。

データの指定には、名前つき引数で指定する方法と、辞書オブジェクトで指定する方法があります。

```python
add(temperature=t, light=l)  # 引数名はset_labelsに指定した項目名と一致している必要あり

add({"temperature":t, "light":l})  # 辞書のキーはset_labelsに指定した項目名と一致している必要あり
```

## log.delete()

記録されているデータを(ヘッダも含めて)削除します。MakeCodeの~delete log'ブロックに相当します。

## set_mirroring(serial)

ログの記録を UART にも出力していきます。MakeCodeに該当する機能はありません。

# サンプル

ユーザガイドの[Data logging with the micro:bit](https://microbit.org/get-started/user-guide/data-logging/)にあるMakeCodeの例をMicroPython用に書き換えてみました。

加速度センサー x, y, z の値が記録されます。
Aボタンで記録する/しない状態を切り替えます。
A+Bボタンでログを削除します。

今のところ、ログ領域がフルになったことを検出する機能は無いので、ログが一杯になったら記録を止める機能は実現していません。

```python
from microbit import (accelerometer,
                      display, Image, 
                      button_a, button_b,
                      run_every)
import log


logging = False
log.set_labels('x', 'y', 'z', timestamp=log.SECONDS)


@run_every(ms=100)
def logging_xyz():
    if logging:
        log.add(x=accelerometer.get_x(),
                y=accelerometer.get_y(),
                z=accelerometer.get_z())


def on_button_a_pressed():
    global logging
    logging = not logging
    if logging:
        display.show(Image.HEART)
    else:
        display.clear()


def on_button_a_and_b_pressed():
    display.scroll("deleting log")
    log.delete()


@run_every(ms=100)
def hundle_button_action():
    if button_a.is_pressed() and button_b.is_pressed():
        while button_a.is_pressed() or button_b.is_pressed():
            pass
        on_button_a_and_b_pressed()
    elif button_a.is_pressed():
        while button_a.is_pressed():
            pass
        on_button_a_pressed()
```

実行すると、MICROBIT フォルダに `MY_DATA.HTM` というファイルができるので、これを開いて表示します。

![スクリーンショット 2021-12-19 10.57.51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/39386e03-246a-ce01-f25a-ef1d9bf3249c.jpeg)

次のように表示されます。`Download` ボタンをクリックするとCSVファイル形式でデータをダウンロードできます。

![スクリーンショット 2021-12-19 10.59.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/a7bc17a9-8752-d977-3db5-c37d9a4ac77a.jpeg)

`View preview` ボタンをクリックすると、データをグラフ表示できます。

![スクリーンショット 2021-12-19 11.02.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/cfc3236d-acd9-346a-923c-28bf45501076.jpeg)
JavaScriptで集合演算

「和集合」と「共通部分」と「部分集合か判定」するメソッドです。

```js
// 和集合
function union(a, b) {
    return a.concat(b).filter((e, i, r) => r.indexOf(e) === i);
}

// 共通部分
function intersection(a, b) {
    return a.filter(e => b.includes(e));
}

// 部分集合か判定 (a⊂b なら true を返す)
function isSubset(a, b) {
    return a.every(e => b.includes(e));
}
```
Next.jsでアニメーションパッケージ(ScrollReveal)を使用する際の注意点

## はじめに
Next.jsを使用しているプロジェクトにアニメーションを使用する機会があり、そこで、Next.jsの概念周りで理解力不足ではまった点があるので、記録として残しておきます。

## Next.js(ssgやssr)でアニメーションをする際の注意点
自分がハマったのが、ScrollRevealというパッケージを使用して、スクロールすると対象の要素がふわっと浮き上がるアニメーションを実装しようとした時です。
https://scrollrevealjs.org/

```
//jacascript インストール
npm i (yarn add) scrollreveal
```

```
//typescriptインストール
npm i (yarn add) @types/scrollreveal
```

まず、すのReactでのコードを見ていきます。

```typescript
import { useRef, useEffect } from "react";
import { NextPage } from "next";
// ビルド時にimportしている
import scrollReveal from "scrollreveal";

type Props = {
  move: string;
  delay: number
  className?: string
}

const ScrollReveal: NextPage<Props> = ({
  children,
  move,
  delay,
  className
}) => {
  const sectionRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    async function animate() {
      if (sectionRef.current) {
        //ここに注目
        scrollReveal().reveal(sectionRef.current, {
          delay: delay,
          opacity: 0,
          origin: move,
          distance: "20px",
          viewFactor: 0.2
        })
      }
    }
    animate()
  }, [sectionRef])
  return <div className={`${className}`} ref={sectionRef}>{children}</div>
};
export default ScrollReveal;
```

このように、記述できます。

しかし、Next.jsでSSG(静的サイトジェネレーション)、SSR(サーバーサイトジェネレーション)を用いた開発を行う際、yurn build もしくは npm run buildする際に document is not defined というエラーが出てきます。

### エラーの原因
ScrollRevealパッケージをimportする際、パソコンの情報(windowの横、縦幅など)が必要なんですが、ビルド時には、それらの情報は存在しないのでエラーが出ます。

### 解決策
ビルド時にScrollRevealをimportせずに、ユーザーがパソコンでサイトを開いたタイミングでScrollRevealをimportする。

### 具体的な解決策
まず、Next.jsには **Dynamic import** というパッケージのimport方法があるのでこの技術を使用してエラー回避します。

#### [Dynamic Import](https://nextjs.org/docs/advanced-features/dynamic-import)
これは、動的にパッケージをimportする技術です。(動的というとわかりにくいので、ユーザーがサイトを開いたタイミングというふうに認識しています。間違ってたらごめんなさい。。。)
つまり、ビルド時、サーバーサイドではScrollRevealパッケージをimportせずに、ユーザーがサイトを訪れたタイミングで初めてimportし、document is not definedを回避するということです。

### Next.jsでのコード
```typescript
import { useRef, useEffect } from "react";
import { NextPage } from "next";
//importしていない


type Props = {
  move: string;
  delay: number
  className?: string
}

const ScrollReveal: NextPage<Props> = ({
  children,
  move,
  delay,
  className
}) => {
  const sectionRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    async function animate() {
      if (sectionRef.current) {
        //Dynamic import
        const sr = (await import("scrollreveal")).default
        sr().reveal(sectionRef.current, {
          delay: delay,
          opacity: 0,
          origin: move,
          distance: "20px",
          viewFactor: 0.2
        })
      }
    }
    animate()
  }, [sectionRef])
  return <div className={`${className}`} ref={sectionRef}>{children}</div>;
};
export default ScrollReveal;
```

このように記述を変更すれば、エラー回避できます！！

### まとめ
Next.jsでは、概念から理解しないとハマるところではハマるので難しいです。
やさしいD言語クイズ（その２）

# はじめに

`やさしいD言語クイズ`の第２弾です。
[第１弾](https://qiita.com/devmynote/items/2c3763246f74ef983fcd)から、読んでいただけると幸いです。

# 問題４
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

```d:
import std;
void main()
{
	int[] a = [1, 2, 3];
	int[] b = a;
	int[] c = a.dup;
	int[] d = a ~ [];
	int[3] e = a;
	a[1] = 5;
	writeln(a[1], b[1], c[1], d[1], e[1]);
}
```

# 問題５
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

```d:
import std;
void main()
{
	try {
		try {
			write("1");
			throw new Exception("2");
		} finally {
			write("3");
			throw new Exception("4");
		}
		write("5");
	} catch (Exception e){
		write(e.msg);
	}
	try {
		write("6");
		goto L1;
	} finally {
		write("7");
	}
	write("8");
L1:
	write("9");
}
```

# 問題６
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

```d:
import std;
void func1(char b){
    write(1);
}
void func1(int b){
    write(2);
}
void func1(long i)
{
    write(3);
}
void func2(byte b){
    write(4);
}
void func2(int i)
{
    write(5);
}
void main()
{
    func1(0x61); // 0x61 = 'a'
    func1('a');
    func1(1L);
    func2(1L);
}
```

:::note warn
ここから回答編です。ネタばれ注意！！
:::

# 問題４の答え

<details><summary>問題４の実行結果</summary><div>

```text:問題４の実行結果
55222
```
</div></details>

シャローコピー、ディープコピーについては、[D言語の配列コピーでの注意点](https://qiita.com/devmynote/items/3d52f846922491301d0c)にも書きています。参考までに。

答えの補足

* `b`はシャローコピーです。`a`と同じ内容を指しています。
* `c`は`dup`を使っているので、ディープコピーです。
* `d`は配列の結合結果を代入します。配列の結合処理時に新たに領域を確保するため、ディープコピーになります。
言語仕様によると、空の配列との結合処理であってもディープコピーとなります。

* `e`は静的配列への代入のため、ディープコピーになります。

https://dlang.org/spec/arrays.html#array-concatenation

# 問題５の答え

<details><summary>問題５の実行結果</summary><div>

```text:問題５の実行結果
132679
```
</div></details>

答えの補足

* `Exception("2")`が発生しますが、`catch`より先に`finally`ブロックが処理されます。
* ただし`4`は出力されません。`Exception`が起因で`finally`ブロックに入る場合は、`finally`ブロック内にある`Exception`は処理されず、フォールスルーされる仕様のためです。
* `try`ブロック内で`goto`でのジャンプが発生しても、`finally`ブロックは処理されます。

https://dlang.org/spec/statement.html#try-statement

# 問題６の答え

<details><summary>問題６の実行結果</summary><div>

```text:問題６の実行結果
2134
```
</div></details>

答えの補足

* `0x61`は、`int`型の定数です。
* `'a'`は、`char`型の定数です。
* `1L`は、`long`型の定数です。
* `func2(1L)`については`func2(long b)`が存在しません。オーバーロード関数に合致する型がない場合の言語仕様は、
 * 引数の型変換を行うことで関数を利用可能か、コンパイラがチェックします。
 * チェックした結果、複数の関数が利用可能であれば、利用可能な範囲が狭い関数が選択されます。
 * `byte`の利用可能範囲は`-128～127`(8bit符号付き)、`int`の利用可能範囲は、`-2,147,483,648～2,147,483,647`(32bit符号付き)のため、利用可能範囲が狭い`func2(byte b)`が呼び出されます。

https://dlang.org/spec/function.html#function-overloading

# 最後に

時間ぎりぎりまで問題を考えましたが、今回はここまでです。
来年の今ごろに、より面白い問題が作れるよう、言語仕様の勉強を続けようと思います。
Goのnet/httpはクエリーパラメータもx-www-form-urlencodedが透過的に扱える

[Goアドベントカレンダー](https://qiita.com/advent-calendar/2021/go)の欠番があったので穴埋めで書きました。

ちょっとウェブアプリケーション開発をがんばった経験がかなりある人であったり、Real World HTTPの熱心な読者であったり、Real World HTTPの熱心な読者の人であれば、フロントエンドからサーバーにデータを送信する手段が何種類もあることはご存知でしょう。

* クエリー(URL)
* ヘッダーフィールド
* ボディ

本ではステータスコードも入れて4兄弟のように説明していたけど、サーバー→クライアント方向なのでここでは触れないでおきます。このうちヘッダーはメタデータなのでここで扱うのは2つですが、ボディを使うのは主にフォームのポスト(x-www-form-urlencodedとmultipart/form-data)と最近はJSONですね。

* クエリー(URL)
* ボディ
  * x-www-form-urlencoded
  * multipart/form-data
  * JSON

GoのAPIはJSON以外の3つが微妙に透過的に扱えるけど微妙にクセがある挙動なのでまとめておきます。

Goでリクエストからデータにアクセスするメソッドが3つあります。

* `FormValue()`
* `PostFormValue()`
* `FormFile()`

これらのメソッドは`ParseForm()`や`ParseMultipartForm(maxMemory int64)`の結果が入る`Form`は`PostForm`にアクセスしますが、必要に応じてこれらのパースのメソッドも呼んでくれます。なお、マルチパートのmaxMemoryはデフォルトで32MBなのでそれ以上のファイルを扱いたい場合は自前で呼ぶ必要があります。

|  | `FormValue()` | `PostFormValue()` | `FormFile()` |
|:-|:-:|:-:|:-:|
| クエリー | ○ |  |   |
| x-www-form-urlencoded | ○(優先) | ○ |   |
| multipart/form-data(ファイル以外) |   | ○ |   |
| multipart/form-data(ファイル) |   |   | ○ |

同じキーのものがクエリーとx-www-form-urlencodedの両方にあるとx-www-form-urlencodedの方が優先される点は要注意ですが、まあそんなAPI設計にはしないと思うので（swagger上もやっかい)、まあ無視してもいいかと思います。

自動生成でがつっと生成する時は、このあたりのAPIを自分で呼ぶことはないと思いますが、これの何が便利かというと、テストで便利ですよね。次のようなリクエストはGETだけどボディがx-www-form-urlencodedでエンコードされたリクエストという変則的なリクエストになりますが、クエリーで渡すのと同じように`FormValue()`で値が取れます。

```bash
$ curl -X GET -d "searchparam=small animal" http://localhost:8000/search
```

自分でエンコードとか頑張らなくてもcurlで気軽にリクエストが投げられて便利ですね。
pythonで自然言語処理のためのtwitterから取得したテキストの前処理

#はじめに
自然言語処理をやってみようと思い、twitterからテキストを集めました。
tweepyを使って過去のツイートを取得しましたが、前処理に手間取ったので、その前処理方法を紹介します。

#困ったこと
・絵文字の処理でemojiモジュールを使ったが、取り除ききれなかったものがあった
　unicodeで\uf353や\uf605など
・改行をコードを取り除くと文章がつながってしまう
　例
　楽しかった
　いい一日だった　→　楽しかったいい一日だった

#やったこと
・「絵文字を取り除く」ではなく「英数字・日本語のみ取り出す」とする
・改行コードを読点"。"に置き換える
　twitterテキストでの改行は文の区切りを意味するため

#実装
###絵文字の除去
reモジュールを使って１文字ずつ英数字・日本語かどうかを判断し、英数字・日本語であれば残す、とします。1行目は半角英数記号、ひらがな・カタカナ、漢字、句読点などの記号の文字コードのコンパイルです。2行目で文字を1つずつ取り出し、判定します。

```Python:
n = re.compile(r"[\u0020-\u007e\u3040-\u30FF\u4E00-\u9FFF\u3000-\u303F]") #文字コードコンパイル
result = "".join(t for t in text if n.search(t)) #一文字ずつre.searchで判定

#\u0020-\u007e 半角英数記号
#\u3040-\u30FF ひらがな・カタカナ
#\u4E00-\u9FFF 漢字
#\u3000-\u303F 句読点などの記号
```

###改行コードの置き換え
こちらは単純に"\n"を"。"に置き換えます。

```Python:
result = re.sub(r"\n", "。", text)
```

#完成
テキストの正規化(neologdn.normalize())、urlの除去を加えたtwitterテキストの前処理関数が以下になります。

```Python:
def fix_twitter_text(text):
    normalized_text = neologdn.normalize(text) #テキストの正規化
    text_without_url = re.sub(r"https?://[\w/:%#\$&\?\(\)~\.=\+\-]+", "", normalized_text) #url除去
    text_replace_newline = re.sub(r"\n", "。", text_without_url) #改行コードを読点に置き換え
    n = re.compile(r"[\u0020-\u007e\u3040-\u30FF\u4E00-\u9FFF\u3000-\u303F]")
    result = "".join(t for t in text_replace_newline if n.search(t)) #絵文字除去
    return result
```

#おわりに
twitterから取得したテキストの前処理を紹介しました。力技な気もしますが、実現したいことはできました。これでtwitterのテキストで自然言語処理をしてみます。(Twitter APIは1週間以上前のデータも取得できるようにしてください）
RDS(リモートデスクトップサービス)におけるEdge のプロファイル管理について

本記事は以下サイトにて記載しています。
恐れ入りますがリンクから移動してご参照ください。

RDS(リモートデスクトップサービス)におけるEdge のプロファイル管理について
https://cloudsteady.jp/post/51917/
　
　
現在パーソルプロセス＆テクノロジーではAdvent Calendar 2021を開催中です。
https://qiita.com/advent-calendar/2021/ppt

こちらも興味ある記事あれば是非ご参照ください。
Udemyでwebについて学習したことまとめ②

# Udemyにて学習したことについて備忘録としてまとめてみました。

[Udemyでwebについて学習したことまとめ①](https://qiita.com/h_ishida_study/items/db7b990beb486925a03e) 
の続きになります。
備忘録のようなものですが、もしご興味あれば
引き続きお付き合いください。。。

## HTML文章の基本構造
### 以下HTMLの構造と説明となります。
- DOCTYPE宣言
 - 使用するHTMLの種類を宣言
- html要素
 - HTML文章の最上位要素
- head要素
 - 文章タイトル、文字コード、キーワード、説明文、関連ファイルなどの文章の基本構造
- body要素
 - 本文

#### メタデータ
データに関する情報を記す。
例)このデータはキャラセットUTF-8を使用する。
```<meta charset="UTF-8">```

#### title
ブラウザのタブに表示されているタイトル
例)```<title>はじめてのHTML</title>```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/772193b6-e34f-f8d4-50b8-5db3e9056a2c.png)


#### html lang
言語設定
例)日本語を使用する。
```<html lang="ja">```

## 要素の入れ子とドキュメントツリー
### 要素の入れ子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/5fe39312-3bc7-741f-c67a-1c54089b2b3e.png)

### ドキュメントツリー
ドキュメントツリーはDOMと呼ぶ。
それぞれをオブジェクトとみなし、オブジェクトをノードと呼ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/adddc143-ef65-8105-4d77-d848ee40076c.png)

## はじめてのHTML
### VSCodeを使用した、htmlファイルの作成を解説

1.FileからOpen Folderをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/73caa134-e10d-8ff8-6780-33fb81297c35.png)

2.今回使用するフォルダを選択し(testフォルダ)フォルダーの選択ボタンを押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/98b3334a-9e90-fb54-6d81-60bc8da3904c.png)

3.New Folder(赤枠のアイコン)を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/1740c2f6-9a58-387c-bdc8-89b7db285581.png)

4.フォルダ名(今回はhtml-basicとする)を付ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/72d9beed-42f6-4e3b-fc18-7152c289df85.png)

5.右クリックでNew Fileを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/b5d31234-c15d-1fe6-f219-b4dedc892252.png)

6.ファイル名(拡張子.htmlにする)を付ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/50131e4d-a979-dbcf-9978-038ba32e1584.png)

7.作成されたファイルにhtml文章を書きこんでいく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1921604/a793ae42-0f00-5d4c-cdc4-e8bde2032f31.png)




##### 参考
###### この記事は以下を参考にして執筆しました。
[Udemyのサイトはこちら](https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwj86qmaoqb0AhUUBGAKHRAoCO0YABAAGgJ0bQ&ohost=www.google.com&cid=CAASEuRosiI9g8wWMNM3IWv9qNg99A&sig=AOD64_0WiuxeRJ3LvyKKWDBRZheaW9AEWQ&q&adurl&ved=2ahUKEwj0gqSaoqb0AhUOiZQKHTbUDj8Q0Qx6BAgCEAE)
Linuxを学び始めたので歴史の備忘録

#目的
Linuxを学び始めたので歴史の備忘録

#Linuxとは
　OSの一種で、コンピューターを動かすための基本ソフト（OS：Windows、Mac OS X、Linux、Android）

・inuxはどのように誕生したの?
　● Unix というOSが誕生
　　1970年頃
　● シンプルな小さいOSで大学や研究所を中心に普及 ●有料。 ライセンス縛りも厳しい
　●オープンソース版のUnixを開発するプロジェクトがスタート
　　1985年~
　　ソースコードも公開されていたので、 様々な派生版のUNIXが誕生
　　1991年
　　当時大学生のリーナス・トーバルズがLinuxを開発し、 オープンソース化
　●UNIXを真似て、 一からOSを作る
　●最終的に最も普及
　　有料のUnixが､ Linuxという形で、 無料で使えるようになった

#Linuxの特徴と欠点
　特徵
　● オープンソースなので誰でも自由に使える
　●世界中で使われていて信頼性が高い
　●品質の高い多くのソフトウェアが利用できる
　●自動化するための仕組みがあり、 サーバーの運用が行いやすい
　欠点
　●商用アプリケーションがあまり存在しない
　　- Microsoft Officeが動作しない
　   - 画像、音楽､動画などのマルチメディア系ファイルを編集するのが苦手
　●日本語対応されていない部分が多い

#まとめ
　● LinuxとはOSの一種で、 コンピュータを動かすための基本ソフト
　● 1991年にリーナス・トーバルズがUnixをベースに一から開発
　●現在では大変普及しており、サーバー、 組み込み、 デスクトップといった幅広い用途で使われている
　● 特徵
　　-オープンソースなので誰でも自由に使える
　　-品質の高い多くのソフトウェアが利用できる
　●欠点
　　-商用アプリケーションがあまり存在しない 
　　-日本語対応されていない部分が多い

#参考
Linux Udemy「もう怖くないLinuxコマンド」
RubyのC拡張でサブディレクトリに配置したCファイルを使いたい！ ー symbol lookup error を回避する

## はじめに

RubyのC拡張でバインディングを作成する場合、`ext/fooba` にCファイルを配置する。伝統的なRubyのGemはこのディレクトリにフラットにCファイルを展開するようだ。けれども、サブディレクトリを使いたい場合がある。具体的には Git submoduleなどで、バインディング先のCのライブラリを `ext/foobar` に配置してバージョン管理したいような場合だ。

その場合、`$INCFLAGS` や `$VPATH` を利用するという方法がよく紹介される。

```
INCFLAGS << " -I$(srcdir)/libFooBar"
VPATH    << " $(srcdir)/libFooBar"
```

しかしこの方法は一見すると`rake compile`が成功するのだが、いざテストを実行すると、と symbol lookup error が発生する。そして `ldd` をしても特に足りない共有ライブラリなどはない。どうすればいいのだろうか？

## どうればいいのか？ 一つの方法

インターネット上を探しても回答は多くない。

[mysqlバインディング](https://github.com/brianmario/mysql2/tree/master/ext/mysql2)や、[opencvバインディング](https://github.com/ruby-opencv/ruby-opencv/tree/master/ext/opencv)のような有名なGemを参考にしようと見に行っても、１つのディレクトリで構成されている。

それでも[英語のStackOverFlowにこの問題に対する回答](https://stackoverflow.com/questions/40336693)があった。大域変数 `$obj` を指定すればいいそうだ。

たとえば、次のような方法である。

```ruby
$objs = Dir.glob([".c", "libFooBar/*.c"], base: __dir__)
           .map { |f| File.expand_path(f, __dir__) }
           .map { |f| f.sub(/\.c$/, ".o") }
```

とする。ただし、この回答はkojix2がStackOverFlowの回答を参考に書いてみたらうまくいった方法にすぎない。（フィードバックのため３番目に投稿してある）、うまくいかない場合は書き直してほしい。何が問題で、どうすればよかったのかQiitaやブログの記事にしたり、コメントに書き込んで情報をRubyコミュニティにフィードバックしてググラビリティの改善に貢献してほしいです。

ちなみに、これを指定すると、`#INCFLAGS` と `$VPATH` は特に必要ないようだ。
どうしてそうなるのか仕組みはわからない。

## 追記

ruby-jp のslackに質問をして、C拡張の作成にサブディレクトリの使用はとくに問題ない（非推奨ではない）との回答をいただきました。Rubyの拡張ライブラリは一つのディレクトリにフラットにファイル展開されていることが多いが、別にそのようにしたほうがいいという決まりはないそうです。

この記事は以上です。
【Rails】deviseで複数モデル設定した時の遷移先変更方法【初学者の疑問点を簡潔に解説】

## はじめに
　本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## deviseで複数モデル設定時の遷移先の変更方法

```application_controller.rb
class ApplicationController < ActionController::Base

    # ログイン後のリダイレクト先
    def after_sign_in_path_for(resource_or_scope)
      if resource.is_a?(Admin)
        admin_orders_path
      else
        root_path
      end
    end

    # ログアウト後のリダイレクト先
    def after_sign_out_path_for(resource_or_scope)
      if resource_or_scope == :admin
        new_admin_session_path
      else
        root_path
      end
    end
end

```

または

```application_controller.rb
class ApplicationController < ActionController::Base

 def after_sign_up_path_for(resource)
   case resource
   when Admin
     admin_orders_path
   when EndUser
     root_path
   end
 end

 def after_sign_out_path_for(resource)
    case resource
    when :admin   # ログアウト時はシンボルが返ってくる
      new_admin_session_path
    when :end_user  # ログアウト時はシンボルが返ってくる
      root_path
    end
 end

end
```

## おわりに
詳細な説明については、後日追記する予定です。
Blenderチャレンジ：網目

3DCGソフトウェアのBlenderを使って、お題のモデルを作成してみましょう。
やり方は一通りではないと思います。あなたは、どんな方法を考えますか？

## 問題

下記のような2m×2mの平面状のメッシュを作成してください。なお、頂点数は`６４`です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/445bcd6f-2191-66c4-737e-004d55b6ea2c.jpeg)

[完成物をSketchfabで見る](https://skfb.ly/orXxI)

…
…
…

OK？

---

作成する手順です。

## 解答例1

- `Shift + A`の追加で「メッシュ」→「グリッド」でグリッドを追加します。
- 編集モードに入ります。
- 「辺」メニューの「分割の復元」を選び、詳細設定で下記のように、「反復」を`1`にしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/cdf79e83-9d72-9d85-010f-e9f39da6f867.png)

## 解答例2

- `Shift + A`の追加で「メッシュ」→「グリッド」でグリッドを追加します。
- デシメートモディファイアーを追加し、「分割の復元」にし、「反復」を`1`にし、適用してください。

「分割の復元」は、縦横のメッシュを斜めにするのに、よく使われますね。

以上
【fwywd】初学者が Next.js tailwindcss JavaScript を使用してポートフォリを作成して学んだこと

# はじめに
初めてQiitaへ投稿いたします。

今回、ポートフォリオを作成する機会がありました。作成を通じて、私がつまずいたところ、学んだことをアウトプットしていきます。

同じように苦戦している初学者の方の参考になれば幸いです。

どのようなポートフォリオを作成したかは、こちらのリンク先からご確認ください。
リンク先➣➣[**ポートフォリオ**](https://shinsuke.vercel.app/)

# 導入方法
導入方法すらわからない状況でしたので、こちらの[**リンク先**](https://fwywd.com/tech/next-tailwind)を見ながら導入していきました。
Vs Code を使用していましたら、便利な拡張機能も紹介していましたので、是非ご参考にしてください。

# tailwindcss
css は少し触れたことがあるので、なんとなくは理解していました。それもあり、tailwindcss の使用に関して大きな抵抗はそこまでありませんでした。
もしcss も触ったことが無い方がいきなりtailwindcss で実装すると、使用イメージがあまりつかめないのかな？と思いました。

#### 参考になった資料
参考にした資料のリンク先を以下に記載しておきます。
[TailwindCSS](https://tailwindcss.com/)
[Tailwind CSS Cheat Sheet](https://nerdcave.com/tailwind-cheat-sheet)
[Tailwind CSS おすすめ便利サイト１０選](https://shuu1104.com/2021/04/2746/)

#### 実装していてわかったこと
①「className」にtailwindcssのプロパティを割り当てていけば良いこと
②プロパティは連続して書いてOK
③Vs Code が自動で補完してくれるので、なんとなくプロパティを理解していてもサクサク書ける

```
例）
className='mt-5 py-5 font-bold text-white'
```

上記のコードの意味
「margin-topに5px, padding y方向に5px, フォントは太文字、テキストは白色」

#### 実装していてつまずいたところ
レスポンシブデザインで、以下の部分でつまずきました。

**sm: md: lg: をどのように使用すればいいのかが分からない、法則性を自身で見つけ出すこと**

#### 解決方法
DevToolsを使用して、sm: md: lg: を一つ一つテストし変化点、法則性を見つけていきました。
使い方の記事➣➣[**DevToolsの使い方**](https://willcloud.jp/knowhow/dev-tools-01/)
![スクリーンショット 2021-12-19 4.16.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713046/4f4e32c2-f802-7fee-b372-8209c0e62dce.png)
DevToolsのResponsiveを使用して、画面の大きさを手動で変更していました。

ここで発見できた法則性として、
**「指定したサイズから変更になり、それ以下は適応されない」**
![スクリーンショット 2021-12-19 4.34.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713046/02c69103-923e-bfcc-3e22-eef151f179a5.png)
例として、「sm(640px)」で見ていきます。

```
例）
sm:font-bold
// 640pxからフォントを太文字に変更
```
この場合、640px以上のサイズには反映されますが、**640px未満**（639pxから）のサイズには反映されなくなってしまうことを意味しています。
ここの法則性を発見するのに、とても時間がかかりました。

この法則性から、私の中では**「最小サイズ（スマホ）から作成していくことが効率的」**だと思います。
この部分に関しては、今後Web開発をしていく中で、検証してみたいと思います。

# コンポーネント
概念を理解するのに、最初は戸惑いました。コンポーネントを一言で表現するなら**「分業した仕事をまとめること」**
言葉で表現しても、最初はピンとこなかったので簡易的に図でまとめみました。
![スクリーンショット 2021-12-19 4.59.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713046/ffe3836c-66b3-12fc-2ff7-eda2c85f070d.png)
![スクリーンショット 2021-12-19 4.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713046/dd0ab543-8fae-9ce4-9fa6-2baea015dd2a.png)

言葉は悪いかもしれませんが、仕事しない上司（Index）が仕事を振りまくり、関連部署の部下たちがタスク管理。
各部署が作成した資料を、中間管理職（Layout）がチェックし、上司（Index）へ提出する。
自分の言葉で表現すると、理解度が高まりました。

# 最後に
初学者ですので、誤った理解がある可能性がございます。ございましたら、ご指摘頂けると幸いです。
内容は随時追加、更新していきます。
Google Analytics(GA4)の設定とContent Security Policy(CSP)

<script async src="https://www.googletagmanager.com/gtag/js?id=G-77HMWXY6DY"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-77HMWXY6DY');
</script>

こういう奴のことらしい？（今では`GA`よりも`GA4`が一般らしい）
ちょっとやりたかっただけ

```
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<measurment ID(String)>"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', <measurment ID(String)>);
</script>
```

Webページ上で測定ID付きURLを呼び出してjsを叩くと送信されるのかな…？




# やる前に

なぜだかGoogle Analyticsのページに仕組まれてるインラインスクリプトがCSP設定で弾かれるので（自社製品同士の兼ね合いなんだからデバッグしてくれないものか）

+ 「環境設定」
+ 「プライバシーとセキュリティ」
+ 「安全でないコンテンツ」（1番下にあるはず）
+ `[*.]analytics.google.com`をurlに追加

しておこう，CSPが設定されたページでは危険な関数（eval系など）や許可のないurlから得たjsをブラウザが実行せず，前者のせいで操作不能になる
ちなみに実際にGA4を埋め込むと後者が原因で動かない時があるらしい，はてなブログはMathJaxが動くから流石にセーフだと思うが，自分でCSPを設定できるサイト（`<meta>`タグの中か`http`ヘッダの中に入れるらしい）の場合はGA4に対応するurlを許可しないといけない（ここでは扱わない）




# 導入



## アカウント作成

+ [ここ](https://analytics.google.com/analytics)に行く
+ 「無料で設定」を選択（アカウントがないなら）
+ アカウント名を設定
  + とりあえず自分の名前でいいんじゃない？
  + ⚠︎GA4アカウントとGmailアカウントは別物です！⚠︎
  + 管理者はちゃんと管理しておこう（激うまギャグ）
  + 複数のアカウントが持てるらしいが今のところ必要性を感じない
+ 質問には適当に回答
  + どうせ自分しか見ないならデータ共有の類は全て却下してもよさそう
  + なんなら後からでも設定できるので問題はなし



## プロパティ作成

+ プロパティ名は識別しやすくサービス名を表現する
  + 「HatenaBlog」とかでどう？
+ タイムゾーンと通貨は日本で設定
  + 本当は場所に合わせた方が良い
+ 「ユニバーサル アナリティクス（GA）のプロパティのみを作成する」は今回は却下
  + [ここ](https://help.hatenablog.com/entry/external/google_analytics)曰くはてブロではデフォでGAを埋め込めるらしい
  + まぁプロパティは後から作れるので気になればやり直せば良い
  + GA（昔からある）とGA4（まだ1年も経ってないらしい）では機能が違うらしいが，どうせ改良されるだろ



## ストリーム作成

+ 「管理」→「データストリーム」→「データストリームを追加」
+ ストリームURLに対象ドメインを設定
  + `https://blog.hatena.ne.jp/Soluna_Eureka/soluna-eureka.hatenablog.com`とかになる
+ ストリーム名に識別しやすくページ名を設定
  + 「ChoHoChoDo」（調法調度）にした
+ 拡張機能を全てオンにする
+ すると測定IDが生成される




# 利用

「タグ設定手順」の上のやつを開いてコピーしたら任意のページの`<head></head>`にコピペ<br>
はてブロなら「デザイン」「🔧」「ヘッダ」に入れれば動くはず…

冒頭に挙げたような形式を取っている




# Google Tag Manager(GTM)

これを使うと管理が一気に楽になるらしいのだが，ここでは扱わない（難しそうなので）




# 手元でどう映るか

**俺はお前らが俺を見たのを見たぞ**

![check.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/0b77f9af-02e6-9275-b379-d5aad0921eee.png)

実際ただこれがやりたかっただけなのである！
Python/OpenCVを使った車線推定

# はじめに
こんにちは、HCB Advent Calendar 2021の18日目を担当する、kudokaiです。
卒業研究では車幅感覚習得支援システムの提案という研究をしており、研究の中ではPythonを使った車線推定機能を実装しています。
今回は僕が実装した車線推定について紹介します。

普段はiOSアプリに関する記事を書いたりiOSアプリを開発したりしています。
今回、Pythonの記事は初めて書きます。

# 車線推定方法
### Hough変換
[Hough変換](https://jp.mathworks.com/discovery/image-transform.html)とは画像や動画の中から直線や円を検出するアルゴリズムです。
OpenCVで提供されているHoughLinesP関数を使用する方法が一番簡単なのかなと思います。
Hough変換に至るまで、画像のグレースケール化→2値化をしておく必要があります。

```python
lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/360, threshold=60, minLineLength=10, maxLineGap=20)
```
この1行でHough変換が使えます。
第２引数と第３引数に関しては[ハフ変換による直線検出](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html)をご覧ください。

- ***threshold***   
直線上に乗った線がこの値を超えたら直線とみなします。
- ***minLineLength***   
検出する直線の最小の長さを表します。この値より短い線分は検出されません。
- ***maxLineGap***   
同一線上にある点の間隔の最大値を指定します。指定した値より小さければ、同一の直線とします。

### Haar-Like特徴
[Haar-Like特徴](http://www.ail.cs.gunma-u.ac.jp/ailwiki/index.php?Haar-like%E7%89%B9%E5%BE%B4%E9%87%8F%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%82%AB%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%89%E5%88%86%E9%A1%9E%E5%99%A8%E3%81%AB%E3%82%88%E3%82%8B%E5%89%8D%E6%96%B9%E8%BB%8A%E4%B8%A1%E3%81%AE%E8%AD%98%E5%88%A5)とは、局所領域の明暗差から求めた特徴量のことです。
矩形領域のパターンを設定し、白領域に対応する画素の和と、黒領域に対応する画素の和の差を特徴量とします。
この特徴量は特に顔検出でよく使われます。

矩形領域のパターンは例として以下のようなものを用意します。
![スクリーンショット 2021-12-19 2.56.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425368/338cb07d-7fb0-6056-9ef7-f9a4d1e5fcf6.png)
![スクリーンショット 2021-12-19 2.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425368/366b2251-20e5-699a-cad7-1bfef64bd1ba.png)
より高い精度を出すためには、実際もっと多くのパターンが必要になります。
Haar-Like特徴の詳細は[An efficient lane detection algorithm for lane departure detection](https://ieeexplore.ieee.org/document/6629593)というIEEEの論文に書いてあります。


僕の研究では白線の推定をするだけなので矩形領域のパターンは用意せず、探索領域内における相対的な画素値を用いてHaar-Like特徴を簡略化して実装しています。

## 車線推定結果
Hough変換とHaar-Like特徴を用いてそれぞれの推定結果を動画として書き出しました。
走行動画は僕が通っている大学敷地内で撮影したものを使っています。
### Hough変換
緑の線が白線の候補になります。
車線以外の箇所も多数検出されていますね。
![qiita_hough.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425368/91a6c173-1ca2-5076-c058-cff2176e8671.gif)

### Haar-Like特徴
ピンクの点が車線の候補になります。
緑の枠線が車線の探索領域になります。
いい感じに推定できているかと思います。

しかし、車線逸脱時には縁石を車線を判定してしまうので改良が必要です。
Hough変換と比べても動画の書き出し時間が圧倒的に短くなりました。
![qiita_haar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425368/89d4f202-92b5-b0d0-f09f-35b4157eba70.gif)

# 最後に
提案システム実装の足掛かりとして車線推定の機能を実装しました。
今回は特に具体的なコードは載せずにアルゴリズムの紹介をしてきました。(研究で書いたソースコードって外部に公開してもいいものなのか...)
Hough変換はカーブに対応するのは難しそうですが、Haar-Like特徴であれば相対的な画素値を用いるのでカーブにも対応できそうな気がしています。
Rust変数スコープの終わりについて(ちょこっとC++)

Rustにおいてスコープはブロック({})によって区切られ、ブロックを抜けるとスコープを外れることになっていますが、ブロックを抜けるのは厳密にどのようなタイミングなのか調べてみました。
なお、本内容はあくまでコードに基づいており言語仕様に基づいた内容ではないので正確ではない可能性があることをご了承ください。

# 検証結果
ブロックの最後(})の直前でスコープを外れる。

# 検証プログラム
以下のコードではloopブロック内でX型の変数xを定義しています。X型はdrop演算子を上書きして変数が廃棄されたらコンソールに文字列を表示するようにしています。一見するとプログラムはブロック外である(B)の場所には到達しないため(A)で定義した変数はスコープを抜けないように見えますが……

```rust
use std::thread;
use std::time;
use std::ops;

struct X;

impl ops::Drop for X {
    fn drop(&mut self) {
        println!("drop!");
    }
}

fn main() {
    loop {
        let x:X = X;  // loopブロック内で変数xを定義 ---(A)
        thread::sleep(time::Duration::new(0, 1_000_000_000u32));
    }
    // ここには到達しない ---(B)
}
```

実際に実行すると

```
$ ./target/debug/rustwb
drop!
drop!
drop!
```

と毎回スコープを抜けていることを確認できます。

ちなみに、C++の以下のコードでもループ回るごとに毎回デストラクタが呼ばれているので同じ挙動でした。

```cpp
#include <iostream>

class Class {
public:
	Class() {
		std::cout << "constructor!" << std::endl;
	}
	~Class() {
		std::cout << "destructor!" << std::endl;
	}
};

int main() {
	while (true) {
		Class c;
	}
}
```

毎回コンストラクタが走るので毎回デストラクトされるのは自然な挙動と言えるのかもしれませんが、以上、気になったので調査した結果です。
【Scala】Play FrameworkでJoda-Timeを含むJSONをパース

## 概要
Play Frameworkでは、JSONをパースする`play-json`というライブラリが用意されています。基本的な使い方は、[こちら](https://www.playframework.com/documentation/2.8.x/ScalaJsonCombinators)のドキュメントをご参考ください。
今回はこの`play-json`で、Scalaでよく使われる[Joda-Time](https://www.joda.org/joda-time/)の日付型を、パースしたい場合の対応メモです。

## 対応方法
Joda-Timeをパースするためには、別途[play-json-joda](https://mvnrepository.com/artifact/com.typesafe.play/play-json-joda)というライブラリを使用します。このライブラリを、パースのオブジェクトでインポートしてあげればOKです。

## 実装サンプル
以下がplay-jsonのcombinatorsで実装した、パースのサンプルです。
JodaTimeをパースするために、`DefaultJodaDateTimeReads`と`JodaDateTimeWrites`をimportしています。

```Scala
import org.joda.time.DateTime
import play.api.libs.json.JodaReads.DefaultJodaDateTimeReads
import play.api.libs.json.JodaWrites.JodaDateTimeWrites
import play.api.libs.json._
import play.api.libs.functional.syntax._

object SampleData {

  implicit val sampleDataFormat = (
    (__ \ "_id").format[String] ~
      (__ \ "name").format[String] ~
      (__ \ "register_user_id").format[String] ~
      (__ \ "register_date").format[DateTime] // これがJodaTimeの日付型
    ) (SampleData.apply, unlift(SampleData.unapply))

}

case class SampleData(id: String = "",
                      name: String = "",
                      registerUserId: String = "",
                      registerDate: DateTime = DateTime.now())
```
初めての人に見てもらう

この記事は [驚異のFANZA女優検索](https://fanza-actress-bust-search.azurewebsites.net/) Advent Calendar 2021 の 19 日目の記事です。

# 何度も見ている人が客観的に判断することは難しい
驚異のFANZA女優検索はこんなサービスなので、レビューをしてもらうのも人を選ぶ。自分にも数は少なくとも友人がいることはいるのでレビューしてもらった。その相手にはその後も何度もアドバイスをもらった。ただアドバイスを受けて直してを続けていると、その相手と自分の間だけの共通認識が出来てしまう。なので、2人とも初めて来るユーザーの視点でサイトを評価することが難しくなっていた。

# サービスを始めての人にみてもらう
初めての視点を得るためのもっともよい方法は、このサイトのことを一切知らない別の人を連れてきて、説明なしにさわってもらうことだ。大分煮詰まってきた時にこれをやってみた。その友人には敢えてどういうサービスかを殆ど説明せずにさわってもらった。すると今まで説明をしなくても通じると思っていたことが予想以上に伝わらないことが分かった。そもそもTOPページを見てもこのサイトが何が出来るサイトかピンとこないと言われてしまった。

# 大前提が暗黙知になっていた
今にして思えばレビュー前のサイトは、このサイトの最も売りであるはずのバスト検索できる機能についての説明が何処にも書いていなかった。にも拘わらず、自分も、何度もレビューしてくれた友人も、そこは伝わる前提で考えていた。サイトの売りが2人の間で当たり前になりすぎて説明などなくても通じる前提の思考になっていたのだ。これは非常に危険でかつありがちな話だと思う。

# 情報が全て同じに扱われていた
そこで初めての視点を意識して直していった。先ずサイトを見ると最初からテキストボックスには「100+」と書いてあり、何で検索出来るのか初見ユーザーには分からない作りになっていた。さらにナビゲーションバーに置いてあるものは全て良く分からないと言われた。良く分からないものは、初めての人には認識出来ないものになる。つまり置いてないのと一緒だった。また全ての情報のフォントサイズが一定だったため、とりあえず女優が並んでいるが、何が出来るかはパッと分からないサイトになっていた。特にフォントが同じサイズなのは大きいと思った。

# 重要な情報にプライオリティを付けた
そこで先ず、テキストボックスにはデフォルトを空白にしてさらに何を検索するかの説明を書いた。ナビゲーションは[既に書いた](https://qiita.com/fabsabsfabsabs/items/5a5d0aee0f540784dc72)が、デザイン含めて一新した。最も重要と思っている女優のバスト情報を名前より前に持ってきた。正直名前より先にバストサイズを持ってくるのは結構心理的なハードルもあった。写真、名前、プロフィールの順番がどう考えても一般的だし、むしろその順番以外で書くのはなんというか常識的にあり得ないと思っていた。しかし、実際に持ってくると、印象が変わって見えたし、思ったほど違和感がなかった。

# 重要な情報を大きくしてみた
さらにバスト情報のフォントを大きくした。さらに検索対象のフォントサイズも大きくした。あと画像サイズも大きくした。これでそれほどレイアウトを気にしていない自分にもはっきり分かるレベルでサイトの印象が変わった。それまで自分はフォントサイズを大きくする発想がなかったので、フォントサイズを変えたことは本当に大きかったと思う。今後も場所は選んで使っていきたいテクニックになった。少なくともこのサイトに来た時に何が出来るサービスなのか、売りは分かりやすくなったと思う。

# 初めてのレビューは1人1回しかできない
1度でも初見レビューをやって。このサービスが何をやろうとしてしているかが良く分からないと言われたのは本当に大きかった。ただ、初体験のレビューしてもらった部分を直した場合、その人に再度初体験感を持ってレビューしてもらうことは無理な話だ。やはりまた別の人にレビューをしてもらうしかない。今後さらに進化させた場合にまた別の初見の人にレビューしてもらいたい。ただ、現状、自分にはもうレビューしてもらえる友人のあてはない。ただの旧友には頼みにくいし、さてどうしたものかとは思う。