OmniAICreator/Qiita-1.07M huggingface dataset:
BastilleBSDを試してみた

13.0-RELEASE/amd64でjailの管理ツールの[BastilleBSD](https://bastillebsd.org/)を試してみました。

jailは一つのホストの中に複数のホストがあるように見せかける技術です。FreeBSDなんかより以前の太古の時代に作られたchrootを使った仕組みです。FreeBSDでは古くからある技術で最近はコンテナと呼ばれることもあるようです。

FreeBSDにはbhyveと呼ばれるハイパーバイザーがあり、OSの完全分離が可能ですが、jailより多くの資源を必要とするため、私は試した事がありません。

![jail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/fa5952a1-7a34-de54-35af-43a6c92d1270.png)

jailをサポートする仕組みは標準のカーネルに入っていて、jexec,jlsなどの設定コマンドも標準で用意されています。ただこれらのコマンドで設定していくのはかなり複雑で、これまで代替のコマンドがいろいろ作られてきましたが、最近はBastilleBSDやiocageがトレンドのようです。

pkgでBastilleBSDをインストールします。

```
% sudo pkg install bastille
% sudo bastille -v
0.8.20210115
```

インターフェースを作ります。

``` 
% sudo sysrc cloned_interfaces+=lo1
% sudo sysrc ifconfig_lo1_name="bastille0"
% sudo service netif cloneup
```

/etc/pf.confを書きます。ext_ifは自分のホストのインターフェースにします。

```
ext_if="alc0"

set block-policy return
scrub in on $ext_if all fragment reassemble
set skip on lo

table <jails> persist
nat on $ext_if from <jails> to any -> ($ext_if)

## Enable dynamic rdr (see below) bastille 0.7+
rdr-anchor "rdr/*"

block in all
pass out quick keep state
antispoof for $ext_if inet #disable for VNET
pass in inet proto tcp from any to any port ssh flags S/SA keep state
```

pfは設定を間違えると、ログインできなくなりますので、注意してください。またこの設定だとホストでtftpクライアントも使用できなくなりますので必要な設定を追加する必要があります。pfを有効にします。

```
% sudo sysrc pf_enable="YES"
% sudo service pf start
```

セッションが切れるのでもう一度ログインします。

/usr/local/etc/bastille/bastille.confのbastille_tzdataを"Asia/Tokyo"に変更しておきます。

jailを作ります。IPアドレスはホストのインターフェースでnatするのでホストのインターフェースとは別のサブネットでアドレスを設定します。

```
% sudo bastille bootstrap 13.0-RELEASE
% sudo bastille create testjail 13.0-RELEASE 192.168.10.50
```

rootでjailに入ります。

```
% sudo bastille console testjail
```

ツール名はパリにあった「バスティーユ牢獄」によるものだと思います。

マシン起動時にjailを上げておきたい時は、下記を実行しておきます。

```
% sudo sysrc bastille_enable=YES
```
LWCでカスタムデータ属性を扱うには

前回書いたこちらのpost
https://qiita.com/geeorgey/items/ff2ab9503091366dfb7d
カスタムデータ属性を使うともっと便利になるという情報を頂いたので実際にやってみたらハマったので備忘録。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">属性に関しては name でも持てますが将来的に使いたくなる可能性もあるので、カスタムデータ属性(data-*)がおすすめです💡 <a href="https://t.co/g7PDGPVC7c">https://t.co/g7PDGPVC7c</a></p>&mdash; Hiroki Tanaka | 田中宏樹 (@hrk623) <a href="https://twitter.com/hrk623/status/1398116956159418368?ref_src=twsrc%5Etfw">May 28, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##どうやって使うのか
ここではハイパーリンクのクリックイベントを拾うことにする。

```link.html
<a href={url} onclick={handleClick} data-opid={d.Opportunity__c}>{d.Opportunity__r.Name}</a>
```

js側でデータを受け取る場合

```link_clicked.js

    handleClick_like_opportunity(event) {
        console.log(event)
        console.log(event.target);
        console.log(event.target.dataset.opid);
    }
```

event.target.dataset.opid
という形式で取得できる。
分かってしまえばかんたんなんですけど、知らないと永遠にたどり着けないという罠。


大感謝

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://t.co/dtdPi66Pgm">https://t.co/dtdPi66Pgm</a>.dataset.test だったかと思います！</p>&mdash; Hiroki Tanaka | 田中宏樹 (@hrk623) <a href="https://twitter.com/hrk623/status/1399610575114567689?ref_src=twsrc%5Etfw">June 1, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【GCP】DB関連の動画

[Cloud OnAir] #01 徹底解剖 GCP のここがすごい - YouTube	
https://www.youtube.com/watch?v=VSV9AJWjMCI
 BQ、IaasPaasなどGCPの基本から説明してくれている。
　GCPの特徴もわかるかと思います。
	
(1) B12【Cloud】Google Cloud Platform を始めてみよう：GCP初心者向けのガイド - YouTube	
https://www.youtube.com/watch?v=xGzWnM3fvV4
　浅く広い説明をしてくれています。
　25:00からCLoud SQLについて触れています。
	
(1) D2-1-S06_フルマネージド データベースサービス "Cloud SQL" 徹底活用法 - YouTube	
https://www.youtube.com/watch?v=hdoUoJtURNE
　GCPのDB全体のはなしから、CloudSQLの詳細な説明をしてくれます。
　ちょっと専門的な話もでてくるので、理解に苦しむところもあるかもしれません。
	
(1) #CloudOnAir [Cloud OnAir] Google Cloud へのデータ移行 [2019年1月24日放送] - YouTube	
https://www.youtube.com/watch?v=KE6pcmYeAiA&list=PLmoHjhhs3ySG19mDr5YZgtp-XdZ0D1dYr&index=67
　これと似た内容かも
 39:15からDB機能の使い分けのフローチャートも紹介してくれています。
【Kotlin】Class コンストラクタ

#■コンストラクタとは
classのインスタンス化を生成した時に初めに呼ばれるメソッド

インスタンス化する時に引数に値を渡して
インスタンス内のclassの値をカスタマイズする。

#■プライマリコンストラクタ
クラスに一つだけ記述できるコンストラクタ
書き方

calss クラス名 constructor(引数名:データ型,引数名:データ型){}

``` kotlin
class Human constructor(name: String, age: Int) {
 var name: String
 var age: Int

  init{
  this.name = name
  this.age = age    
 }

 fun intro() {
  println("私の名前は${this.name}です.${this.age}歳です。")   
  }
}

//インスタンス化する時に引数に渡したいものを渡せる。class内部を更新
val aaa = Human("たける",19)
aaa.intro()
//結果: 私の名前は太郎です。19歳です。
```

■constructorを省略して書ける。

``` kotlin
class Human(name: String, age: Int){}
```

■プロパティを引数に渡してもっとシンプルに書ける。
 中に書いてたプロパティを引数に書いてる。
init{}とかいらない。

``` kotlin
class Human(var name: String, var age: Int) {
  fun intro() {
  println("私の名前は${this.name}です.${this.age}歳です。")   
  }
}
```

■private等アクセス修飾子も付けれる。

``` kotlin
class Human(private var name: String, private var age: Int) {}
```

#■セカンダリコンストラクタ
ひとつのclassに2つ以上のコンストラクタを定義できる。
指定した引数の数以外の時に中身に書いたコンストラクタが発動する。

``` kotlin
class Human(var name: String, var age: Int) {
  constructor(name: String):this(name,10) {}
  constructor():this("太郎"){}
  fun intro() {
  println("私の名前は${this.name}"です。${this.age}歳です。)
  }
}

val human1 = Human("義経",5)
val human2 = Human("サンタクロース")
val human3 = Human()

human1.intro() //結果: 私の名前は義経です。5歳です。
human2.intro() //結果: 私の名前はサンタクロースです。10歳です。
human3.intro() //結果: 私の名前は太郎です。10歳です。
```

■もっとシンプルに書く下記でも同じ意味

``` kotlin
class Human(var name: String = "太郎", var age: Int = 10) {
   fun intro() {
   println("私の名前は${this.name}です。${this.age}歳です。")
 }
}

val human1 = Human("三菱",5)
val human2 = Human("ゴリラ")
val human3 = Human()
human1.intoro() //結果: 私の名前は三菱です。5歳です。
human2.intoro() //結果: 私の名前はゴリラです。10歳です。
human3.intoro() //結果: 私の名前は太郎です.10歳です。

```
GitHub actionsでSkickaを使う方法

GitHub actionsからGoogle Drive APIのラッパーであるSkickaを使う方法です。
公開されているactionもあるんですが、macがサポートされていなかったり、ダウンロード機能がなかったりしたので、直接Skickaを使えるように調べました。
認証情報の取得方法は https://qiita.com/sekitaka_1214/items/85875d64c226b2f7ab86 を参考にしてください。

```
steps:
  - run: echo SETUP_SKICKA
  - uses: actions/setup-go@v2
  # skickaダウンロード
  - run: go get github.com/google/skicka
  # シークレットから認証情報を流し込み
  - run: |
      cat <<EOF >> $HOME/.skicka.config
      [google]
      ;Override the default application client id used by skicka.
      clientid=$GOOGLE_CLIENT_ID
      clientsecret=$GOOGLE_CLIENT_SECRET
      EOF
    shell: bash
    env:
      GOOGLE_CLIENT_ID: ${{secrets.GOOGLE_CLIENT_ID}}
      GOOGLE_CLIENT_SECRET: ${{secrets.GOOGLE_CLIENT_SECRET}}
  - run: chmod 600 $HOME/.skicka.config
  # シークレットから認証情報を流し込み
  - run: echo $SKICKA_TOKENCACHE_JSON > $HOME/.skicka.tokencache.json
    shell: bash
    env:
      SKICKA_TOKENCACHE_JSON: ${{secrets.SKICKA_TOKENCACHE_JSON}}
  - run: chmod 600 $HOME/.skicka.tokencache.json
  # 実際に使う
  - run: $HOME/go/bin/skicka -no-browser-auth download hoge/ ./hoge

```
gmailでエイリアスごとに署名を設定する

Gmailでエイリアス設定済みアカウントにて複数の署名をエイリアスそれぞれに割り当てる方法です。

# エイリアスを設定する
個人用GmailとGoogle Workspeace(旧G Suite)では設定が異なるので省略します。
以下の記事を参考にしてください。

### 個人用エイリアス設定方法
https://support.google.com/mail/answer/22370

### Google Workspeace用設定方法
Google Workspeaceではアカウントにエイリアスが割り当てられている必要があります。
管理者用設定方法は以下の記事を参考にしてください。
https://support.google.com/a/answer/33327?hl=ja

利用者側での設定方法は個人用と同一です。

# 署名の設定
https://support.google.com/mail/answer/8395
このページの`[名前] 機能を使用している場合に署名を追加する`に書いてありますが、簡略すぎるので図で説明します。
設定→全般→署名に以下の図のような設定があります
![qiita01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593714/628d0af8-a49c-02cf-7023-883606bbab07.png)
真ん中あたりに`デフォルトの署名`というのがあるのでこれを設定します。
署名を設定したいエイリアスを`メールアドレス`から選択し、上で設定した署名を割り当てます。
新規メール用と返信/転送用でそれぞれ署名が割り当てられるようです。
設定が完了したら、ページ下部の`変更を保存`を忘れずに押してください。
以上です。
リバーシの操作（斜め） Java編　解答

https://qiita.com/shidoh78/items/e43ad540ea60fcf40fcd

ようやくハマりから抜け出せた。
「お手本を写してもなんかうまくいかない……」
「質問を投げてみたけどmaxとminはC++と一緒……？　うーん……？」
という感じで迷っていたのだが、

なんてことはない、**JavaのString一致判定はequals()メソッドであることを失念していた**というオチだった。
==で繋いでも駄目ですよそりゃ。


```java
import java.util.Scanner;


public class Main {
    public static void main(String[] args) {
        int h, w, y, x;
        String[][] map;

        Scanner sc = new Scanner(System.in);

        h = sc.nextInt();
        w = sc.nextInt();
        y = sc.nextInt();
        x = sc.nextInt();

        map = new String[h][w];

        for(int i=0; i<h; i++){
            String temp = sc.next();
            for(int j=0; j<w; j++){
                map[i][j] = String.valueOf(temp.charAt(j));
            }
        }
        //_____ここまで初期化______

        for(int i=-1; i <= 1; i+=2){
            for(int j=1; ; j++){

                if(x+(i*j) == -1 || x+(i*j) == w || y+(i*j) == -1 || y+(i*j) == h){
                    break;
                }

                if(map[y+(i*j)][x+(i*j)].equals("*")){
                    for(int k = Math.min(y+(i*j), y); k <= Math.max(y+(i*j), y); k++){
                        map[k][k-y+x] = "*";
                    }
                    break;
                }
            }
        }

        for(int i=-1; i <= 1; i+=2){
            for(int j=1; ; j++){

                if(x+(i*j) == -1 || x+(i*j) == w || y-(i*j) == -1 || y-(i*j) == h){
                    break;
                }

                if(map[y-(i*j)][x+(i*j)].equals("*")){
                    for(int k = Math.min(x+(i*j), x); k <= Math.max(x+(i*j), x); k++){
                        map[y+x-k][k] = "*";
                    }
                    break;
                }
            }
        }
        map[y][x] = "*";

        // _____ここから表示_______
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                System.out.print(map[i][j]);
            }
            System.out.println("");
        }
    }
}
```

ただ、「囲む処理をどういう基準で算出しているのか」についてはまだ理解出来ていないので、紙に書くなりして整理してみようと思う。
意外とこういうところでアナログって強いのよね。

そこを理解したらやっと次に行ける……。Cランク相当問題とはいったい……。（体調不良のせいってことにしといて）
puppeteerのダウンロード先を指定してもwinでは上手く動作しない場合の対処法



## 問題
macで作成したブラウザの自動操作でダウンロードを行うプログラムをwinで動作させようと引越しした時のこと

chroniumのダウンロードバーで「ダウンロードエラー」の表示が出てきて、正常に動作しない。

```js:index.js
const TOP_DIR = __dirname;
const DOWNLOAD_DIR = `${TOP_DIR}/download`;

//ブラウザをlaunchした後
await page._client.send(
    'Page.setDownloadBehavior', { behavior: 'allow', downloadPath: DOWNLOAD_DIR }
);

```

macではこれで指定したdownloadフォルダにファイルがダウンロードされたのに、なんでだろう？


## 対応
「/」じゃなくて「¥」を使えば解決しました。うーん初心者

```js:index.js
const TOP_DIR = __dirname;
const DOWNLOAD_DIR = `${TOP_DIR}\\download`;

//ブラウザをlaunchした後
await page._client.send(
    'Page.setDownloadBehavior', { behavior: 'allow', downloadPath: DOWNLOAD_DIR }
);

```

あんまりwinで作業しないので自分のエディタ(sublime)だけなのか知りませんが、「¥」が入力されなくて「\\」になっちゃうので「\\\\」と入力すれば解決です。

winでもパス指定の書き方は別に「/」区切りで問題なく使えていたので、勝手に大丈夫と見落としていたので時間かかりました。お恥ずかしい。

備忘録として
非エンジニアがエンジニアと仕事をする際に大切なこと

## はじめに
https://qiita.com/qnoyxu/items/8b07d571ef858608e93d

@qnoyxuさんのこの記事が非エンジニアの私から見てもとても参考になったので、非エンジニアである私がこれまでエンジニアと一緒に仕事をしてきた中で、色々な失敗も経て学んできた大切だと思うことをまとめてみました。


## これまでやってきたお仕事
現在私はQiita株式会社の代表としての会社経営が主なお仕事です。
これまでエンジニアと一緒にやってきた主なお仕事は下記の通りです。

* ツールアプリの新規事業責任者（3年ほど）
    * 全体3名の少人数チームでスタート
    * 私、エンジニア1名、デザイナー1名
    * その後ビジネスサイド20名、エンジニア10名、デザイナー5名ほどの体制へ

* ゲームアプリのマーケティングマネージャー（5年ほど）
    * 組織全体としてはビジネスサイド20名、エンジニア5名、デザイナー5名ほど
    * アプリのトラッキングツールの設定やWebサイトの制作、ユーザーデータ管理システムやKPI管理ツールの開発の領域をエンジニアと共に推進


## 非エンジニアがエンジニアと仕事をする際に大切なこと
**目次**

* [エンジニアの仕事を理解する](#エンジニアの仕事を理解する)
* [曖昧な依頼は極力避ける](#曖昧な依頼は極力避ける)
* [品質に関する費用対効果を考える](#品質に関する費用対効果を考える)
* [出来るか出来ないかを深く確認する](#出来るか出来ないかを深く確認する)
* [最後に](#最後)


## エンジニアの仕事を理解する
以前私は全くエンジニアに関する理解が無い中でUIの変更や仕様変更の依頼を頻繁にやっていました。そのとき私の視点からすると「ボタンの位置変更」や「ページ遷移の変更」などは、まるでパワーポイントのデザインを変えるくらいの感覚だったのです。（今思い返してもひどい話です。許してください。）

もちろん、そんなやりとりでうまくいくはずもなく当時のエンジニアとは険悪になりました。
どうにか改善をしようと下記のことをやってみました。

* **すごく簡単なプログラミングの仕事を実際にやってみる**

当時はアプリを作っていたのでエンジニアに教えてもらいながらXcodeやEclipseで環境を準備してみたり、Gitコマンドを勉強してみたり。しばらくすると動作チェックのためのビルドやボタンの位置の微調整などのリリースは自分でやるようになっていました。
以下のサイトは当時良く見ていました。非エンジニアにも分かりやすい内容になっています。

https://backlog.com/ja/git-tutorial/

そんなことを続けていくことで何となくですが、エンジニアがやっている仕事の想像が出来るようになりました。表面的に見えているもの以上に色々な作業を行っているという理解を得られたことで、コミュニケーションの仕方が改善していきました。

## 曖昧な依頼は極力避ける
あるときのやりとりです。

**私「このボタンをタップすると登録が出来るように作って欲しいです」**
**エンジニア「わかりました」**
~
**エンジニア「出来ました」**

確認すると、たしかにボタンをタップすると登録が完了するように動いていました。
ただ、登録の処理が完了した際の「登録が完了しました！」という表示はありません。
私のイメージしていたものは完了後に完了したことがユーザーに分かるような動きでした。

確かに私がお願いした仕様は「ボタンをタップすると登録が完了する」ですのでエンジニアは悪くないです。

それからは、エンジニアに依頼するときは**なるべく全ての動きを細かく伝えること**を意識しています。
もちろん詳細な仕様書があるときは問題ないですが、状況によっては口頭ベースで物事が進むこともあるためその際には強く意識をしておくことが大切です。

## 品質に関する費用対効果を考える
これもプロダクト開発に対する考えがとても浅はかだったときの話です。
あるプロダクトの開発を外部の会社に発注をするために複数社から相見積もりをとりました。
そしたら出てきた費用見積もりの金額が、安いところと高いところで5倍ほどの差がありました。

そこで浅はかな当時の私はこう考えました。

* **仕様書通りのものが出来上がるのだから、安いところを選ぶのがベスト**

（ひどい話です。許してください。）

そのことを社内のエンジニアに話すと猛反対を受け、結果的にいくつかの会社とコミュニケーションをとった結果、2番目に高い会社に依頼することになりました。

その結果、出来上がったアプリの品質は素晴らしく、リリース後の不具合対応や保守運用もスムーズでした。
そしてなんとマテリアルデザインに準拠した素晴らしいUI/UXということでGoogle Playからピックアップもされるというビジネス的な恩恵も受けました。

https://tayori.com/blog/material-design/

後に別案件でとても低単価の発注をしたこともありましたが、納品時の品質（仕様書通りの動きはするけど色々まずい状態）や保守運用や更新時や仕様追加時のトラブルなどで結果的に社内の人件費と考えると高くついた経験があります。

## 出来るか出来ないかを深く確認する
ある時に新しい仕様についてエンジニアと相談していたときの話です。

**私「検索結果の表示情報を一覧で1ページにまとめて表示をしたいんですが」**
**エンジニア「うーん、ちょっとそれは○○の仕様的に無理ですね」**
**私「なるほど、では別のやり方を検討しますね」**

その後、再度エンジニアと相談をしていく中で、実際には出来ることが分かりました。
結果的には一覧表示をする情報は全てのデータではなく、主要な一部のデータを抜粋して表示することになったのです。
ではなぜ最初の会話の中で一旦無理という着地になったのか。

冒頭の会話の中でそれぞれの頭の中にずれがありました。

**私「検索結果の表示情報を一覧で1ページにまとめて表示をしたいんですが」**
頭の中（とにかく視覚的に一覧で情報を表示したい。細かい情報はそこから詳細へ飛ぶでも問題ないかも）

**エンジニア「うーん、ちょっとそれは○○の仕様的に無理ですね」**
頭の中（全ての情報を一覧で表示するには画像の処理や表示的にどうしても現状の仕様では実現できない）

このようなずれを無くすためにも

* **実現したい大目的は何なのか**
* **出来ない場合は出来る他の方法は無いかを探る**

ことがとても大切です。


## 最後に
これを読んで頂いたエンジニア、非エンジニアが良い関係性で良い開発が出来る手助けに少しでもなれれば幸いです。

https://qiita.com/official-events/c826cda7a9514df143cb
GitHub Actionsでコマンドの結果を環境変数に設定する


`変数名=値` というテキストを `$GITHUB_ENV` にリダイレクトすると環境変数に設定でき、 `${{ env.変数名 }}` でアクセスできる。

例: app_versionという環境変数に、package.jsonに記載されているバージョンを設定するには次のようにする。

```
      - name: setup environment variables
        run: |
          node -e "console.log('app_version=' + require('./package.json').version)" >> $GITHUB_ENV
      - name: use environment variable
        run: |
          echo "app_version is ${{ env.app_version }}"
```

# 参考
https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
Error: Api: /smart/api/order/xxx/capture returned status code: 500 

# ■(PayPal) status code: 500

PayPalボタンをWEBに設置した際、ログインをして支払いをすると以下のようなエラーが出た。

>Error: Api: /smart/api/order/xxx/capture returned status code: 500 (Corr ID: xxxxxxxx)
    at https://www.paypal.com/smart/buttons?style.label=paypal&style.layout=vertical&style.color=gold&style.shape=rect&style.tagline=false&components.0=buttons&locale.country=JP&locale.lang=ja&sdkMeta=

エラーコードが500なので、公式のリファレンスで調べると
https://developer.paypal.com/docs/api/reference/api-responses/

予期しないエラーとのことで、原因は分からず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477820/8613fbd1-772a-e765-0772-ac1d8840eae7.png)

## ■解決策
単純に、支払っているPayPalのアカウントに紐づけられたクレジットカードが使えなくなっていた。
意外に当事者は気づかないので、少しハマった。

少しでも皆さんの開発が効率的になればと思います。

My Twitter:
https://twitter.com/funny_man_daa
vi の起動・編集・保存・終了の超基本コマンドメモ。

テキストエディタの vi を１年に１回くらいの頻度で使うのだが、毎回いろいろ忘れてしまう。

# 起動

```
$ vi hoge.txt
```
ファイル名を指定して起動。ファイルが存在しない場合はファイル新規作成になる。

# 編集・保存・終了

以下の流れさえ覚えておけば何とかなる。

* `i`で編集モードに入る
* 内容を編集する（よそからコピーしてきた文字列のペーストも可）
* `Esc`で編集モードを抜ける
* `:wq`で保存しつつ終了（代わりに`:q!`だと保存せずに終了）

# 便利コマンド

* `↑` `↓` `←` `→`：カーソル移動。
* `G`：カーソルを最終行に移動。
* カーソル移動してから`o`：`i`とは異なり、編集モードに入りながら改行もする。`G`と組み合わせればファイル末尾への追記に便利。
* `dd`：１行消す。
* `x`：１文字消す。

コマンドは編集モードでないときに使うこと。編集モード中だと`G`や`dd`といった文字列が入力されてしまう。

# おわりに

この記事で紹介したコマンドはごく一部。
例えば下記の記事とかを見てみると、とても丁寧にまとまっている。ありがたいです。

https://qiita.com/pe-ta/items/0510bee10bcfd88afeee

高性能なテキストエディタがいろいろある世の中だけど、セキュリティの事情とかで vi しか使えない状況とかもあるし、必要最低限のコマンドくらいは覚えておきたいね。。。



今回はここまで。
無償でTeradataDB環境構築（Teradata Express for VMware）

# 目的
評価、開発、学習を目的に、無償で利用可能なTeradataDB Expressを利用してTeradataDB環境を構築
構築済の環境がVMware仮想Diskとして提供されているので流れは以下。簡単。

1. Teradata Express for VMwareをダウンロード
1. VMware Playerで起動


# ■手順
## １．「Teradata Express | Download Free Trial」にアクセス
　　https://www.teradata.jp/Products/Software/Database/Teradata-Express


## ２．DOWNLOADTERADATA EXPRESSをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/b0c91177-7dc9-819f-73c7-a80af5dd0610.png)

## ３．ユーザ登録してログイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/5dc40138-eaae-d77c-9353-5061feaf82e8.png)


## ４．インストーラダウンロード
　　ログインするとダウンロード可能なインストーラとユーザガイドが表示される
　　現在、ダウンロード可能なバージョンは17.05, 16.20, 16.10 
　　今回は16.20をダウンロード（3.9GB）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/1521fab2-901c-6343-2d0a-30426ca7bcc1.png)

## ５．ダウンロードしたファイル（7zファイル）を解凍

解凍後の容量は14GB
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/b8164949-9ef6-30a6-4b43-63e5bae03fa5.png)

## ６．VMware Workstation Playerをダウンロード
VMware Workstation Player - My VMware
https://my.vmware.com/jp/web/vmware/downloads/info/slug/desktop_end_user_computing/vmware_workstation_player/16_0

VMware Workstation 16.1.2 Player for Windows 64-bit Operating Systemsをダウンロード（215MB）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/72826568-685a-00f2-0433-b6d25f1377a9.png)



## ７．VMware Workstation Playerをインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/5a719e81-ea1c-fccd-fb2c-e0c27a7376d8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/cd6609ad-677c-a403-c930-4bb3d5f58e50.png)


## ８．VMware Workstation Playerを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/9a5932ea-7d04-c55c-c04e-2aeeaaa977d7.png)

仮想マシンを開くから「TDExpress16.20_Sles11」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/3513b5d8-3a09-bd84-899a-808ad68b0583.png)

## ９．仮想マシンの再生
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/6980a23e-8385-23e9-2326-ab5ab3648859.png)

## １０．SUSE Linux SUSE Linux にログイン
　Login　　 ：　root
　Password　：　root

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/2e091aab-7774-81bf-d712-2c77f7a31522.png)

## １１．起動完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685631/fb7fdfad-5025-108b-75ff-efa7abcd3c92.png)

## １２．起動後（作業環境）

- [SUSE Linuxのキーボードを日本語に変更](https://qiita.com/bickel/items/55bbd2d29a9f534bc79d)

- [Teradata Studio Express 接続方法](https://qiita.com/bickel/items/2132c575e29a6dc0fc45)

## １３．DB設定

[インストール後に実施すること](https://qiita.com/bickel/items/e9ac5617c733e5e8314c)参照
MyBatis Dynamic SQLでつまづいた～型が一致しません。～

# はじめに
手を動かして事象を理解しただけで、本質的に間違っている部分があれば、ご指摘いただけると幸いです。 :man-bowing:

# 環境
- MyBatis
- MyBatis Generator
- Kotlin

# 起きたこと
以下のソースコードでなぜか怒られた。

```SampleRepositoryImpl.kt（例）
SampleMapper.select {
    where(userIdFromDb, isEqualTo(userId))
    if(limit >= 1){limit(limit.toLong())}// ->この行が「型が一致しません。必要:Buildable<SelectModel> 検出:Unit」と言われる
}
```
※SampleMapper#selectはMyBatis Generatorが自動生成してくれるselectメソッド（[MyBatis Dynamic SQL](https://mybatis.org/mybatis-dynamic-sql/docs/kotlinMyBatis3.html#Select_Method_Support)）です。
limitに変な値が来ても大丈夫なよう「limitが1以上ならSQLにLIMIT句を付けてほしい」だけで、
変な値だったらWHERE句だけにしてくれればいいのにな。。。という感想。（例のlimitは他の `and` や `offset` に読み替えていただけます）

# 事象理解
Kotlinならではの事象だと理解しました。端的に説明すると
if文判定した結果falseの場合、 `if文の戻り値が無し` ＝ `Kotlinで戻り値無しはUnit型扱いとなり型が不一致(KotlinQueryBuilderを期待している)`
ということで、「if文の結果、空行になったとしても、if文を判定した以上、if文の戻り値(はないのでUnit)がselectに渡される」んだなあ、、と。

# 回避策
ただ回避するための策になったので、別案を募っております。

```SampleRepositoryImpl.kt
SampleMapper.select {
    where(userIdFromDb, isEqualTo(userId))
    if(limit >= 1){limit(limit.toLong())} else {this}
```

`this: KotlinQueryBuilder` なので、「返すものがないならthisを返せばいいじゃない」という発想です。
ただこれ、if文が複数行続く場合「最後のやつにだけ付ければオーケー」という謎ルールになりスマートではないな、、と。

ひとまずbuildで怒られなくなりました、という話でした。
SquidでHTTPS通信をする場合に追加する設定

Squidを導入したProxyサーバを経由して、443以外のポートを使用しているHTTPSサイトにアクセスする場合の設定

#### やること
* Safe_ports と SSL_ports に、使用するポートを追加する。
この2つがセットで設定されている必要がある。

```squid.conf
acl Safe_ports port 5000
acl SSL_ports port 5000
```

Safe_ports を追記することで、Proxy経由でのアクセスが許可される。
SSL_ports を追記することで、HTTPSアクセスが許可される。


参考：squid.confへの追記内容

https://shibainu55.hatenadiary.org/entry/20100220/1267341365

#### 補足

HTTPSアクセスを許可しているのは、デフォルトで記述されている以下の2つの記述。

```
acl CONNECT method CONNECT
http_access deny CONNECT !SSL_ports
```

http://realizeznsg.hatenablog.com/entry/2018/08/07/070000
CloudFrontを導入してから、ブラウザ再読込で403エラーになってしまう際の解決法

CloudFrontのコンソールから、Invalidationsタブ→Create Invalidationで/*を指定するとブラウザ再読込を行ってもエラーにならなくなりました。古いキャッシュを消してくれるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630191/84d3bd4b-445e-3873-20c7-e630aea5ebc6.png)

ここまでだと、トップページ以外で再読込した場合はまだ403になってしまうので、CloudFrontのコンソールError Pagesタブで以下の用にトップページへリダイレクトする設定にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630191/fe3b820c-ca68-eaed-5ff7-82b5e443901b.png)
オンプレにおけるAzure Private linkの名前解決について / Name resolution of Azure Private link on DNS on-prem

(Followed by English translation)

オンプレ（を模した環境）から、Azure Private linkを経由して閉域網にてAzure blobにアクセスする環境を試しました

### 前提
Azure Private Link を使うとblobやSQL等にPrivate Ip addressでアクセスできますが、アクセス元がオンプレミスのサーバーの場合、名前解決が課題です。
 
Private linkはTLS利用が必須で、よってIPアドレスでは無くFQDN宛にアクセスする必要があり、かつこのFQDNがPrivate linkのprivate IPアドレスに名前解決される必要があります。Private link作成時にAzureのデフォルトDNSに設定がされるので、同一regionのAzureリソースからのアクセスの場合気にしなくていいのですが、それ以外の場合は名前解決にひと手間必要です 

オンプレからの場合、hostsを使うかDNS forwardingかの2択です
https://docs.microsoft.com/azure/private-link/private-endpoint-dns

### 手順
今回はAzure JapanEast regionのblob にprivate linkを設定し、オンプレの代わりにJapanWest regionのVMからVPN経由でアクセスを試しました。private linkの名前解決は当該VMのhostsを使っています。手順は以下です

- VPN
https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-howto-vnet-vnet-resource-manager-portal

- Private link for Azure Storage
https://docs.microsoft.com/ja-jp/azure/storage/common/storage-private-endpoints?toc=/azure/storage/blobs/toc.json

blobの設定はこんな感じになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327770/5a9d7293-c90e-3a52-2928-c4175981743f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327770/71cdb2e9-da1a-935c-f15e-bc5465908b1b.png)



環境の構成図はこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327770/64ef61e4-008d-cc52-e0c1-675d13fcabe1.png)
VM at JapanWest -> blob at JapanEastのテストはazcopyを使いました

- ./azcopy copy "./hoge.txt" "https://yoaraistorage1.blob.core.windows.net/con1/1.txt?&lt;SAS token&gt;
- ./azcopy list "https://yoaraistorage1.blob.core.windows.net/con1/?&lt;SAS token&gt;
- ./azcopy copy "https://yoaraistorage1.blob.core.windows.net/con1/1.txt?&lt;SAS token&gt; "./download_1.txt"

ご参考になれば幸いです

-----
Let me share how to access Azure blob from on-prem through closed network with private link.

### Background
Azure Private Link allows you to access Azure blob, SQL etc via a private IP address.  However, if you access Azure from On-prem, name resolution becomes a matter.

TLS is required to access private link, hence you need to access not IP address but FQDN of the private link, and the FQDN should be resolved to private IP address of the private link.  Azure default DNS Server in the same region is automatically updated when creating a private links, but you need to take action by yourself in other case.

From on-prem, hosts or DNS forwarding are solutions.  See below doc about more detail.
https://docs.microsoft.com/azure/private-link/private-endpoint-dns

### Procedure

I checked this by creating a private link on a blob at Azure JapanEast, then accessing there from VM at JapanWest via VPN.  Name resolution was based on host of the VM.  Related docs are below:

- VPN
https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-howto-vnet-vnet-resource-manager-portal

- Private link for Azure Storage
https://docs.microsoft.com/ja-jp/azure/storage/common/storage-private-endpoints?toc=/azure/storage/blobs/toc.json

Please check the architecture diagram and test procedure by using AzCopy in Japanese section above.

Hope it helps you. Thank you.
EXECL関数のみで、データバー的なものを表現する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/5376cc05-5b1d-ccc4-3b27-7c97b2970fc2.png)


REPT関数を使用して、データバーを再現しました。自身以外の数値でも計算できるので、使い道はあるかと思います。
拡大率を変更すると見た目が変わってしまうので注意。
<br>

#1[AB:AC]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/277cd3f0-b842-d8bc-7905-ba6a67df805b.png)

```microsoftshell
=REPT("|" , 対象のセル )
```

これで数値分の"|"(ヴァーティカルバー:Shit+￥(Backspaceの隣))が表示されます。

■や環境依存文字なども使用できます。

書体を$"HG正楷書体-PRO"$や$"教科書体"$などにしてフォントサイズを小さくすると"|"の間隔がほとんどなくなりデータバー風になります。
文字サイズを変更することでも見た目が変わります。

<サンプル> 文字数、文字サイズ、文字色はすべて同じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/0519cb0b-b6f6-f971-2f95-51e3aca45721.png)
フォントサイズを11=>6に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/f7d5b46e-f315-8dfc-a36e-99baa9eeb69c.png)


<br>

#2[AE:AG]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/ba3693f6-9765-154b-ea28-d72aede2c785.png)

2列使用して80を超えると赤く表示します。

```vb
1列目: =if( 対象セル <=80 , REPT("|", 対象のセル ) , REPT("|",80))

2列目: =if( 対象セル <=80 , ""                    , REPT("|", 対象のセル - 80))
```

としています。あとは1列目の幅を調整して、2列目の文字色を赤くしてやれば完成です。
(数値を赤くしたり背景を塗るのは条件付き書式で)

<br>
#3[AI:AJ]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/e43e0153-d3f7-333d-73ce-98f0a865b3b0.png)

3つ目では、現在までの経過日数を出していますが、1日="|" にしてしまうと長くなってしまうので、15で割って約半月="|"にしています。

```vb
=REPT("|" , ( NOW()- 対象のセル )/15 )
```

例えばを最大値を決めたければ

``````vb
=REPT( "|" , 対象のセル / 最大値 * 表示させる最大文字数 )

ex1.) =REPT( "|" , 対象のセル / 100 * 10 )
    '最大値100を10個の"|"で表示する

ex2.) =REPT( "|" , 対象のセル / MAX( すべての対象のセル範囲 ) * 100 )
    'すべての対象のセル範囲中で最大のものを100個の"|"で表示する = パーセント(%)表示

```

とすることで決められます。

<br>
#4[AL:AP]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/184b750c-4d95-6575-5c85-a681ccbda21b.png)

一番右の表では合計の欄に

```vb
="  " & SUM( 対象範囲 ) & REPT( " " , 5 - LEN( SUM( 対象範囲 ))) & REPT( "|"  ,SUM( 対象範囲 ) / 10 )

1.                            "  "   '最初の余白'
2.                   SUM( 対象範囲 )  '合計'
3. REPT(" ",5-LEN(SUM( 対象範囲 )))   '5文字になるように" "を追加'
4.      REPT("|",SUM( 対象範囲 )/10)  '数値の数/10だけ"|"を表示'

```

と入力しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/5d373ae6-638a-112c-cc94-f939786d50b5.png)

書体によっては、数字とスペースの幅が異なるので、バーの開始位置が合いません。
幅が同一の$"SimSun"$などの書体に変更します。

（バーと合計の表示順を逆にすればいいだけでは？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/5d64a44c-b47b-0efa-5b66-f450b7d28b09.png)




<br>

色も付きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/0371e521-9653-813b-82a6-ee3aa3882ac5.png)


#追記

文字の方向を回転させればグラフも作成できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/41cac553-9a9f-1075-a6bc-5ebdc919757c.png)


REPT関数に小数点を含む数値を指定した時と、切り上げ/切り捨て/四捨五入
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1529940/fe76599d-bc70-7ca0-8293-7997bb326fbd.png)

<br>
以上
jQuery.Deferred exceptionが出て困った

jQuery.Deferred exceptionがブラウザのコンソールに出てきて困った。

自作のjsファイルをrequireして使用していたが、初歩的な部分でうまくかけていなかった様。

    module.exports = {hogehoge, hogehoge2};

requireされる対象のファイルに上記を記載して例外は解消。
PHPでテンプレートデザインを作成する

イラストレーター等で作成したテンプレートデザインにプログラミング言語PHPを利用して流し込みできるサンプルを実装したので、自分への備考録も兼ねてまとめましたのでご紹介します。


□ 使用言語: PHP
前提 HTML/PHPの基礎的知識、フォーム送信が分かる方向け

□ テンプレート作成ツール
Adobe Illustrator推奨、解像度にこだわなければAdobe XDも可
他にもExcel、WordなどPDFを作成できるアプリケーションなら可


### ライブラリを用意
TCPDF: https://github.com/tecnickcom/tcpdf

ダウンロード後、下記フォルダ・ファイルを抜き出して「tcpdf」（名称任意）のフォルダ名で新規作成して入れておく
fonts
include
tcpdf_autoconfig.php
tcpdf_barcodes_1d.php
tcpdf_barcodes_2d.php
tcpdf_import.php
tcpdf_parser.php
tcpdf.php


FPDI: https://www.setasign.com/products/fpdi/downloads/
ダウンロード後、「src」フォルダを抜き出して「fpdi」（名称任意）の名前に書き換える

この2個のフォルダを「lib」（名称任意）というフォルダにまとめる。


### 全体のディレクトリを構成する

①全体のプロジェクトフォルダとして「tcpdf」（名称任意）作成」

②その中に先ほど作った「lib」フォルダとルートファイルの「index.php」と「receipt / receipt-pdf.php」「receipt / receipt.pdf」を作成

index.php　今回はここにフォームデータ入れます
receipt-pdf.php　流し込むための処理を書く
receipt.pdf 　流し込みテンプレートとなるファイル
※今回はサンプルとして領収書なのでreceiptにしています

□ index.phpを編集

```php
<form method="post" action="./receipt/receipt-pdf.php" target="_blank">
    <div>
        <div>No.</div>
        <div><input type="text" name="number" value="00" placeholder="No." required></div>
    </div>
    <div>
        <div>名前</div>
        <div><input type="text" name="name" value="山田太郎" placeholder="お名前" required></div>
    </div>
    <div>
        <div>金額</div>
        <div><input type="text" name="price" value="10000" placeholder="金額" required></div>
    </div>
    <div>
        <div>但し書き</div>
        <div><input type="text" name="proviso" value="お品代として" placeholder="但し書き" required></div>
    </div>
    <button type="submit">PDFを作成</button>
</form>
```

□ receipt-pdf.phpを編集

```php
<?php
// ライブラリ読み込み
require_once('../lib/tcpdf/tcpdf.php');
require_once('../lib/fpdi/autoload.php');

// ライブラリインスタンス化
$pdf = new setasign\Fpdi\Tcpdf\Fpdi('P', 'mm', [210, 297], true, 'UTF-8', false);

// $pdf->SetMargins(0, 0, 0); //マージン無効
$pdf->SetAutoPageBreak(false); //自動改ページ無効
$pdf->setPrintHeader(false); //ヘッダー無効　trueにすると線が表示
$pdf->setPrintFooter(false); //フッター無効　trueにすると線が表示

$pdf->setSourceFile("receipt.pdf"); // テンプレートファイル指定
$pdf->AddPage();
$tpl = $pdf->importPage(1);
$pdf->useTemplate($tpl);

// フォームから送られてくる値受け取り
$number = $_POST["number"];
$name = $_POST["name"];
$price = $_POST["price"];
$proviso = $_POST["proviso"];

//$pdf->SetFont('kozminproregular', スタイル, サイズ);
//$pdf->Text(x座標, y座標, テキスト);

//No.
$pdf->SetFont('kozminproregular', '', 11);
$pdf->Text(150, 11, htmlspecialchars( $number ) );

//名前
$pdf->SetFont('kozminproregular', '', 28);
$pdf->Text(15, 35, htmlspecialchars( $name ) );

//金額
$pdf->SetFont('kozminproregular', '', 40);
$price = number_format($price) . "-";
$pdf->Text(68, 70, htmlspecialchars( $price ) );

//但し書き
$pdf->SetFont('kozminproregular', '', 11);
$pdf->Text(70, 90, htmlspecialchars( $proviso ) );

//日付
$pdf->SetFont('kozminproregular', '', 11);
$today = date("Y年m月d日");
$pdf->Text(150, 21, $today);

//$pdf->Output(出力時のファイル名, 出力モード);
$pdf->Output("output.pdf", "I");
```
CodeCommitのプルリクエストをSlackに通知する


#構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/5d486a64-572e-6a3d-0b40-b496c5a48b8f.png)

#Lambdaを作成

lambdaのコードです。userdict、slackのトークン、slackのチャンネルは各自編集してください。

```python:lambda_function.py
import logging
import pprint
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def SendToSlackMessage(message):
    #tokenとチャンネルIDは各自編集してください
    client = WebClient(token='your_slackbot_token') 
    response=client.chat_postMessage(channel='your_slack_channel', text=message)

def lambda_handler(event, context):
    
    pprint.pprint(event)
    
    repositoryname=event["detail"]["repositoryNames"][0]
    
    #arnとslackに通知したいユーザー名を対応させます。
    userdict={
      "arn:aws:iam::account_id:user/your_username":"shoma",
    }
    requestauthor=event["detail"]["author"]
    authorname=userdict[requestauthor]
    

    destinationReference=event["detail"]["destinationReference"]
    destinationBranch=destinationReference.split("/")[2]
    

    sourceReference=event["detail"]["sourceReference"]
    sourceBranch=sourceReference.split("/")[2]
    
    pullRequestId=event["detail"]["pullRequestId"]
    url="https://ap-northeast-1.console.aws.amazon.com/codesuite/codecommit/repositories/"+repositoryname+"/pull-requests/"+pullRequestId+"/changes?region=ap-northeast-1"

    if event["detail"]["pullRequestStatus"] =="Open":
      if event["detail"]["event"] =="pullRequestCreated":
        message=":clap:"+authorname+"さんがプルリクエストをオープンしました!:clap:"\
        +"\n【Repository】 "+repositoryname\
        +"\n【Branch】 "+sourceBranch+"→"+destinationBranch\
        +"\n"+url
        SendToSlackMessage(message)
```
###slackでのbot作成方法はこちら
https://qiita.com/ms2geki/items/f63757edf705dc5df537


#CloudWatchEventでルールを作成する
CloudWatchEventで以下のルールを作成します。


|設定|値|
| ---|---|
|イベントパターン|○|
|サービス名|CodeCommit|
|イベントタイプ|CodeCommit Pull Request State Change|
|ARN別任意のリソース|○|
|ターゲット|Lambda関数|
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/8c0589ad-afed-6034-2a4d-94c14339a1c9.png)


#完成例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/76c9b55b-0d1b-9966-22d7-16874f3cd7b1.png)
Dreamweaver 2021 サイト管理の内容が消し飛んだときの応急処置（Macのみ）

## 前段
バックアップしましょう。と言うと身も蓋もないですね。
しないと結構大変だったので、応急処置対応を備忘録。応急処置の方法を知りたい方は応急処置の項目に飛んでください。

ちなみに、バックアップの選択肢は以下。
### バックアップ選択肢
1. タイムマシン
2. 定期的な`.ste`ファイルの書き出し → ローカルのどこかに保存
3. `Site Prefs` ファイルの複製 → ローカルのどこかに保存

※ 2,3の処理を自動化しておくと良さげ

## なぜ消し飛んだのか
サイト管理への新規のサイト情報追加保存 → クラッシュ
上記のパターンの場合に消し飛びました。まっさら。もう今日仕事しなくて良いのかと思いました。
どうも`Site Prefs` ファイルへの書き込み処理が中途半端な状態になってしまった様子。
リカバリ用ファイルとかも見当たらなかったので...す。

## 応急処置
2つご紹介。
### 1. Site Prefs ファイルを編集する
サイト管理の定義は上述している`Site Prefs` ファイルに記載されているので、そちらの内容を修正する。
`Site Prefs` ファイルの場所は以下。

/Users/{ユーザー名}/Library/Application Support/Adobe/Common/{バージョン数字}/Sites/Site Prefs

具体的には、記述されている特定のサイト情報がバグっているので、その部分をマルッと削除とか編集するとサイト情報が復活します。

### 2. 旧バージョンのSite Prefs ファイルを再利用
`Site Prefs` ファイルの破損の具合によっては、修復不可な状態になっているので、こちらの方法も試してみると良いです。
`/Users/{ユーザー名}/Library/Application Support/Adobe/Common/` 配下にバージョン違い（数字のディレクトリ）の`Site Prefs` ファイルが残っているので、そちらを流用する。
最新ではないですが過去の定義は復旧可能なので、選択肢の1つとして考えておくと吉、です。


## 参考サイト
[サイト定義に関連する操作を行うと強制終了する（Dreamweaver CS6/CC/CC 2014）](https://helpx.adobe.com/jp/dreamweaver/kb/cq03110804.html)
Codeforces Round #722 (Div. 2) C. Parsa's Humongous Tree 木DP


http://codeforces.com/contest/1529/problem/C

# 題意(省略)

# こう考えた
辺の合計を最大化するためには、各頂点の値は$l$あるは$r$のどちらかの値に振るのがよく、中間的な値は取らない．
ただし、各頂点を$l, r$どちらに寄せるのが良いのかはわからない．

考え方としては

- 1つの頂点$a$ 以外のすべての頂点が決まっているとするなら、$a$を$l, r$のどちらに寄せるべきかは自明である.

このため、適当な頂点(例えば0)をとり、葉から根に対して、自分が$l$である時を$[0]$で、$r$であるときを$[1]$として、それぞれのとき、子が$[0]$あるいは$[1]$どっちの時に大きな値になるかを判定し、加算していけば良い．

# 実装

```C++
int solve(){
    int n;
    cin >> n;

    vector<ll> values0(n);
    vector<ll> values1(n);
    vector<ll> dp0(n);
    vector<ll> dp1(n);

    ll a,b;
    REP(i, n){
        cin >> a >> b;
        values0.at(i) = a;
        values1.at(i) = b;
    }

    vector<vector<int>> G(n);

    REP(i, n-1){
        cin >> a >> b;
        a--;
        b--;
        G[a].emplace_back(b);
        G[b].emplace_back(a);
    }
    list<int> q;
    list<int> qdepth;
    q.emplace_back(0); qdepth.emplace_back(0);



    vector<int> res(n);
    vector<int> depth(n, -1);
    vector<int> parent(n, -1);

    int curnode, curdepth;
    while(q.size() > 0) {
        curnode = q.front();
        q.pop_front();
        curdepth = qdepth.front();
        qdepth.pop_front();

        if (curnode >= 0) {
            depth.at(curnode) = curdepth;
            q.emplace_front(-1 - curnode);
            qdepth.emplace_front(curdepth);
            for (auto nextNode: G.at(curnode)) {
                if (depth.at(nextNode) != -1) continue;
                parent[nextNode] = curnode;
                q.emplace_front(nextNode);
                qdepth.emplace_front(curdepth + 1);
            }
        } else {
            ll val0, val1, curval;
            curnode = (-curnode) - 1;
            for(auto child: G[curnode]){
                if(child == parent[curnode]) continue;
                curval = values0[curnode];
                val0 = abs(curval - values0[child]) + dp0[child];
                val1 = abs(curval - values1[child]) + dp1[child];
                dp0[curnode] += max(val0, val1);

                curval = values1[curnode];
                val0 = abs(curval - values0[child]) + dp0[child];
                val1 = abs(curval - values1[child]) + dp1[child];
                dp1[curnode] += max(val0, val1);
            }

        }
    }
    cout << max(dp0[0], dp1[0]) << "\n";
    return 0;
}

using namespace std;
int main() {
    FASTIOpre();
    int q;
    cin >> q;
    REP(qq, q) solve();
}

```

http://codeforces.com/contest/1529/submission/117251269
Hiveで月毎に年度内累積

```
CREATE TABLE test (
   nendo varchar,
   nengetsu varchar,
   num bigint
)
```

```
insert into test(nendo, nengetsu, num) values ('2018', '201903', 1);
insert into test(nendo, nengetsu, num) values ('2019', '201904', 2);
insert into test(nendo, nengetsu, num) values ('2019', '201905', 4);
insert into test(nendo, nengetsu, num) values ('2019', '201906', 8);
insert into test(nendo, nengetsu, num) values ('2019', '201907', 16);
insert into test(nendo, nengetsu, num) values ('2019', '201908', 32);
insert into test(nendo, nengetsu, num) values ('2019', '201909', 64);
insert into test(nendo, nengetsu, num) values ('2019', '201910', 128);
insert into test(nendo, nengetsu, num) values ('2019', '201911', 256);
insert into test(nendo, nengetsu, num) values ('2019', '201912', 512);
insert into test(nendo, nengetsu, num) values ('2019', '202001', 1024);
insert into test(nendo, nengetsu, num) values ('2019', '202002', 2048);
insert into test(nendo, nengetsu, num) values ('2019', '202003', 4096);
insert into test(nendo, nengetsu, num) values ('2020', '202004', 8192);
```

```
select
  nendo,
  nengetsu,
  sum(num) over (partition by nendo order by nengetsu rows between unbounded preceding and current row)
from test
```
Codeforces Round #722 (Div. 2) B. Sifid and Strange Subsequences

http://codeforces.com/contest/1529/problem/B

# 題意
-  整数n個が与えられる
-  連続しなくても良い適当な要素をy個選ぶ．
-  この選んだどの要素の差も、この選んだ要素の最大値以上でないといけない

# 例
- NG: [0,1,2]を選んだとき、最小の差は1であり、最大値の2未満であるため選べない
- OK: [0,0,0]を選んだとき、最小の差は 0 であり、最大値0以上であるためよい
- OK: [-1, 3]を選んだとき、最小の差は 4 であり、最大値3以上である
- OK: [ 0, 3]を選んだとき、最小の差は3であり、最大値3以上である

# こう考えた:
まず、適当な数列a を選び、 これをソートしたとき、$a_0, a_1, ... , a_(n-1)$とすると、隣接する２項間の最小値がすべて$a_(n-1)$以上であるかが焦点になる．これは、最小の差がある値以上であるかの判定を行いたいので、隣接する差の最小値に注目すべきであるからだ．

ところで、2つの値$x、y$があったときに$x, y (x ¥leq y)$が厳密な正の値であるとき、条件を満たせない．なぜなら、$(y - x) < y$であるためである．(2値の差はy以下になってしまう)

次に、2つの値$x,y$が、$ x、y　leq 0 $だったとき、必ず条件を満たせる．なぜなら、2値の差は必ず0以上であるため、最大値が$x, y$ 未満であることはない．

これらを合わせると、以下のことが言える．

- この配列には、厳密に正の整数は1つ以上入らない．
- この配列には、0以下の整数はいくつ入れても良い.

このため、以下の処理を行う．

- 0以下の整数全てをとり、ソートして、隣合う差の最小値を$m$とする
- 整数のうち最小の値があればそれを１つだけ取り、処理を打ち切り答えとする
- 他に取れる数があったとしても、それは条件に引っかかるので取れない
[PHP]ベーシック認証の実装

#はじめに
Railsを学んでいるときにも実装したBasic認証について、PHPでも同様にやってみようと思います。

#実装
やり方はとても簡単です。以下の2つのファイルを作成してください。

- .htaccess
- .htpasswd

次に、以下のようにmainte.phpを作成してください（パスワードの暗号化で使用します）。

```mainte.php
<?php

//パスワードの暗号化
echo(password_hash('password123',PASSWORD_BCRYPT));
//$2y$10$gcXSxuDRPEbIAL5chj/hZOY.xmx7dm56pnZBIktVR.FMuk7AFjLfm
?>
```

もちろん設定ファイルにパスワードをそのまま記載するのはもってのほかです！
そのため、上記のように、password_hashを使用してパスワードの暗号化を行います。
今回は、パスワード「password123」を設定してます。

次に、Basic認証の設定をしていきます。
Basic認証を実装するには、以下のようにAuthType Basicとします。

```:.htaccess
AuthType Basic
AuthName "IDとパスワードを入力してください"
AuthUserFile /Applications/MAMP/htdocs/php_test/.htpasswd
require valid-user

```

次に、.htpasswdに、許可するユーザを登録します。
この際に、先ほど暗号化したパスワードをユーザ名とセットで記載してやります。

```:.htpasswd
admin:$2y$10$gcXSxuDRPEbIAL5chj/hZOY.xmx7dm56pnZBIktVR.FMuk7AFjLfm
```

これで全て設定は完了です。
再度アクセスしてみましょう！以下の画面が出てこれば成功です！

![スクリーンショット 2021-05-31 14.32.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1128031/1d8308af-5466-eadd-0d33-60597253d1e3.png)


#おわりに

Railsの時とは全く違う方法での実装の仕方でした。こうした違いについて気をつけながら学んでいこうと思います！
プログラミング言語を手続き型と関数型、静的型付けと動的型付けで4象限に分類する

![4象限.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427308/b040013f-f4b4-a337-77d9-43ba919719a6.png)


# これは何？
私が所属しているIncrementsではエンジニア採用担当者向けにエンジニアリングに関するお役立ち資料を作成しております。

非エンジニアの採用担当者とエンジニアのコミュニケーションをより良いものにするため、採用担当者向けに作成しています。
今回作成したものが、Qiita内に同内容の記事が見当たらなかったため、私が資料を作成するに当たり学んだこと投稿します。

※本資料作成時の対象読者は採用担当者のため、非エンジニアにもわかりやすく理解をしてもらうため、表現に語弊を含む場合があります。気になる箇所があればコメント、編集リクエストをいただけると幸いです。

#目次
[1.手続き型言語とは？](#1-手続き型言語とは？)
[2.関数型言語とは？](#2-関数型言語とは？)
[3.静的型付け言語とは？](#3-静的型付け言語とは？)
[4.動的型付け言語とは？](#4-動的型付け言語とは？)
[5.プログラミング言語の4象限](#5-プログラミング言語の4象限)
[6. まとめ](#6-まとめ)
[7. 参考記事](#7-参考記事)


#1. 手続き型言語とは？
手続き型言語とはコンピュータに命令したい処理を順番通りに記述する言語です。
例えば卵焼きを作るという結果を表現する際に、以下の用に手順を順番通りに記載するようなものです。

```rb:例(Ruby)
egg = Egg.new
crack(egg) # 卵を割る
mix(egg) # 卵を混ぜる
harden(egg) # 卵を焼く
egg # 卵焼きになっている
```

実世界の考え方に似ているため、コードが記述しやすいという特徴があります。
代表的なものとしてはJavaやRubyなどがあります。

#2. 関数型言語とは？
関数型言語とはコンピュータに命令したい処理に関数を用いた記述を推奨された言語です。
ここでは関数についての詳細な説明はしないため、例を参考に大枠を掴んでいただければと思います。
例えば、卵焼きを作る際に以下のような考え方をします。

```elixir:例(Elixir)
omlet = egg |> crack |> mix |> harden # 卵から卵焼きを生み出す
# omlet = harden(mix(crack(egg))) と同じ
```

手続き型言語を作業の命令だとすると、関数型言語は値の変換ルールをただ、定義して、それを組み立てて目的のものを生み出す、というような考え方に近いです。

関数という形で処理を定義するため、文脈として読みやすい、また、状態（&副作用）を持たないため不測挙動をプログラムがしにくい、という特徴があります
代表的なものとしてはHaskellやScalaなどがあります。

#3. 静的型付け言語とは？
静的型付け言語とは変数などのデータ型の宣言が必要なプログラミング言語です。

卵焼きを作る際の卵の選定時に、生卵でなければならない、という定義をするのが静的型付け言語です。

1. 卵を割る（ここの卵は絶対に生卵）
1. 卵を混ぜる
1. 卵を焼く

データ型の宣言が必要なので、手間はその分かかりますが、リリースする前にエラーやバグに気づきやすいという特徴があります。
代表的なものとしてはSwiftやTypeScriptなどがあります。

#4. 動的型付け言語とは？
動的型付け言語とは変数などのデータ型の宣言が不要なプログラミング言語です。

卵焼きを作る際の卵の選定時に、生卵かゆで卵かなど卵の状態を定義をせずにプログラミング言語に判断を任せるのが動的型付け言語です。

1. 卵を割る
1. 卵を混ぜる
1. 卵を焼く

データ型の判断はプログラミング言語に任せるため、仮にゆで卵が混入していたとしても割ってみるまで気づけないといったことが起こりえます。
データ型の宣言が不要なので、記述量が少なく済みますが、リリース後に実際にプログラムを実行してみないとエラーやバグに気づけないという特徴があります。
代表的なものとしてはJavaScriptやPythonなどがあります。

#5. プログラミング言語の4象限
各言語をこれまで説明した各分類に図示したものが以下
※本記事の読者がこよなく愛する言語が含まれてなければごめんなさい...

![4象限.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427308/d29c10c5-2622-9f5e-7c41-9d901d475ff8.png)

JavaScriptやSwift、TypeScriptは関数型プログラミングもできるため、境目に近いところに配置しています
※この言語はここじゃないよね？というご指摘があればコメントください！

## 関数型言語×動的型付け言語
- Elixir
- Erlang

## 関数型言語×静的型付け言語
- Haskell
- Scala
- OCaml

## 手続き型言語×動的型付け言語
- JavaScript
- Python
- Ruby
- PHP
- Julia
- Perl

## 手続き型言語×静的型付け言語
- Swift
- TypeScript
- Rust
- Go
- Objective-C
- Kotlin
- Java
- C
- C++
- C#

#6. まとめ
この分類で以下のようなことが言えるのではないでしょうか？

- 4象限の図を把握すると、同じ象限に属する言語同士は特徴が似ているためキャッチアップしやすい？
- その次は横の象限、その次が縦の象限の順に広げていくとよさそう

特定の言語を習得し、つぎに何の言語を学ぼうかと考える際の参考になるかもしれません！

#7. 参考記事

https://qiita.com/wann/items/16920b070dc0483f152a

https://qiita.com/toryuneko/items/c023031b61886cae2a99

https://qiita.com/nokonoko_1203/items/1cbce5566a6ea0a4029b

https://qiita.com/stkdev/items/5c021d4e5d54d56b927c
VBAの配列とUBoundによる要素数について

# Sample Code

```vba:Sample
Dim list(3) As Long
list(0) = 1
list(1) = 2
list(2) = 3
list(3) = 4
Dim i As Integer
For i = 0 To UBound(list)
    list(i) = list(i) * list(i)
Next i

↓

list(0) : 1
list(1) : 4
list(2) : 9
list(3) : 16
```
# 他の言語と根本的に異なる（Different way of thinking）
<strong>VBAのループに「ー１」は必要ない。</strong>仕様を下記に記述する。
You <strong>don't need a "-1"</strong> in a VBA loop. The specifications are as follows.

# ①&emsp;配列に定義したアイテム数よりも<strong>１つ多くアイテムが生成される</strong>
下記のように記述した場合、アイテムは４個生成される。つまり、<strong>０～３</strong>のキーが生成される。
(1)&emsp;One more item will be generated than the number of elements defined in the array.
If you write as follows, 4 items will be generated. So, That is, <strong>keys 0 to 3</strong> are generated.

```vba:List
Dim list(3) As Long
↓
[list(0), list(1), list(2), list(3)]
```

# ②&emsp;<strong>UBound</strong>は定義されている数よりも<strong>１つ少ない数を取得する</strong>
先ほどの①の変数「list」のアイテム数を取得すると３となる。つまり、<strong>キーの最大値を取得</strong>する。
（UBound：UpperBoundの略）
(2)&emsp;<strong>UBound</strong> is one less than the defined number.
If you get the number of items in the variable "list" in (1) above, you will get 3. That is, get the <strong>maximum value of the key</strong>.

```vba:UBound
UBound(list)
↓
3
```
# ③&emsp;配列の定義にUBoundを使用したい場合、<strong>ReDimを使う</strong>
なお、ReDimは再定義という意味であり、アイテム数を途中で変更することも可能。
(3)&emsp;If you want to use UBound to define the array, <strong>use ReDim</strong>.
ReDim is a redefinition, and it is possible to change the number of items on the way.

```vba:ReDim
Dim list(3) As Long
ReDim anotherList(UBound(list)) As Long
ReDim anotherList(10) As Long
```

# これを書いた理由（Why i wrote this）
どこにも分かりやすく書いてないから。
Because, It is not written anywhere in an easy-to-understand manner.
どうせまた検索することになるから。
Because, I'll look for it again.

# 付録
Integer型は「-32,768 ～ 32,767」であり、すぐにOverFlowする。
無限ループ回避には適しているが、ビックデータを扱うならLong型を使うと良い。
Good for avoiding infinite loops, but use the Long type when dealing with big data.
フロントエンド関連ツールの理解

# 概要

開発時に目にしたフロントエンドの関連ツールをまとめる。

# node.jsのバージョン管理ツール

node.jsのバージョンを管理するツール

いくつかあるが日本人が作成したものもある

## nodebrew

[hokaccha/nodebrew](https://github.com/hokaccha/nodebrew)

## nvm

マルチプラットフォーム対応なのでwindowsでも使える

[nvm-sh/nvm](https://github.com/nvm-sh/nvm)

## n

[tj/n](https://github.com/tj/n)

そのほか色々ある

# node.jsのパッケージ管理

node.jsにインストールするパッケージを管理するツール

二種類あるが互換性あるので併用してもいいそう。

これを使ってインストールされたパッケージはpackage.jsonというファイルに表記され、json形式で管理されている。（pipのrequirement.txtと似ている。）

## npm

## yarn

こっちの方が処理が高速

[yarnとは - Qiita](https://qiita.com/akitxxx/items/c97ff951ca31298f3f24)

## 違いについて

[npmとyarnとpnpmの違い2021](https://zenn.dev/hibikine/articles/27621a7f95e761)

# jsのフレームワーク

## vue

バージョンが2と3があるので注意

[Vue CLI の変更点・使い方(vue-cliから@vue/cliにアップデート) - Qiita](https://qiita.com/Junpei_Takagi/items/603d44f7885bd6519de2)

## react

## 違い

### テンプレート言語

`Vue.js`: HTML
htmlとjs（とcss）を分離して記述する

`React.js`: JSX

jsの中にhtmlを記述する

[JSXが実はベターな解だったのではないか？｜erukiti｜note](https://note.com/erukiti/n/n6f673021469e)

### 書き方の違い

[react.js(next.js)とvue.js(nuxt.js)の違いをソースで確認してみましょう - Qiita](https://qiita.com/airix/items/df341f0f24c05ecd8aa7)
Windows 10の設定だけでマウスポインターを目立つデザインに変える

最近はモニタが高精細化したこともあって、マウスポインターを見失いがちで困るんですよね。これを目立たせるものに変えるには、好きな.curファイルを入手してマウスのプロパティで変更するのが一般的かと思いますが、大きさや色だけであればWindows 10の設定の「簡単操作」でカスタマイズが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536630/f8237a1e-9ec1-dbf9-3300-831c46d68991.png)

サイズ3、金色にするとこんな感じ。目立つ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536630/4dc67eae-1a1a-99cf-6557-c0ce85dbfd8f.png)

Windows 10の標準機能だけで実現できるので、会社などファイルの持ち込みが制限されている場合でも使えるのが良いですね。
例外と例外処理について

# 例外と例外処理について

## 例外
プログラムはコンパイルが成功しても、実行時にエラーが発生する場合があります。
Javaでは実行時に発生したエラーを**例外**と呼びます。
かつ、例外が発生することを**例外がスローされる**といいます。

## 例外処理
例外がスローされた際は、プログラム側で例外処理を記述していない場合は、
**プログラムが強制終了**します。

以下のコードを観てみましょう。


```
public class Main{
    public static void main(String[] args){
        int num = {20, 40, 60};

        for(int = 0; i < 4; i++){
            System.out.print(num[i]);
        }
    }
}

```

このコードでは、3回目のループまでは出力されます。

しかし、4回目の出力で配列の要素外にアクセスしているので、例外がスローされます。

```
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
index 3 out of bounds for length 3
        at Main.main(Main.java:5)

```

この際、例外処理を記述しておけば、プログラムは強制終了することはなく、実行を継続出来ます。

## Javaで扱われる例外クラス

Javaで扱われる例外クラスをいくつか紹介します。


・ArrayIndexOutOfBoundsException ⇨ 不正なインデックスで要素にアクセスしようとした場合に発生。
・ClassCastException - 参照変数において間違ったキャストを行った場合に発生。
・ArithmeticExcpetion - 整数をゼロで徐算した場合に発生

## まとめ
・Javaでは実行時に発生したエラーを例外と呼ぶ。
・例外が発生することを「例外がスローされる」と呼ぶ
・例外の種類によって例外クラスが用意されている。
ポートフォリオ製作中、セキュリティ対策について学んだこと

# はじめに
某マッチングアプリにて”SQLインジェクション”世間が賑わっていた際に、自分のRailsで作ったポートフォリオは問題ないだろうかと思い、学習を兼ねて色々調べた際の備忘録となります。

# 参考文献

https://railsguides.jp/security.html

# セッションハイジャック
`概要`
ログイン情報が入ったcookieを盗むことで、そのユーザーになりすましログインができる
`対応策`
SSLサーバ証明書を取得しHTTPSでの通信を行えるように対応。
また、HTTPでアクセスしたユーザーに対しては、HTTPSにリダイレクトするよう設定。

```conf:nginx.conf 
server {
  listen 80;
  server_name  _;
  return 301 https://$host$request_uri;
}
```

# クロスサイトリクエストフォージェリ (CSRF)
`概要`
imgのソース属性に、`"http://www.webapp.com/project/1/destroy"`などを埋め込み、www.webapp.comにログイン状態のユーザーがその画像を閲覧すると、projectの1番が削除されてしまう
`対応策`
DBを書き換える動作などにはGETを使用しないことで対応

また、Railsにはデフォルトで、Railsで生成されるすべてのフォームとAjaxリクエストに対しセキュリティトークンが自動的に含まれるため、外部から送信が来た場合、そのトークンがマッチしない判定になるため例外が発生する。

# クロスサイトスクリプティング (XSS)
`概要`
サイト上のフォームにスクリプトタグなどを埋め込み、悪意のあるコードを実行させる攻撃
`対応策`
Railsではデフォルトでエスケープする仕様のため、意図的に解除していない限りは問題なし
しかし、改行の反映はデフォルトのままではできないため、以下内容にて対応

```ruby
simple_format(h(schedule.content))
```

# SQLインジェクション
`概要`
フォームなどで、悪意のあるSQL文を打つことで、データを不正に入手したり削除したりする攻撃
`対応策`
RailsではActiverecordを使用して実行していれば、Rails側で対策をしているので問題なし。
しかし、whereメソッドでは手動でエスケープもしくは、配列やハッシュで文字を渡す対応策は必要。

```sql
--検索フォーム入力内容
" a' OR WHERE employee_id = 1 "

WHERE (title LIKE '%a\' OR WHERE employee_id = 1%') 
-- 自動的にバックスラッシュが'についている
```