OmniAICreator/Qiita-1.07M huggingface dataset:
google_recruit

![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 

# お題

<https://qiita.com/daddygongon/items/ba94b0f2a73990fc6a07>

## 解答

```ruby
# frozen_string_literal: true

require './assert_equal'

def prime?(n)
  return true if n == 2

  # ある数 n に対し、初期値 m=1, l=nとして、mを増やしながら、lを減らしながら n =
  # m*l となる(m,l)を探すとき、m=sqrt(n)に到達した以降の(m,l)は、m=sqrt(n) に到
  # 達する以前の(l,m)と同じであるから、探索はm=sqrt(n)で打ちきることができる
  max_i = Math.sqrt(n).to_i + 1

  [*2..max_i].each do |i|
    mod = n % i
    break if mod.zero?
    return true if i == max_i
  end
  false
end

def read_exp
  gets.to_s.chomp
end

def prime_test
  expected = [2, 3, 5, 7]
  results = []

  [*2..10].each do |num|
    results << num if prime?(num)
  end
  assert_equal(expected, results)
end

def read_exp_test
  exp1 = read_exp

  assert_equal(7_182_818_284, exp1[2..2 + 10 - 1].to_i)
end

def main
  exp1 = read_exp

  [*2..exp1.length - 10].each do |i|
    num = exp1[i..i + 10 - 1].to_i
    if prime?(num)
      puts num
      break
    end
  end
end

main if __FILE__ == $PROGRAM_NAME
```

## output

    7427466391

# 類題

Congratulations. You've made it to level 2. Go to www.Linux.org and enter Bobsyouruncle as the login and the answer to this equation as the password.

```
f(1)=7182818284
f(2)=8182845904
f(3)=8747135266
f(4)=7427466391
f(5)=__________
```

ctf っぽい。数列を眺め、試行錯誤してたら法則性を偶然発見した。

```ruby
# frozen_string_literal: true

require './assert_equal'

def read_exp
  gets.to_s.chomp
end

def g_eq?(n)
  sum = 0
  until n.zero?
    sum += n % 10
    n = (n / 10).floor
  end
  sum == 49
end

def main
  exp1 = read_exp

  [*2..exp1.length - 10].each do |i|
    num = exp1[i..i + 10 - 1].to_i
    puts num if g_eq?(num)
  end
end

main if __FILE__ == $PROGRAM_NAME
```

## output

    7182818284
    8182845904
    8747135266
    7427466391
    5966290435
    2952605956

## 余談

Go to www.Linux.org and enter Bobsyouruncle as the login and the answer to thisequation as the password. っていうとおりにlogin を試みたが、失敗した。実は上の回答が間違っているか、もうgoogle\_recruit は時間が経ちすぎていて、無効になっているか&#x2026;多分後者だと思うけど。

------
 - **source** ~/ghq/github.com/TeamNishitani/grad_members_20f/members/syasin-5d/google_recruit.org
私がリカバリ後にインストールするソフト(メモ)

# はじめに

私がリカバリ後にインストールするソフトです．
参考になるものがあれば．


随時更新予定

# windows

以下のソフトをインストールする．


- acrobat reader dc
- adobe acrobat 6.0 standard
- Amazon Games
- adobe photoshop 1.0
    - あらかじめ他のPCからプログラムをサルベージしておくこと [cf](https://igaueno.jyoukamachi.com/photoshop-w10.htm)
- blender
- Brave
- ChatGPT
- DeepL
- Epic Games
- MEGA desktop app
- chrome
- csv to excel
- git bash
- google remote desktop(セットアップも忘れずに行う)
- PowerToys
- Power Automate Desktop
- hotCornerApp
- inkscape
- Line
- Luminar3
- Logi Options+
- Logitech SetPoint
- MacType
- microsoft office
- MyricaM
- NextCloud
- Spotify
- tailscale
- Textify
- visualstudio(latest)
- vlc
- vscode
- GIMP
- WinQuickLook
- WSL2
- 7-zip
- xmediarecode
- xrecode ii
- かざぐるマウス
- QTTab bar
- VOICEBOX
- Vivaldi
- windows terminal
- BthPS3
- EasyReforge
- kensington works



# mac

以下のソフトをインストールする．

- acrobat reader dc
- backup and sync
- BetterTouchTool
- chrome
- deepl
- google remote desktop(セットアップも忘れずに行う)
- Homebrew
- iMovie
- inkscape
- latex環境
- lazygit
- line
- mendeley desktop
- microsoft office
- nodebrew
- skitch
- Spotify
- tailscale
- the unarchiver
- vlc
- vscode
- xcode
- Raycast
- Alt-tab
- Microsoft Cascadia Code font


# linux

以下のソフトをインストールする．

- Easystroke
- google-drive-ocamlfuse
- Guake terminal
- NextCloud
- tailscale
- VS Code
- Microsoft Cascadia Code font
スクラム開発を学習して思ったこと

# はじめに
スクラム開発について体系的に学習を行った。
スクラム開発についてまとめられた記事はたくさんあるので、
ここでは筆者が学習時に印象に残ったことなどをつらつらと書いていきます。

# 参考
最新のスクラム公式ガイド（2020/11/30現在）
https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf

SCRUM BOOT CAMP THE BOOK【増補改訂版】 スクラムチームではじめるアジャイル開発
https://www.amazon.co.jp/SCRUM-BOOT-CAMP-BOOK-E3-80-90-E5-A2-97-E8-A3-9C-E6-94-B9-E8-A8-82-E7-89-88-E3-80-91-E3-82-B9-E3-82/dp/4798163686/ref=dp_ob_title_bk


# スクラム開発とは

アジャイル開発手法の一つであり、スクラムチームという10人以下のチームを組み、スプリントという決められた期間に決められたルールに沿って、プロダクトとチームの改良を行っていく開発フレームワーク


# 実際に勉強してみて思ったこと

## やること自体はとてもシンプル（PDCAサイクルのよう）
実際にスクラム開発を体系的に学んでみると「思ったよりもとてもシンプルだな・・・」という印象を受けました。
一つのスプリントの中で、プロダクトバックログという作業リストの中から実現可能なものをスプリントプランニングにて選定し、デイリースクラムで各作業の状況の確認をし、スプリントレビューにて成果物を確認し、レトロスペクティブにて振り返りを行う・・・やることとしてはこれの繰り返しとなっています。
これは、[PDCAサイクル](https://ja.wikipedia.org/wiki/PDCA%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB)に似ていると感じ、システム開発以外のシーンでも、このスクラムというフレームワークは応用ができそうな印象を受けました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226457/57a17830-153b-6de3-0d00-eaa25e634e49.png)
引用元：https://www.fujitsu.com/jp/group/fst/about/resources/featurestories/about-agile-02.html

## 「柔軟に対応」するための「厳格」なルール
スクラム開発（というかアジャイル開発）のメリットといえば、仕様の変更などに柔軟に対応できる点にあるのですが、スクラム開発自体のルールについては厳格であると感じました。具体的には

- スプリントの期間は1ヶ月以内で決定を行い、決定した期間を延長することはできない（1週間で決めたけど今週だけ２週間で・・・はだめ）

- デイリースクラムは15分で実施し、延長してはならない

- スクラムイベントの省略はできない（今週はレトロスペクティブはやらない・・・はだめ）

などがある。

これらのルールは、一見厳格であると感じましたが、なぜこういったルールが定義されているかを考えると、それは「柔軟に対応」する為であることに気付きます。

例えば仮にスプリントのイベントの中からデイリースクラムをなくした場合、プランニングにて設定したスプリントゴールにむけて順調に進捗しているかが分からず、スプリントレビュー時に「実はこれこれで詰まってしまってできてません」といった状況になりかねません。
きちんとデイリースクラムを行っていれば、作業に詰まってしまっている開発メンバーを検知することができ、協力や対応を行うことができる。そのためにもデイリースクラムは必ず実施する必要があるのです。

また、１週間で決めていたスプリントを「今週のスプリントは1週間じゃ終わらなさそうだから2週間にしようか」という特例を許してしまうと、スプリントのゴールまでの期間が不透明になってしまい、開発リズムの乱れや、咄嗟のリスクへの対応が十分に行えなくなってしまうことにつながります。
上記のことから、「柔軟に対応」することは「厳格」なルールの元で初めて成り立つ物であるのだと感じました。

## 「チームで開発する」が体現されている
スクラム開発での開発チームの特徴として「[自己組織化](https://www.infoq.com/jp/articles/what-are-self-organising-teams/)」があります。これは、開発の進め方をチームで決めて、チームで責任を持って開発を行うことで、チームの主体性向上、およびチームの開発能力の向上を促進することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226457/72200f11-6e03-28dc-6ec0-813e4843df6d.png)
引用元：http://agile.blog.jp/agile_scrum/14970332.html

また、スクラム開発における開発チームは「機能横断的」なチームであるので「自分はフロントエンドエンジニアだからサーバサイドの実装はやらない」などの、肩書や専門分野に囚われなず、どのメンバーも複数のことができることが望まれます。

この「機能横断的」なチームを実現することで、チーム全体のレベルアップ、および、どんな作業でもメンバー全員が責任を持って作業を行うようになると思われるため、先述した「自己組織化」へとつながるのではないかと感じました。

これは、開発以外でも同じことが言えると思います。
私は趣味でアイスホッケーというチームスポーツをやっているのですが、個々の能力は高いが「自分はフォワードだから守備はやらない」や「自分はシュートは苦手だからパスだけ出そう」という思考を持った選手が集まったチームよりも、個々の能力は平均的だが、全員で攻め、全員で守り、苦手なプレーでも状況に応じて実行するチームの方が、好成績を残している印象があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226457/772f0e96-e3f6-03b1-ec29-8f9c5e23069f.png)
引用元：http://shabonyu.com/pyeongchang2018_icehockey/

### まとめ
スクラム開発の学習を通して感じたこととしてまとめると
`「チームが最大のパフォーマンスを発揮し、チーム、プロダクトが成長するための仕組み」`
です。
また、ここで言う「チームの成長」と「プロダクトの成長」はイコールであり、チームが大きく成長すると、同じだけプロダクトも成長すると考えています。

今回は、スクラムマスターやプロダクトオーナーなどのロールや、実務のケースに照らし合わせた事象などについて記載しなかったので、次回以降追記していく。
VSCodeのショートカット，拡張機能などの紹介

# はじめに
VSCodeのためのメモを記します．
ほぼ参考文献の切り抜きみたいなものです．

# ショートカット

`opt.`+`→`　単語毎にカーソル移動する
`opt.`+`↑`　カーソルの行をそのまま上下に移動
`Command` + `D`　1つずつマルチカーソル
`Command` + `Shift` + `L`　一括マルチカーソル

中間クリックで範囲選択　矩形選択

# チートシート
[Keyboard shortcuts for Windows(pdf)](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf)

[Keyboard shortcuts for macOS(pdf)](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf)

[Keyboard shortcuts for Linux(pdf)](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-linux.pdf)



# コマンド
-dオプションでファイルの差分をVS Code上で確認

```sh
$ code -d a.py b.py
```
# 拡張機能
- **Bracket Pair Colorizer2** ペアのカッコを見やすく
- **indent-rainbow** インデントに色をつけて見やすく
- **Markdown Preview Enhanced**　数式がTeX形式で書ける
- **markdownlint**　mdのコードチェック
- **Markdown TOC**　mdに目次を追加
- **テキスト校正くん**　txt, mdの校正


# 参考文献
[VS Codeエディタ入門](https://zenn.dev/karaage0703/books/80b6999d429abc8051bb)
JS でシンプルにバリデーションしたい

最近 [validatorjs](https://github.com/skaterdav85/validatorjs) というバリデーションライブラリを使ったのですが、結構よかったので紹介したいと思います。

## 使い方

### インストール

```bash
$ npm install validatorjs
```

### サンプルコード

```javascript:sample.js
import Validator from 'validatorjs'

// 検証するデータ
const data = {
  name: 'D',
  email: 'not an email address.com'
}

// バリデーションルール
const rules = {
  name: 'size:3',
  email: 'required|email'
}

const validation = new Validator(data, rules)

// 結果
validation.fails() // true
validation.passes() // false

// エラー
validation.errors.get('email') // ['The email format is invalid.']
validation.errors.first('email') // 'The email format is invalid.'
validation.errors.all() // { name: ['The name must be 3 characters.'], email: ['The email format is invalid.']}
```

ルールは配列でも記述できます

```javascript
const rules = {
  name: ['size:3'],
  email: ['required', 'email']
}
```

### エラーメッセージをカスタマイズする

デフォルトでは英語なので、日本語にしたいです

```javascript
Validator.useLang('ja')
```

[Language Support](https://github.com/skaterdav85/validatorjs#language-support)

独自の文言を設定することも可能です

```javascript
const customErrorMessages = {
  required: ':attribute は必須です' // :attribute でフィールド名を参照できます
}

const validation = new Validator(data, rules, customErrorMessages)
```

[Custom Error Messages](https://github.com/skaterdav85/validatorjs#custom-error-messages)

### 使用できるルール

必須チェック、文字数チェック、正規表現、メールなど、よく使うようなものは揃っています
オリジナルのルールが必要な場合はカスタムルールを登録できます

[Available Rules](https://github.com/skaterdav85/validatorjs#available-rules)

### カスタムルールの登録

```javascript
// Validator.register(name, callbackFn, errorMessage)

Validator.register(
  'telephone',
  function(value, requirement, attribute) {
    return value.match(/^\d{3}-\d{3}-\d{4}$/)
  },
  'XXX-XXX-XXXX の形式で入力してください'
)
```

[Register Custom Validation Rules](https://github.com/skaterdav85/validatorjs#register-custom-validation-rules)

## メリット
- ちょこっとバリデーションしたいときに入れやすい
- シンプルなので柔軟性がある

## デメリット
- いろんな処理は自分で書く必要あり
    - バリデーションの実行タイミング
    - エラーの管理　など

## まとめ
普通のフォームだったら Vue.js の場合は [VeeValidator](https://logaretm.github.io/vee-validate/) や [Vuelidate](https://vuelidate.js.org/) を使うほうが楽かなと思います。
エラーの管理とかinput時に自動でバリデーションとかしてくれたと思うので・・・🤔

今回は表のような大量のデータにバリデーションをかけたくて、
UI ライブラリとの相性や体感速度の面でそれらを使えなくて validatorjs を選びました。
エラーの管理などは自分で実装しなければいけませんでしたが、
バリデーションのタイミングを柔軟にできたり、1つのデータが変更されただけなのに処理が重くなる、
みたいなことを避けられたのでよかったです。
C++20便利機能の紹介：文字列チェック三銃士(2/3) starts_with, ends_with

C++20標準ライブラリの文字列クラスでは「先頭／末尾一致を確認するメンバ関数」が追加されます。

* `starts_with`：対象は指定する部分文字列から始まっている？
* `ends_with`：対象は指定する部分文字列で終わっている？

えー、いまさらーとか言わないソコ


# starts_withとends_with

文字列クラス`std::string`と文字列ビュークラス`std::string_view`それぞれに、`starts_with`, `ends_with`メンバ関数が追加されます。[^1]

[^1]: 厳密には文字列クラステンプレート`std::baisc_string<E,T,A>`と文字列ビュークラステンプレート`std::basic_string_view<E,T,A>`に対して、それぞれ3種類のメンバ関数オーバーロード（文字列ビュー, 単一文字, NULL終端文字へのポインタ）が追加されます。

```c++:C++20
#include <string>
#include <string_view>

void download(std::string_view url)
{
  if (url.starts_with("http://") || url.starts_with("https://")) {
    // http(s)スキームを処理...
  } else {
    // ...
  }
}

void process_path(std::string path)
{
  // path末尾が / となるよう正規化
  if (!path.ends_with('/')) {
    path += '/';
  }
  // ...
}
```

※注意：前掲コードでは動作例示のために`std::string`を使いましたが、ファイルパスに関する処理は [`std::filesystem::path`クラス](https://cpprefjp.github.io/reference/filesystem/path.html) の方が適しています。


## Three string checking Musketeers
`starts_with`と`ends_with`は “Three string checking [Musketeers](https://en.wikipedia.org/wiki/The_Three_Musketeers)（文字列チェック三銃士）[^2]” のうちの2関数です。最後の1つ `contains` は、2023年に予定されているC++23標準ライブラリへの追加が決定しています。[^3]

[^2]: "Three string checking Musketeers" という表現は提案文書 [P1679R3](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1679r3.html) より借用しました。このフレーズが気に入ったのでこの記事を書いただけともいう。
[^3]: [Trip report: Autumn ISO C++ standards meeting (virtual) – Sutter’s Mill](https://herbsutter.com/2020/11/13/trip-report-autumn-iso-c-standards-meeting-virtual/) 「I can already hear the chorus of "finally!"」

* `contains`：対象は指定する部分文字列を含んでいる？

3人揃うまであと3年待ってね ☆(ゝω・)vキャピ


## 参考ページ
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r2.html
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1679r3.html
* https://speakerdeck.com/cpp/cedec2020?slide=18
Puppeteer導入手順

# 環境
- Mac
- Node.js v15.3.0
- Npm 7.0.14
- puppeteer 5.5.0

# ■ Puppeteer導入
### 1. [Puppeteerインストール](https://github.com/puppeteer/puppeteer/)
```
npm install puppeteer
```
### 2. 動作確認
- スクリーンショット取得
 
```example.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();
```
```
node example.js
```

- PDF取得

```hn.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
  await page.pdf({path: 'hn.pdf', format: 'A4'});

  await browser.close();
})();
```
```
node hn.js
```

- viewport取得

```get-dimensions.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');

  // Get the "viewport" of the page, as reported by the page.
  const dimensions = await page.evaluate(() => {
    return {
      width: document.documentElement.clientWidth,
      height: document.documentElement.clientHeight,
      deviceScaleFactor: window.devicePixelRatio
    };
  });

  console.log('Dimensions:', dimensions);

  await browser.close();
})();
```

```
node get-dimensions.js
```

# ■ 実行オプション

- ブラウザ表示

```
const browser = await puppeteer.launch({headless: false}); // default is true
```

- Chromiumのバージョン指定

```
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
```
tweet全消し

```python
import tweepy
import os
import json

consumer_key = ''
consumer_secret = ''
access_token = ''
access_token_secret = ''

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)

# アカウントの情報を取得
myinfo = api.me()

with open('tweet.js', encoding='utf-8', mode='r') as f:
    tj = json.load(f)
    for tweet0 in tj:
        tweet = tweet0['tweet']
        print("------------------")
        print(tweet['id'])
        print(tweet['full_text'])
        try:
            api.destroy_status(tweet['id'])
        except Exception as e:
            print(e.args)
```

めっちゃ時間かかる(1万ツイートで1時間とかかな？)けど大体消せました。ツイート数の表示がしばらくバグって、その後ちゃんとしたツイート数になるみたいな挙動をします。理由はよく分かりません
N+1問題についての理解と対処方法

#はじめに
SQLについて学び始めると、最初に取り上げられる問題がN+1問題です。
この問題を解決するだけで、サーバーへの負荷を大きく減らすことができます。

ここでは、

**「N+1問題とは何なのか？」**

また、

**「N+1問題への対処方法とは？」**

ということを解説していきます。

#N+1問題とは？
一言でいうと、**2つのデータベース間のやりとりがデータ総数+1回起こってしまうこと**です。

お買い物をするときに、1つずつお会計を済ます・・・というようなイメージです。
非常に無駄なことをしていますよね。

例を挙げてみましょう。
以下のようなデータベースがあったとします。

###shopsテーブル

|  id  |  name  |
| ---- | ---- |
|  1  |  青木商店  |
|  2  |  やよい商店  |
|  3  |  吉田商店  |

###fruitsテーブル

|  id  |  shop_id  |  name  |
| ---- | ---- | ---- |
|  1  |  1  |  バナナ  |
|  2  |  1  |  りんご  |
|  3  |  2  |  みかん  |
|  5  |  2  |  ぶどう  |
|  6  |  3  |  メロン  |
|  7  |  3  |  なし  |
|  8  |  3  |  すいか  |

例えば、以下のコードをコンソールで実行してみます。

```ruby

# すべてのshopに対し、それぞれのfruitの名前を出力する
Shop.all.each do |sho|
  # fruitsテーブルから名前を取得し、カンマ区切りで結合する
  fruit_names = sho.fruits.pluck(:name).join(",")
  p "#{sho.name}に売っている果物は#{fruit_names}です"
end
```

これに対して、発行されるクエリ文は以下となります。

```sql

  Shop Load (0.8ms)  SELECT "shops".* FROM "shops"
   (0.2ms)  SELECT "fruits"."name" FROM "fruits" WHERE "fruits"."shop_id" = ?  [["shop_id", "1"]]
"青木商店に売っている果物はバナナ,りんごです"
   (0.2ms)  SELECT "fruits"."name" FROM "fruits" WHERE "fruits"."shop_id" = ?  [["shop_id", "2"]]
"やよい商店に売っている果物はみかん,ぶどうです"
   (0.2ms)  SELECT "fruits"."name" FROM "fruits" WHERE "fruits"."shop_id" = ?  [["shop_id", "3"]]
"吉田商店に売っている果物はメロン,なし,すいかです"
```

まずshopsテーブルにアクセスし、そこからfruitsテーブルのデータ数をやりとりします。
今回は1+3=4回で済んでいるのであまり大したことはありません。

しかし、例えばデータ総数が100万個あるとすれば、データを取得するたびに100万1回のやりとりがおこなわれます。
この無駄から生まれるサーバーへの負荷の大きさは、想像に難くないですよね・・・。


#N+1問題への具体的な対処方法
お買い物の例えでいえば、まとめてお会計をするイメージです。
そうすれば、やりとり回数は1（購入）+1（来店）=2回で済むはずです。

先ほどのコード文に、includesを使って書き加えます。

```ruby
Shop.all.includes(:fruits).each do |sho|
  fruit_names = sho.fruits.pluck(:name).join(",")
  p "#{sho.name}に売っている果物は#{fruit_names}です"
end
```

これに対して、発行されるクエリ文は・・・。

```sql
 Shop Load (0.7ms)  SELECT "shops".* FROM "shops"
  Fruit Load (0.7ms)  SELECT "fruits".* FROM "fruits" WHERE "fruits"."shop_id" IN (?, ?, ?)  [["shop_id", "1"], ["shop_id", "2"], ["shop_id", "3"]]
```

先ほどと比べて、スッキリしました！
最初のshopsテーブルへのアクセスは変わりませんが、fruitsテーブルへのアクセスが3回→1回へとまとまりました。
結果として、合計2回のやりとりでデータを取得することができています。

#おわりに
いかがでしたでしょうか。
データベースへのアクセスをいかに効率良くできるか、負担を減らせるかどうかはエンジニアの力の見せ所だと思っています。
上記のように、allメソッドを使うときは、N+1問題のことを思い出しましょう！

#参考
【Ruby on Rails】N+1問題ってなんだ？
https://qiita.com/massaaaaan/items/4eb770f20e636f7a1361
Datomic使ってて嬉しい点/頑張って欲しい点



気がつくと一年が終わりそうという事実に毎年驚愕しています。
今年はアドベントカレンダーに空きがあるようなので、仕事で使い始めてから2年は経過している
Datomicの軽めな話題から投入しようと思いこちらを執筆しました。

## Datomicを使ってて嬉しい点

### datalogが楽しい

初見だとエグい感じの見ためですが、慣れると脳汁ドバドバです。
個人的にはエンティティ間のjoinに頭を使わずに済む点が好きです。

```sql
select user.name, order.id from user inner join order on user.id = order.user_id;
```

```clojure
[:find ?user-name ?order-id
 :where
 [?u :user/name ?user-name]
 [?u :user/id ?user-id]
 [?o :order/user-id ?user-id]
 [?o :order/id ?order-id]]
```

### Presto連携が強い

仕事ではmetabase->Presto->datomicの接続をセットアップしているおかげでダッシュボード的な機能を殆ど実装せずに済んでいます。
metabaseにクエリを足すだけ。

### とある時点でのdb valueに対してクエリを行なうので一貫性を心配することが少ない。

datomicでクエリを行う操作はまずコネクションからdb valueを得るところから始まります。
このdb valueはどの時点かという属性が含まれており、内容が変わらないことが保証されています。
これは例えばとある条件にマッチするレコードの一覧(のページ)とカウントを別々のクエリーで取得してAPIのレスポンスで合体させて返すみたいな処理を実装する時に嬉しいです。

### History api

端的に言うとデータの変更履歴が何もしなくても取得できる、ということです。
伝統的なデータベースを利用していて変更履歴的な機能を実装したい場合、履歴用のスキーマをデータとは別に用意して。。。という流れが選択肢になると思われますが

- 更新の際に履歴として保存するデータに漏れがある
- 履歴の保存を独自で実装することによって発生するバグ

といった問題と争わずに済むのは特にあたりまえにデータの変更履歴機能を求められる現職ではありがたい限りです。

更にdatomicではトランザクション自体もデータなので変更の原因、誰が変更したかといった情報をエンティティの表面に露出させずに済むのも強力です。

## Datomicに頑張って欲しい点

### クエリ結果のorder-byが提供されていない

僕の持っている情報が古い可能性はありますが、SQLで言う所の`order-by ...`に相当する機能が無いためdatomicのapiレベルでソート済みの結果を得る方法が無いため、自前でソートを行なう必要があります。

適切にindexが指定できていれば伝統的なデータベースにおいてもパフォーマンス的な問題にはなりづらい認識[要出典]なので、datomicの方でも実装する気になればできるのでは？という気がしています。

### フレーバーの乱立

プロダクション向けでdatomic-cloud/datomic on-prem,
開発用途でdatomic-pro/dev-local,
deprecateされた物にfree edition,
そしてon-premはコンポーネントの選択肢がdynamo dbだったりsqlデータベースだったりを選べます

こちらはアーキテクチャの自由度とのトレードオフなのでマイナスな感情では無いのですが、
ある機能が自分の利用しているフレーバーで使えないことがしばらくしてから分かったりするので意識する必要があるなぁーという感想です。


といった感じでdatomicは楽しいのでぜひ日本でも広まって欲しいなーという希望を込めて結びとさせていただきます!
permission deniedでgit clone 出来ない問題は、大体SSHがGitHubに登録されていないから

#はじめに
git clone 出来ない問題は、開発メンバーが増えた際なんかによく発生するかと。。。

```console
 git clone git@github.com/---.git
Cloning into '---'...
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
```

大体これは公開鍵がGitHubに登録されていないからですね:sweat:
※公開鍵とは何ぞや？と言う話は置いといて、、、

毎回手順とコマンドを忘れているので、ここに全て記録するとする！

#GitHubにssh接続するためには公開鍵をGitHubに登録する必要がある

##クライアントPC（Mac）に公開鍵と秘密鍵を作成
鍵を作るための階層（ディレクトリ）に移動します

```console
cd ~/.ssh/
```

色々と確認を求められますが、全てenterでOK

大体`Users/user/`の階層にあるかと
![スクリーンショット 2020-12-02 11.41.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/711f9536-4f41-d99c-45c2-c2467d984b2c.png)
.から始まるので**隠しフォルダ**です。
**普通に探しても見れないので注意！**

隠しファイル（フォルダ）の表示方法ですが、
Macなら「command + shift + .」
Windowsなら[こちら](https://www.reneelab.jp/displays-hidden-files.html)を参考に

```console
ssh-keygen -t rsa
```

これで鍵が生成されました。

#鍵を確認

```console
ls ~/.ssh

id_rsa   id_rsa.pub  known_hosts
```

`id_rsa`（秘密鍵）と `id_rsa.pub`（公開鍵）のファイルが作られていればOKです。
今回は`id_rsa.pub`を使います。


##鍵をコピー

```console
pbcopy < ~/.ssh/id_rsa.pub
```

これでssh key（id_rsa.pubというファイル）をコピーできます。

Google翻訳の画面なんかに貼り付けて、控えておきます。

Google翻訳の画面なんかに貼り付けてみると、どんな内容のファイルなのか視覚的にわかると思います。以下のような大量の文字列が確認できるかと。
※**「abcd」の部分は大量の英数字です**

```
ssh-rsa abcd user@gmail.com
```



#GitHubに公開鍵を登録する
![スクリーンショット 2020-12-02 13.40.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/f92dc241-0c01-9d35-1296-36b17d997a1f.png)

「New SSH key」をクリックします。
適当にタイトルをつけて、控えておいたコピーを貼り付けて追加します。

これでプライベートリポジトリを、`git clone`できるようになったかと:smile:
【Panoptic Segmentation】Seamless Scene Segmentation : backboneは共有すべし

<h1>Seamless Scene Segmentation</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/a42f0dda-d839-dabe-64f6-cd0d66693a4d.png)

論文のテーマは[Panoptic Segmentation](https://qiita.com/minh33/items/101153371b9fd4ee6115)の構造に関しての提案である。

<h1>新規性</h1>

<h2>2つのネットワークの提案</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/1f9f5a73-f4b4-9492-6b93-e8e3d67d47e2.png)
Body(backbone)をshareするかしないかの2通り


<h2>結果</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/dcb578ca-ae1e-51a2-a71a-43e916656fdd.png)
Bodyをshareしたほうが精度が高かった。
計算速度も早くなるし、メモリの消費量も小さくなるから一石3鳥

<h1>結論</h1>
当たり前のようだがbackboneをshareしたほうが精度が高くなった。


<h1>参考文献</h1>
Seamless Scene Segmentation
https://arxiv.org/pdf/1905.01220.pdf
Flutter+Firebaseでdynamic link がGoogle Play Storeからのインストールの時のみ動かない件

#公式デバッグやってみると
Android app 'com.memorymate' lacks SHA256. AppLinks is not enabled for the app. 
というワーニングが。
![スクリーンショット 2020-12-02 13.22.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/c1c1b0e3-8ae7-cfb8-9f0d-79660a6f1e68.png)

きっとこれが原因だと思ったので対応する。

#どうやら、Firebaseにsha256証明書というものを提出しなくてはならないらしい。
Firebase コンソールから、アプリの設定画面で「全般」タブの下の方に何やら提出出来そうな場所が。
（画像は提出後）
![スクリーンショット 2020-12-02 13.25.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/a60e4db0-beab-111b-7fb7-850ff589a3fd.png)

#で、この証明書ってどうやって作るの？
https://stackoverflow.com/questions/51845559/generate-sha-1-for-flutter-app
を参考にしたら出来た。

手動でやるやり方はNothing to showとなってしまったが、以下のコマンドをプロジェクトフォルダ直下で叩いたら出た。

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android


![スクリーンショット 2020-12-02 13.29.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/4aec6df1-eb74-35f1-b050-8ab122d25a62.png)

これをさっきの提出場所にコピペすればOK。

（ちなみに、まずSHA1から提出しなきゃダメっぽかった。）
【Swift / 多次元配列】structを型に持った配列をソートする

コロナウイルスの感染状況がWebAPIで公開されていたので、
それに関する実装の時のコードになります。

型の中身はこんな感じ

```Swift
struct Prefecture: Codable {
    var id: Int
    var name_ja: String  //都道府県
    var cases: Int //陽性者数
    var deaths: Int //死者数
    var pcr: Int //PCR検査人数
}
```

たったの3行でソートができる

```Swift
var array:[Prefecture] = []
array.sort(by: { a, b -> Bool in
    return a.cases > b.cases
})
```
aとbは配列の中身の2要素で、それぞれが持つプロパティを
演算、trueかfalseをreturnしてそれに応じてソートしてくれる。
csvを加工してBigQueryにAPPENDする

csvを加工してBigQueryにAppendする方法のメモ。

# 残課題
BigQueryのテーブルで、DATE型の列があるときのpandas.DataFrameからの書き出しが上手くいかない。

# まずはColaboratoryでテスト
Colaboratoryからはうまく動作することを確認

```python:ColaboratoryでBigQueryとGSCへアクセスするための認証
from google.colab import auth
auth.authenticate_user()
project_id = 'xxx'
!gcloud config set project {project_id}
```
```python:BigQueryテーブルの最新データを取得
from google.cloud import bigquery as bq
from google.cloud import storage
dataset = "aaa"
table = "bbb"
 
bq_client = bq.Client(project_id) #初期化
query = "SELECT max(dy_date) as max_date FROM `{0}.{1}.{2}`".format(project_id, dataset, table)
rows = bq_client.query(query).result()
for r in rows:
  max_date = r['max_date']
max_date
```
```python:GCSからcsvを読み込み、pandasで加工
import pandas as pd
import datetime as dt

bucket_name = 'yyy'
file_read   = 'test.csv'
    
s_client = storage.Client(project_id) #初期化
s_bucket = s_client.get_bucket(bucket_name)
blob = storage.Blob(file_read, s_bucket)
data = blob.download_as_string()
df = pd.read_csv(BytesIO(data))

df['date'] = pd.to_datetime(df['date'], format='%Y%m%d') #'date'列を日付型に変更
df = df[df['date'].dt.date >max_date] #BigQueryテーブルの最新日付よりも後の日付のみに絞る
df['date'] = df['date'].dt.date #日付型に変更しておく(Object型になる)
```
```python:pandas.DataframeをBigQueryのテーブルにAPPEND
bq_client = bq.Client(project=project_id) #初期化
table_ref = bq_client.dataset(dataset_name).table(table_name) #BigQueryのテーブルを指定
    
#BigQuery のJobConfigを作成
job_config = bq.job.LoadJobConfig()
job_config.write_disposition = bq.WriteDisposition.WRITE_APPEND
    
#BigQueryのテーブルにデータをAPPEND
load_job = bq_client.load_table_from_dataframe(
    df
    ,table_ref
    ,job_config = job_config
    ,location   = 'US'
    ,project    = project_id
)  # API request
```

#CloudFunctionsで実装
①BigQueryに書き出すためには、pyarrow, fastparquetが必要。pyarrowはバージョンの指定が必要。

```python:main.pyの一部
import pyarrow
import fastparquet
```
```python:reqirment.txt
google-cloud-storage==1.16.1
google-cloud-bigquery==1.15.0
pandas
pyarrow>=0.4
fastparquet
```
②BigQueryに書き出すためには、テーブルの列はすべてNULLABLEでないとならない。

③BigQueryのテーブルDATE型に指定しており、datetime.dateで型を変更したが、型の不一致でうまくいかなかった。
→一度GCSにcsvを出力し、csvからBigQueryへAPPENDする形に変更

```python:DataframeをGCSのcsvに書き出す
s_client = storage.Client(project_id) #初期化
s_bucket = s_client.get_bucket(バケット名)
blob = storage.Blob(ファイル名.csv, s_bucket)
blob.upload_from_string(data=df.to_csv(sep=",", index=False), content_type='text/csv')
```
```python:GCSからBigQueryへAPPEND
bq_client = bq.Client(project=project_id) #初期化
table_ref = bq_client.dataset(dataset_name).table(table_name)
    
#BigQuery のJobConfigを作成
job_config = bq.job.LoadJobConfig()
job_config.write_disposition = bq.WriteDisposition.WRITE_APPEND
job_config.skip_leading_rows = 1
job_config.source_format = bq.SourceFormat.CSV
job_config.allow_jagged_rows = True
job_config.ignore_unknown_values = True
    
#BigQueryのテーブルにデータをAPPEND
load_job = bq_client.load_table_from_uri(
    uri_out  # uri_out = 'gs://バケット名/ファイル名.csv
    ,table_ref
    ,job_config = job_config
    ,location   = 'US'
    ,project    = project_id
)  # API request
```
asp.net VisualStudio でデバッグしようとしたら「リソースが見つかりませんでした。」になる

## 問題
asp.net で開発中に、VisualStudio でページをデバッグしようとすると 
ブラウザに下記のような画面が表示されて 
開発中のページが表示されないことがありました。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311258/5a5ccaa0-e505-aaef-4031-e0e306a66875.png)

## 解決方法
`プロジェクト` → `プロパティ` → `Web` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311258/3e8a67b1-8017-2464-ee67-e3c5c55c27b8.png)

`プロジェクトのURL (J)` のポート番号を**ほかのプロジェクトと重複しないよう**にして `仮想ディレクトリの作成`ボタンをクリックします。


## 原因
asp.net のプロジェクトをコピペして作り直したか、別ソリューションで作成した asp.net をソリューションに追加したのかもしれません。
vim-sandwich をデフォルト以外のキーマップで使う（surround.vimに合わせたキーマップにする）

[machakann/vim\-sandwich](https://github.com/machakann/vim-sandwich) は便利ですが、デフォルトのキーマップが `s` なのはいただけません。
そういうわけで、[tpope/vim\-surround](https://github.com/tpope/vim-surround) に合わせたキーマップに置き換えます。

## デフォルトキーマップの無効化
**ハマりポイント1**:
デフォルトキーマップを無効化するための変数は3つ用意されていて、とりあえず今回のケースでは2つの変数を設定しなければいけません。

```vim
  let g:sandwich_no_default_key_mappings = 1
  let g:operator_sandwich_no_default_key_mappings = 1
```

はじめ `g:sandwich_no_default_key_mappings` だけしか設定せずに「オイ全然無効化しねェぞ！どうなってんだァコレェ！！」って使用を中断したクチです。

ちなみにこのプラグインには [osyo\-manga/vim\-textobj\-multiblock](https://github.com/osyo-manga/vim-textobj-multiblock) に似た機能[^multiblock] も提供していて、そのデフォルトマップを無効にするには `g:textobj_sandwich_no_default_key_mappings` も設定しないといけません。

## vim-surroundライクなキーマップの設定

### 囲いを追加(vim-sandwich のデフォルト `sa`) のリマップ
`ys`{motion/textobject}{addition}

vim-surround のヘルプドキュメントに載っている記憶法:

> "ys" is "you surround".

たとえばある単語を丸括弧で囲むなら、`ysiw(`。

```vim
nmap ys <Plug>(operator-sandwich-add)
```

### 囲いの削除(デフォルト`sd`) と 囲いの置き換え(デフォルト`sr`) のリマップ
`ds` と `cs` へ

**ハマりポイント2**:
単純に `<Plug>(operator-sandwich-delete)` `<Plug>(operator-sandwich-replace)` にキーマップするのではなく、以下のような複雑で意味不明なマップにしないと動いてくれません[^x]。

```vim
nmap <silent>ds <Plug>(operator-sandwich-delete)<Plug>(operator-sandwich-release-count)<Plug>(textobj-sandwich-query-a)
nmap <silent>cs <Plug>(operator-sandwich-replace)<Plug>(operator-sandwich-release-count)<Plug>(textobj-sandwich-query-a)
```

と、このように使用までに（デフォルトキーマップを使用したくないのなら）罠があって挫折させられてしまいますが、使い始めると括弧・クォート関係のタイプ量が大幅に減って手放せないプラグインになります。
tpope/vim-surround より副作用もなくわかりやすい効果エフェクトもついてるのでその上位互換と言えるでしょう。

[^multiblock]: 括弧やクォートをすべてomap `ib` や `ab` でテキストオブジェクトとして選択する機能
[^x]: リピータブルにしたりカウントに対応するために色々やっているのだろう。plugin/sandwich.vim からの引用。
for文のloop変数にdoubleを使ったらダメの勘違い(+=1.0は問題無いよ)

数値計算の教科書などにfor文のloop変数に浮動小数点型のdoubleやfloatを使ったらダメという記述がみられます。整数型を使いなさいという記述があります。

以下は数値計算に関するサイトではありませんが、

> https://www.jpcert.or.jp/java-rules/num09-j.html
> NUM09-J. 浮動小数点数型変数をループカウンタとして使用しない

上記に

> 浮動小数点数型変数をループカウンタとして使用してはならない。精度に限界のある IEEE 754 浮動小数点数型は、次に示すように、すべての値を表現できるわけではない。

とあります。確かに正しい記述です。

実際以下のコードでは正しくループ回数がカウントされません。一回余計に実行されます。(OS:CentOS7.9, CPU: AMD64, gcc-4.8.5で確認)

```double_loop.c
#include <stdio.h>

int
main ()
{
  double i;
  long int count = 0;
  for (i = 0.0; i < 1000000.0; i += 0.1)
    {
      count++;
    }
  printf ("ループ回数 = %ld\n", count);
  return 0;
}
```

```
$ gcc double_loop.c
$ ./a.out
ループ回数 = 10000001
```

というように回数が正しくなくなります。これは10進数0.1が2進数では循環小数となるからです。

```
10進数: 0.1
2進数: 0 . 000110011..(循環小数)
```

循環小数になるため、丸め誤差により+=0.1の足し算が正しくおこなわれないため、ループ回数が正しく実行されません。

この問題は循環小数になるからダメなだけです。この点注意していただきたい。この点を忘れている人が時々います。

10進数の整数は2進数で有限桁数で正確に表現できます。double型の仮数部の有効桁数内なら正確に2進数で表現できます。

なのでこんな感じに小数0.1を足す処理を整数1を足す処理に置き換えればfor文で正しくループが実行されます。

```double_loop2.c
#include <stdio.h>

int
main ()
{
  double i;
  long int count = 0;
  for (i = 0.0; i < 1000000.0 * 10; i += 1.0)
    {
      count++;
    }
  printf ("ループ回数 = %ld\n", count);
  return 0;
}
```

```
$ gcc double_loop2.c
$ ./a.out
ループ回数 = 10000000
```

ですので、

#整数演算ならfor文のloop変数にdoubleを使っても丸め誤差は起きません

C言語の浮動小数点の実装は処理系依存なのですが、IEEE754に準じた処理系の場合は仮数部は52bitでケチ表現を使っているため、

0から2^53-1までの整数は正確に計算できます。

Ref: https://ja.wikipedia.org/wiki/%E5%80%8D%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0

なので、loop変数に対して整数演算しか行わない場合はなんら問題ありません。但し除算を除く。

#除算は例外
除算を行う場合は、計算結果が小数になった場合、整数演算なら切り捨てになりますが、浮動小数点演算の場合は切り捨てにならず小数になりますので、扱いが異なります。

なのでfor文で除算を使う場合は除きます。加減乗算については結果が同じです。

繰り返しますが、仮数部の有効桁数を超えない場合のみです。

#なぜ浮動小数点型のみやり玉に挙げられるのか?
整数の場合であってもint型で加算や乗算で2^31-1を超えた場合、正しい演算が行われません。何故浮動小数点のみやり玉にあげられるのは腑に落ちません。

#とは言え
doubleをloop変数にするのはお勧めはしませんが(^_^;

#最後に
偉い方からお叱りを受けそうな記事ですが、声を大にして言いたい。

十分理解して書いてるコードなのに、よく見もせずにfor文でdoubleを使ってるコードは間違いであると断言しないで頂きたい。

#追記(12/25)
コメントを頂いてますが、double_loop.cのコードのループ回数が１回多くなってしまうのは丸め誤差の影響に加えて、情報落ちの影響が大きいようです。

学問が浅い人間が思い付きで書くとよくありません。ご指摘ありがとうございました。

参考文献を挙げておきます。私がdobuleを使うとループ回数が正しくない事が起きるという話を学習したは次の書籍になります。少々古い本ですが、今でも役に立つと思います。

> 数値計算の常識 
> https://www.amazon.co.jp/dp/4320013433/

現在でも刊行されてるんですね。ちょっと驚き。また有名な書籍ですので、理系の大学図書館とか置いてあることが多いと思います。
Vuetify v-iconが表示されない

# v-iconだけが表示されない

Vuetifyは正しくインストールできて `v-icon` 以外は表示されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530205/3357e3c6-a0e2-40b1-db36-e351ee7170bb.png)

各種ライブラリのインポートはmain.jsで行っています

```main.js
import Vue from 'vue'
import Vuex from 'vuex'
import Vuetify from "vuetify";
import "vuetify/dist/vuetify.min.css";

import App from './App.vue'

Vue.config.productionTip = false
Vue.use(Vuex)
Vue.use(Vuetify)

new Vue({
  vuetify: new Vuetify(),
  render: h => h(App),
}).$mount('#app')
```

鉛筆アイコンボタンのコード

```Edit.vue
<template>
  <v-btn icon>
    <v-icon>mdi-lead-pencil</v-icon>
  </v-btn>
</template>

<script>
export default {
  name: "Edit"
}
</script>

<style scoped>

</style>
```

ハートアイコンボタンのコード

```Like.vue
<template>
  <v-btn icon>
    <v-icon>mdi-heart</v-icon>
  </v-btn>
</template>

<script>
export default {
  name: "Like"
}
</script>

<style scoped>

</style>
```
[Vuetifyリファレンス](https://v2.vuetifyjs.com/ja/components/icons/)の記載は `<v-icon>mdi-heart</v-icon>` と書けばアイコンが表示されるように見える…

# これで解決しました！

### @mdi/font をインストール

マテリアルデザインアイコンのライブラリをインストール

```
npm install --save @mdi/font
```

### main.js に @mdi/font インポートを記述

```main.js
import Vue from 'vue'
import Vuex from 'vuex'
import Vuetify from "vuetify";
import "vuetify/dist/vuetify.min.css";
import '@mdi/font/css/materialdesignicons.css' // この行を追加

import App from './App.vue'

Vue.config.productionTip = false
Vue.use(Vuex)
Vue.use(Vuetify)

new Vue({
  vuetify: new Vuetify(),
  render: h => h(App),
}).$mount('#app')
```

これで `v-icon` が表示されるようになりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530205/d694bfed-d2f9-460f-302c-28f9dc47de97.png)
manコマンドの日本語化

## ロケールを確認

- ロケールの確認

`locale` コマンドを使用
一番上が `LANG=ja_JP.UTF-8` となっていたらOK

```
locale
==========
LANG=ja_JP.UTF-8
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
==========
```

- ロケールの変更(CentOS7)

一番上が `LANG=ja_JP.UTF-8` となっていない場合は以下でロケールを変更する

```
localectl set-locale LANG=ja_JP.utf8
localectl status
==========
   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: jp
      X11 Layout: jp
==========
source /etc/locale.conf
```

## 日本語のmanコマンドページ集のインストール

- `man-pages-ja` をインストール

```
yum install man-pages-ja
==========
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.iij.ad.jp
 * extras: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ man-pages-ja.noarch 0:20130615-6.el7 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

========================================================================================================================================================================
 Package                                    アーキテクチャー                     バージョン                                    リポジトリー                        容量
========================================================================================================================================================================
インストール中:
 man-pages-ja                               noarch                               20130615-6.el7                                base                               5.4 M

トランザクションの要約
========================================================================================================================================================================
インストール  1 パッケージ

総ダウンロード容量: 5.4 M
インストール容量: 5.2 M
Is this ok [y/d/N]: y
Downloading packages:
man-pages-ja-20130615-6.el7.noarch.rpm                                                                                                           | 5.4 MB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : man-pages-ja-20130615-6.el7.noarch                                                                                                      1/1 
  検証中                  : man-pages-ja-20130615-6.el7.noarch                                                                                                      1/1 

インストール:
  man-pages-ja.noarch 0:20130615-6.el7                                                                                                                                  

完了しました!
==========
```

- man コマンド叩いてみる

```
man cron
==========
CRON(8)                                                               System Manager's Manual                                                               CRON(8)

名前
       cron - 予定されたコマンドを実行するデーモン(Vixie Cron)

書式
       cron

説明
       cron は /etc/rc または /etc/rc.local から起動されるべきである。 すぐに(シェルに)戻るので、'&' を付けて起動する必要はない。
.....
==========
```
Azure Monitor を使用して仮想マシンを監視

この記事は「[NEXTSCAPE Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nextscape)」の2日目です。

2年程前に、AzureのIaaS監視周りをまとめた記事を書かせていただきましたが、 あれからAzure Monitor for VMs というサービスが新たにできていますので紹介したいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/fe067d01-5f5f-3de2-b508-22b888e77673.png)

##Azure Monitor for VMsとは
ざっくり言うと、仮想マシンをAzure Monitor ログ(LogAnalytics)にデータを流し、
ポータル上でパフォーマンス等の情報を可視化し、分析しやすくなったサービス。
LogAnalyticsワークスペースでパフォーマンスカウンターを設定してた今までのものとは別であり、ログは別テーブルで管理されています。

##設定してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/ca2cca4f-20af-99d5-38b4-0589c4e67d11.png)
モニター > 仮想マシン　から　任意の仮想マシンの「有効にする」ボタンをポチり。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/c80ce5a1-dd5a-ec21-d9b3-61ee6d865de6.png)
サブスクリプションとLogAnalyticsワークスペースを選択して「有効」を押すだけです。
数分でデプロイ完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/21d678d2-12b5-d469-db00-3d68025ba389.png)
「パフォーマンス」や「マップ」が表示されるようになりました。
グラフはピン止めがあるので、ダッシュボードへの貼り付けが可能ですね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/3ba196f8-e36b-bbf8-c618-f16b042bbef8.png)
障害時の問題の切り分け時に活躍しそうですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/83c0c538-bcd1-6a97-53d4-49dbaf92c3b0.png)
有効にした事で、仮想マシンの拡張機能に
Azure Monitor for VMsのマップ機能を提供する為の「DependencyAgentWindows」
Windows用のLog Analytics(AzureMonitor)エージェントである「MicrosoftMonitoringAgent」
がインストールされている事が確認できます。

##ゲストOSの正常性(プレビュー)機能について
仮想マシンやLogAnalyticsのリージョンが対応済みで
システム割り当てのマネージドIDやWorkloadMonitorのプロバイダ登録していれば、利用可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/a865a9c8-6f2d-d5f8-247d-c360903f906a.png)
分析情報 > 正常性(プレビュー) > 有効化 > 「アップグレード」ボタンを押すだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/3aea996b-94db-642b-4047-846f09d6a247.png)
CPU使用率、ディスクの空き容量、メモリの正常性が表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/98eeffa1-230c-6077-9642-2edba47ed373.png)
「構成」では、正常性状態のロジックが設定可能です。アラートは、分析情報として表示のものになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552307/3cfc595a-6d97-dbef-a5ab-bf8f7b162d4c.png)
LogAnalyticsにAzure Monitor for VMsのログが出ているので、
閾値を超えた場合にメール通知などを行う場合は、今まで通りLogAnalyticsのクエリからアラートルールを設定すれば良いかと思います。

##まとめ
LogAnalyticsワークスペースで仮想マシンのパフォーマンスカウンターを設定してた時よりも、Azure Monitor for VMsの場合は、とても設定が簡単になっています。
また、LogAnalyticsにログを流しているので、今までと同様にアラート設定も可能です。

今後、新たにログを設定するのであれば、Azure Monitor for VMsを検討してもいいかもしれません。
また、LogAnalyticsの課金のみなので、すでにLogAnalyticsを使用しているのであれば、まずは有効にしてみたりと試しやすいですね。

■NEXTSCAPE Advent Calendar 2020
アドベントカレンダーについては[コチラ](https://qiita.com/advent-calendar/2020/nextscape)
Dockerをついに使ってみる:インストール編

いよいよ、Dockerとなるものを使ってみるときがきた…
最近は初学者がポートフォリオとかで組み込んだりしていて、名前しか聞いたことがない
なので、色々調べてみる

##Dockerとは
開発者やシステム管理者が(リナックス)コンテナを利用して
開発・デプロイ・アプリケーションの実行を行えるようにするプラットフォーム

###コンテナとは
プロセスの実行空間を隔離するための技術

##Dockerを使用するメリット
アプリケーションは、本番環境に近い環境をPC上に作るのが好ましいとされている

アプリケーションを実行するための環境構築に使用することができますが
仮想化の仕組みの違いによってDockerの方が、
起動スピードがかなり速いという特徴がある

またAWAやGoogle Cloud Platform などの
クラウドサービスにコンテナを実行するためのサービスが用意
されているため、アプリケーションの公開も容易になってきている



###本番環境とは
実際にアプリケーションを公開する際に、動作させる環境のこと

####なぜ本番環境に近い環境がいいか
動作している環境が違うと開発の時に動いていても、
サーバー上で実行したときの環境の差で
動作しないといったことが起こる可能性があるため

一般的に開発環境と本番環境と、アプリケーション実行環境
はなるべく合わせるのがいい

##インストール方法
https://www.docker.com にアクセス
[for mac](https://www.docker.com/get-started) からインストーラーをダウンロード

##アプリ立ち上げる
アプリ立ち上げてみる

```
docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world

Hello from Docker!
```
何をしているかというと…
`Docker Hub`からHello Worldというメッセージを表示するための
`イメージをダウンロードしてコンテナが実行されている`

`Hello from Docker!`とでていたらOK
度重なる移行を経た基幹DBでORA-01435エラーに困った話

お仕事ではOracleDBに触れることが多いです。基幹データベースはOracleDBで構築されており、度重なる移行を経ており、、私が知っているだけでもすでに4世代目の基盤上で動いています。

今回はそのデータベースを、オンプレに配備されているOracleDBからOCI（Oracle Cloud Infrastructure）に構築されたOracleDBに移行する作業中に見つかった問題。現時点でも根本原因は不明だが回避策はわかったものです。

# 前提

* 移行元・移行先はOracle Database 12c R1。ただし移行元は数年前までは11g、そのまた数年前までは…という具合にバージョンアップ＆移行を繰り返してきました。
* 移行元も移行先も、複数のOracleDBインスタンス（正確に言うと、移行先ではインスタンスではなく同一CDB上の複数のPDB）が存在。
* インスタンス同士はDBLINKにより接続されており、片方のインスタンスからもう片方のインスタンスのオブジェクトが参照可能な状態。
* インスタンスAのテーブルはインスタンスBからDBLINKを通じてアクセス可能。
* インスタンスBには多数のMV（マテリアライズドビュー）が存在。
* それらMVの定義内のクエリでインスタンスAのテーブルを参照するものが多数存在。
* 移行元のOracleDBインスタンスでは、検証環境のシステム群（DBのユーザー）の洗い替え（trunkからbranchへの逆マージ）の都度、Masterの役割を持つスキーマをエクスポートし、別名でインポートすることでDBオブジェクトとレコードの洗い替えをする運用が長年行われてきた。
* 移行はDBLINK経由で移行元DBインスタンスを移行先PDBとしてクローンするという手法で実施。
* 移行元インスタンスに存在したユーザースキーマで、移行先PDBでは不要となるユーザースキーマは、クローン後にdrop。

# 事象

移行先のOracleDBのPDB B（移行元のインスタンスBに相当）側でMVリフレッシュを行ったところ、以下のようなエラーが発生。

```
行１でエラーが発生しました。:
ORA-01435: ユーザーが存在しません。
ORA-06512: "SYS.DBMS_SNAPSHOT_UTL", 行364
ORA-06512: "SYS.DBMS_SNAPSHOT_UTL", 行446
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2821
ORA-06512: "SYS.DBMS_SNAPSHOT", 行3058
ORA-06512: "SYS.DBMS_SNAPSHOT", 行3017
ORA-06512: 行1
```

MVの定義情報を引き出して確認すると、このMVの定義で用いされているDBLINKには問題なし。DBLINK定義時に指定される認証情報は正しく、DBLINKにより参照されるユーザースキーマとそのオブジェクトも健在。手でクエリを実行すれば参照は可能。

# 原因

不明。
ただおそらく「前提」で述べた移行元DBにおける洗い替えの運用により、データディクショナリのデータ不整合が生じている模様。

# 回避策

1. PDB B側で、dba_snapshotsテーブルを参照。
1. dba_snapshots.master_ownerカラムの内容がMVの定義情報（のクエリに含まれるDBLINK経由の参照先）と不一致になっているものを抽出。
1. 「前提」でも述べた「不要なユーザースキーマ」としてdropしていたものに該当していたので、このスキーマをPDB A（インスタンスAに相当）に新規作成、さらにそのスキーマ内にMVから参照されるのと同名のテーブルを新規作成。
1. この状態でMVリフレッシュをトライしたところ成功。

なお、この新規作成するテーブルは名前の一致だけが重要で、カラムや制約、索引などはでたらめで問題ない。。
Shopifyの日本語化対応されていない海外テーマを日本語化する方法

# 目的 
- 今後、Shopifyを学ぶ方に向けての参考に役立てる。

# 前提条件
- 日本語化されていない海外テーマを使用している
- ローカル開発環境でテーマをカスタマイズしている

```
# 私の場合、こんな感じで英語の翻訳ファイルがありました

├── locales
│   └── en.default.json
```

# 手順
## 1. shopify管理画面からテーマの言語編集画面へ遷移する

#### 「テーマ」 ＞ 「言語を編集する」
[![Image from Gyazo](https://i.gyazo.com/1f4c90550c74a2b9ae609c3c41e37d6b.png)](https://gyazo.com/1f4c90550c74a2b9ae609c3c41e37d6b)
↓
[![Image from Gyazo](https://i.gyazo.com/b352106b87eb6981657447a76c12db8a.png)](https://gyazo.com/b352106b87eb6981657447a76c12db8a)

## 2. テーマの言語を日本語に変更する

[![Image from Gyazo](https://i.gyazo.com/66f1a29ee065331808f8ff9660e42a44.png)](https://gyazo.com/66f1a29ee065331808f8ff9660e42a44)
↓
[![Image from Gyazo](https://i.gyazo.com/4d6a77dc9ddb94bc58f8eac593f81e9d.png)](https://gyazo.com/4d6a77dc9ddb94bc58f8eac593f81e9d)
↓
[![Image from Gyazo](https://i.gyazo.com/53fb5ea73251b8a3f3b87acef2fa34e3.png)](https://gyazo.com/53fb5ea73251b8a3f3b87acef2fa34e3)
↓
[![Image from Gyazo](https://i.gyazo.com/b815fae8298445543fa6a7464078d2c3.png)](https://gyazo.com/b815fae8298445543fa6a7464078d2c3)

#### 言語変更後

[![Image from Gyazo](https://i.gyazo.com/440225ac41c9b41783bc5c88f3f5e896.png)](https://gyazo.com/440225ac41c9b41783bc5c88f3f5e896)


## 3. 日本語の翻訳ファイルを作成する

├── locales
│   ├── en.default.json
│   └── ja.json ←このファイルを作成

#### ※最初「en.default.json」をコピペして「ja.default.json」で作成したら反映されなかった💦

## 4. 「ja.json」を編集する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118229/d9432329-c00c-5d76-c91a-d0ac05e46e02.png)

#### 変更後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118229/1d3e7bb5-465d-3878-fd05-4300dcf11ece.png)




# 関連URL

[How To Use Translation Keys To Create Internationalized Themes](https://www.shopify.com/partners/blog/translation-keys)
assert_equal



# assert\_equal

assert equalとはequalかどうかを確かめる(assert)関数

まずは簡単に1==1を試してみる．

assert\_equal.rb に書き込んでいく

```ruby
p 1==1
```

    > ruby assert_equal.rb
    true

と返ってくる

次はこれをmethodにする

```ruby
def assert_equal(expected, result)
  return expected == result
end

p assert_equal(1, 1)
```

    > ruby assert_equal.rb
    true

と返ってくる．


# colorizeで色をつける

まず

    > gem install colorize

で install する

それから先程のコードの先頭に require 'colorize' を加え, 下記のように書きかえる

```ruby
require 'colorize'

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

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

このプログラムを実行すると true が green に false が red になっている.

色は green, red 以外にも black, light\_black, light\_red, light\_green, light\_yellow, light\_blue, magenta, light\_magenta, cyan, light\_cyan, white, light\_whiteがある


# richer output

出力を少しわかりやすくする．

-   引数の expected, resultの値をそのまま出力
-   そして以下のように出力するようにする
    -   true の時は "succeeded in assert\_equal"
    -   false の時は "failed in assert\_equal"

```ruby
require 'colorize'

def assert_equal(expected, result)
  p ['expected', expected]
  p ['result', result]
  if expected == result
    puts 'succeeded in assert_equal'.green
  else
    puts 'failed in assert_equal'.red 
  end
end

if $PROGRAM_NAME  == __FILE__
  assert_equal(1, 1)
  assert_equal(1, 2)
end
```

    > ruby assert_equal_richer_output.rb
    [expected, 1]
    [result, 1]
    succeeded in assert_equal
    [expected, 1]
    [result, 2]
    failed in assert_equal

と出力される.


# 拡張:assert\_not\_equal

関数 assert\_not\_equal を加える.

その後, 重複箇所の整理と重複実行の予防を考慮したコードが以下の通りである.

```ruby
require 'colorize'

def puts_vals(expected, result)
  puts "expected :: #{expected}"
  puts "result   :: #{result}"
end

def assert_not_equal(expected, result)
  puts_vals(expected, result)
  print expected != result ?
	  "succeeded in #{__method__}.\n".cyan :
	  "failed in #{__method__}.\n".magenta
end

def assert_equal(expected, result)
  puts_vals(expected, result)
  print case expected == result
		 when true ; "succeeded in #{__method__}.\n".cyan
		 when false ; "failed in #{__method__}.\n".magenta
		 end
end


if $PROGRAM_NAME == __FILE__
  assert_equal(1, 1)
  assert_equal(1, 2)
  assert_not_equal(1, 2)
  assert_not_equal(1, 1)
end
```

上のコードの

```ruby
if $PROGRAM_NAME == __FILE__
  assert_equal(1, 1)
  assert_equal(1, 2)
  assert_not_equal(1, 2)
  assert_not_equal(1, 1)
end
```

の意味は，codeが書いてあるファイル名(FILE)が，動いているファイル名($PROGRAM\_NAME)と一致したら中身を実行である．これはidiom (熟語) である.


# 参考ページ

[チャート式ruby-IV(assert\_equal)](https://qiita.com/daddygongon/items/f6cea87314ee26e130ea)



------
 - **source** ~/grad_members_20f/members/djj31370/c4_assert_equal.org
師走にSubversionの外部項目をお掃除した話

お仕事で、構成管理にあたっているチームの方からSubversionの「外部項目」について相談をうけて対応したときのお話の紹介です。

# 外部項目とは？

私がお仕事で関わっているSubversionリポジトリでは、わずかではありますが、「外部項目」（externals）の機能を利用しています。

外部項目は、Subversionリポジトリの任意のパスに配置できる一種の「ショートカット」で、同一ないし別のSubversionリポジトリのパスを参照することを可能にする機能です。

外部項目を含むディレクトリをチェックアウトすれば、外部項目が参照するパスのファイルもいっしょにチェックアウトされます。

同一リポジトリであれば、外部項目によりチェックアウトされた項目に対する変更は、参照先のパスに反映されます。

このように便利な機能ですが、Subversionで管理されるファイルセットに単なるツリー構造以上の構造（関係性）を導入することになるため、挙動の理解や管理作業が少し複雑になります。

# 相談内容

構成管理にあたっているチームから相談を受けた内容はおおよそ以下の通り：

* 運用ルールの変更に伴いSubversionリポジトリ内のとあるディレクトリ（A）を削除した
* 当該ディレクトリ（A）は同一リポジトリの別ディレクトリ（B）に含まれる外部項目により参照されていた
* 後者のディレクトリ（B）をチェックアウトしたり更新したりするとエラーが発生するようになってしまった
* 一旦参照先のディレクトリ（A）を復元するとエラーはなくなった
* Subversionの作業コピーやリポジトリブラウザー上で外部項目に対して「削除」を行うと参照先は削除されるが外部項目は残る
* この状態でディレクトリ（B）をチェックアウトしたり更新したりするとエラーが発生する

→エラー発生させることなく外部項目を削除したい。

# 作業内容

この相談を受けて私が行った作業はおおよそ以下の通り：

①外部項目の含まれるディレクトリを手元にチェックアウト
②コマンドプロンプトを起動
③先程チェックアウトした作業コピーディレクトリにカレントディレクトリを移動
④ `svn proplist -v` で外部項目の存在を確認（ある）
出力例：

```
Properties on '.':
  svn:externals

(参照先パス) (外部項目名)
```

⑤ `svn propdel svn:externals .` で外部項目の削除を実施
出力例：

```
property 'svn:externals' deleted from '.'.
```

⑥ `svn proplist -v` で外部項目の存在を確認（ない）
⑦外部項目のディレクトリは（ファイルシステム上は）そのまま残るので `rmdir /S /Q (外部項目フォルダ名)` で削除
⑧作業コピーにおける変更をSVNコミット

外部項目は、作業コピーの置かれたファイルシステムのディレクトリ（フォルダ）としての実体と、Subversionが管理する親ディレクトリ（前述「相談内容」でいえばBの方）のプロパティとしての実体と、2つの実体を持っています。

今回の作業で肝となるのは後者、プロパティの削除です。削除しなくてはならないプロパティは、外部項目を表すディレクトリそのものではなく、その親ディレクトリであるという点も少しわかりにくく感じるところですね。

以上、分かれば大したことはないのですが、分かるまでに少し四苦八苦するお話でした。