OmniAICreator/Qiita-1.07M huggingface dataset:
C＃を使用してWord文書にワードアートを挿入する方法

##C＃を使用してWord文書にワードアートを挿入する方法

##背景
Word文書にワードアート効果を追加すると、文書のレイアウトをより美しくなります。 特定な内容を強調するか、強い印象を残したいするか、ワードアートを選択なら人に閃いた感じを与えることができます。この記事では、主にC＃および***[Spire.Doc](https://www.e-iceblue.com/Download/download-word-for-net-now.html)***コンポーネントを使用してWord文書にワードアートを挿入する方法を紹介します。

***[Spire.Doc](https://www.e-iceblue.com/Download/download-word-for-net-now.html)***は、ワードアートを含むさまざまな形状タイプをサポートしています。これらのタイプは、ShapeType列挙型で探すことができます。次の例では、2つのワードアートをWord文書に追加することを展示します。

***ワードアートを挿入する詳細な手順***

1　Word文書を新しく作成します
```　Document doc = new Document();```

2　文書にセクションと段落を追加します
```Section section = doc.AddSection();
Paragraph paragraph = section.AddParagraph();```

3　図形を段落に挿入し、図形の種類をワードアートとして指定します。ワードアートのテキスト、位置、塗りつぶしの色、ストロークの色を設定します
```ShapeObject shape = paragraph.AppendShape(120,30,ShapeType.TextWave);
shape.WordArt.Text = "ハーロウ";
shape.VerticalPosition = 80;
shape.HorizontalPosition = 170;
shape.FillColor = Color.Yellow;
shape.StrokeColor = Color.SeaGreen;
```
```shape = paragraph.AppendShape(120,30,ShapeType.TextSlantUp);
shape.WordArt.Text = "ワールド";
shape.VerticalPosition = 150;
shape.FillColor = Color.Yellow;
shape.StrokeColor = Color.Red;
```

4　文書を保存します
```doc.SaveToFile("ワードアート.docx", FileFormat.Docx2013);```

***結果は以下の通りです：***
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/7e594384-12c7-cd7b-4f8f-6e736f0a37bb.png)


##コード一覧
```
using System.Drawing;
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;

namespace WordArt
{
    class Program
    {
        static void Main(string[] args)
        {
            //Word文書を新しく作成する
            Document doc = new Document();
            //文書にセクションと段落を追加する
            Section section = doc.AddSection();
            Paragraph paragraph = section.AddParagraph();

            //図形を段落に挿入し、図形の種類をワードアートとして指定する
            //ワードアートのテキスト、位置、塗りつぶしの色、ストロークの色を設定する
            ShapeObject shape = paragraph.AppendShape(120,30,ShapeType.TextWave);
            shape.WordArt.Text = "ハーロウ";
            shape.VerticalPosition = 80;
            shape.HorizontalPosition = 170;
            shape.FillColor = Color.Yellow;
            shape.StrokeColor = Color.SeaGreen;

            shape = paragraph.AppendShape(120,30,ShapeType.TextSlantUp);
            shape.WordArt.Text = "ワールド";
            shape.VerticalPosition = 150;
            shape.FillColor = Color.Yellow;
            shape.StrokeColor = Color.Red;

            //文書を保存する
            doc.SaveToFile("ワードアート.docx", FileFormat.Docx2013);
        }
    }
}
```
以上です、けっこう簡単でしょうね、最後まで読んでいただきありがとうございます。
趣味と~機械学習~プログラミング　アイデア

##したいこと、すべきこと、できること
何をやるにもモチベーションがないと進まない。無理なく、前向きにアウトプットできるように上記が重なる範囲で取り組んでみたいアイデアを書き連ねようと思う。

####したいこと
趣味の範疇：お酒(ワイン、ビール、日本酒)、アイドル・日本語ラップ鑑賞、オンラインゲーム(FORTNITE、APEX)

####すべきこと
新規性があること、少なからずQiitaやgoogleで調べて既報でなさそうこと
誰かしらに面白いと思ってもらえそうなこと(感性)

####できること
pythonコード初心者
kaggleやNishikaでサブミットはできる
スクレイピング勉強中


#アイデア目次
###日本のワイン生産地とボーリング調査の紐づけ解析
###好きなアイドル・ラッパーのメッセージを読み解く
###フォートナイトの戦績を自己管理するデータ収集

基本的に人がやってきたコードを流用して、自分の興味に対して適応させながら勉強してできることをどんどん増やしていきたい。
ASTERIA WARPでAzure CosmosDBにアップロードする

業務でAzureをよく使う関係で，[Microsoft Azure アダプター](https://www.asteria.com/jp/warp/feature/option/microsoft-azure)を導入しています。リレーショナルにしづらいデータを格納したり，Azure Searchの検索対象にしたりするのに便利です。しかしながら，ASTERIA WARPでの実例があまり見当たらないのでここに書いてみることにしました。

## CosmosDB コンテナー作成
テスト用にコンテナーを作成します。

- Container id：Test
- Partition key：/type（テストなので何でもよいのですが，今回は type をパーティションキーにします）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/73c2f97b-7e1b-68de-d55a-eb37d047166e.png)

## フロー作成
今回の記事に使うフローを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/c4851505-38e4-fd2d-ec41-221edb05d3d4.png)

CSVから顧客データ（架空）を読取り，CosmosDBにアップロードするだけのシンプルなフローです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/3e1f63f7-69bf-7a58-503c-64b161d01752.png)

## CSVの準備
CSVは[個人情報テストデータジェネレーター](https://testdata.userlocal.jp/)で作成しました。
idとして使うため，「コード」列は自分で追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/e6e2e202-3c7d-375f-495f-458e70ff5a9e.png)

CSVを読み取るためのFileGetは以下のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/92dee97a-5c90-41c1-e398-8ac03aa8ef16.png)

## ParameterListに変換
マッパーを追加して，以下のように設定します。

- ループを開始：はい（今回は1行ずつアップロードします）
- ストリーム型：ParameterList（RecordやCSVのままだとJSONに変換した時に配列になり，エラーが発生します）
- フィールド名：id（CosmosDBのid）
- フィールド名：type（CosmosDBのパーティションキー）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/4957d17a-e29f-d000-0734-9f251c23827c.png)

以下のように連結します。

- id：コード（コードをCosmosDBのidとして使います）
- type：customer（今回は固定の文字列を使います）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/28fd5df4-e58f-23f4-f0a2-607347beff6a.png)

## JSONに変換
JSONEncodeを追加し，以下のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/5557836f-42ba-6116-accd-1434ab0a3054.png)

以下のようなJSONテキストになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/587e4483-c124-fa8c-ccff-db85671241b4.png)

## CosmosDBにアップロード
AzureDocumentDBPutを追加し，以下のように設定します。

- コネクション情報，データベース名（自分の環境を使用）
- コレクション名：Test
- 実行する処理：Create
- パーティションキー：["customer"]（typeと同じ値。行によって変えたい場合は変数やマッパーを使用）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/97ca525d-4582-c320-23be-17dbfc33541a.png)
### パーティションキー
ポイントはパーティションキーで，大括弧と引用符で囲む必要があります。これを設定しないと以下のようなエラーが発生します。

空白の場合
`The partition key supplied in x-ms-partitionkey header has fewer components than defined in the the collection`
customerだけの場合
`Partition key customer is invalid`

## 実行結果
10件のデータをアップロードすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102503/06cda9f1-24f1-4a34-e5f0-494011434827.png)
RedhatOS設計 ipv6無効

https://tech-lab.sios.jp/archives/10660

grubの設定変更パターン
と
sysctl.confのパターン両方試してみました。

ip -aコマンドで変更前と変更後を確認。


結論
どっちも同じ部分が無効になるだけでした。
よって好きなほうに記載するでいいと思います。
【2021年度】未経験エンジニア転職

2021年度の転職活動がやっと終わったので総括と未経験エンジニア転職の実態をご報告したいと思います。   
##私の略歴   
大学（日東駒専）中退
↓
フリーター
↓
アウトソーシング会社に就職
↓
地方の町工場に転職
↓
退職し地元の職業訓練校に入校（半年）

#結果から先にご紹介
就活期間（約2ヶ月程度）   
エントリー数:　28社
面接:　7社
内定: 1社
   
##未経験からエンジニア転職の実態
結果未経験からエンジニア転職はかなり厳しいです。理由をご説明します。   
***
###エンジニア転職は経験がものを言う
これが最も言いたいことです。私は幸い身内からの業務委託経験が少々あり、多少のアドバンテージにはなりましたがそれでも前職が全く関係ないのでほぼ未経験者として扱われました。エンジニア転職は実績と経験が本当に重要なんだと身をもって知らされました。   
エンジニアは売り手市場だから簡単に転職できるのでは？   
**それ間違えです。**   
まだそう思っている方は非常に危ないです。悪徳な企業にカモられる可能性があります。   
先ほども言った通り売り手市場は**実務経験者**です。未経験社は圧倒的に**買い手市場**だと思ってください。   
***
###ポートフォリオが評価されにくい
未経験者の場合ポートフォリオor資格を用意して就活するのはもはや定番となっていますが、定番が故に競争が激化し質の高いポートフォリオを要求される傾向にあると思います。   
スクール等のカリキュラム内で作成した成果物は提出するともはやマイナス評価になることもあるとか・・・   
つまり他者との差別化がないとせっかく作っても無駄になるケースもあるので要注意です。   
**あとデプロイやGithubは必須要件です！**
***
###年齢の壁
周りの人を観察していてこれもあったと思います。これはエンジニアに限らずどの職業でもそうだと思います。   
特に35歳以上の方は相当な覚悟を持って転職した方がいいと思います。
今20代未経験で転職しようとしている人たちが山のようにいます。
その人たちとどうやったら勝てますか？   
ちなみに私は今ギリギリ20代です。 
***
###情弱を待ち構えているのはS○S企業   
自社開発企業だと思って応募したら実はS○S企業だったと言うこともよくありました。
別にS○S企業が良くないわけではないと思います。
最近はS○S企業でも環境や待遇が見直されリモート可の案件も増えていると聞きました。
S○S企業でも個人のスキルアップを考慮してくれる良さそうな会社はありました。   
ただ先ほどのように未経験者をカモにするS○S企業も一定数存在します。
中には研修期間と称して家電量販店や電話対応のアルバイトに低賃金で派遣するケースもあります。研修期間が終われば案件に参加させてもらえると言う保証はどこにもないので絶対にやめた方がいいと思います。   
***
##まとめ   
**1、エンジニア転職で重要なのは実務経験、今未経験者は買い手市場である。**   
**2、ポートフォリオの作り方を工夫する必要がある。必ずデプロイしよう。**  
**3、35歳以上の人は覚悟を持って転職した方がいい。**   
**4、情報収集を怠るとカモにされる。**   
上記のことを踏まえた上でそれでもエンジニアになりたいと思う強い気持ちがある人は希望の会社に転職できる可能性があると思います。私も希望通りの会社に転職できました。
やはり未経験者の実力証明はポートフォリオしかないと思います。
私も独学でWEBアプリを作成しそれが最終的に評価されました。   
また先述の情弱はカモられると言う話と共通しますが、   
受け身で勉強をするタイプ（先生の言うことを聞くだけ）の人にはエンジニアは向いていないと思います。
当たり前ですがある程度入社難易度のある企業は面接でもそういうところは見てきます。
自ら興味を持ち、調べて学ぶ力がないと就活も就職してからも厳しいと思います。
朝会 フリートークの成功事例 今だけ 無料で 公開 しております！

### 開いちゃいましたね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58330/3dc628f2-7858-e14e-d741-34e7f0529e87.png)
ずっと無料公開してますので気にせず見ていってください。

## この記事はチームの朝会でフリートークをやっていてうまくいった事例について解説しています

フリートークって適当に喋ってワイワイやるだけじゃないの・・・？
うまくいくって言われてもねぇ・・・

そう思っている方にだけ、特別に、限定で、真実をお伝えします・・・！

## フリートークは何のためにやるんだろうか

なくてもいいけど、あると嬉しい理由はこんなところでしょうか

- チームメンバーの人となりが知れる
- チーム内で共通の話題が作れる
- 業務内における息抜き

主にチームビルドの観点で行うことが多いかなと思います。

## じゃあやろう！用意してきてね！盛り上げてよ！よろしくね！

:finnadie: < お前らなんで盛り上がらんのじゃい！

フリートークのアンチパターンがそこそこあるみたいです。
一体何なんでしょうか。気になりますね。
説明しますね。

#### :one: TODOにしない

トークする人が準備し忘れ、スキップして、話す内容考えて、次回までのTODOにして
とやっていくことで義務感が生まれてしまいます。
そもそも「なくてもいいけどあると嬉しい」くらいのものなので、
ガッツリ仕事に組み込まれることは苦しくなりやすいです。

#### :two: フリーテーマで話しあわない

フリートークでフリーテーマNGってどういうことだ！　なんですが、
「今日はこの話題について、みんなで話しましょう！」としない方が良いです。
チームメンバーの数にもよりますが、5人いたとして各3分話したら15分、朝会でやるには少しFATですね。
絶対にやっちゃダメ！というわけではないですが、

- 事前にテーマを伝えて内容考えてもらう
- 前編後編などに分けて朝会で収まるようにする

という工夫が必要になるので少し難しい印象はあります。

#### :three: 業務が逼迫しているなら無理してまで実施しない

そもそもやる余裕があるのか？ということは考えてみるべきです。
プロジェクト終了が差し迫っていたり、遅れが出ていて時間削るべきタイミングであれば、
思い切って取りやめすることも選択しましょう。
焦りのある中で少しでもチームの雰囲気を良くするために・・・！とやっていても、
「忙しいのにこんなことしていていいのか？」という意見が出たら思い切ってやめたほうが良いです。

### :warning: それではうまくいく方法をお教えします！ :warning:
### ↓
### ↓
### ↓
### :bulb: それはこんな方法だったのです・・・！ :bulb:
### ↓
### ↓
### ↓
### :star: :star: :star: こちらからご覧ください :star: :star: :star:
### ↓
### ↓
### ↓
## やってみてうまく行った要因

### :innocent: 話す人、内容を挙手制にする

弊チームではNotionを利用しており、このような感じで
__話す内容をタイトル、ジャンルに入れて起票__
ということだけ事前準備でやってもらっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58330/4fe3a043-212e-4ad6-3d18-5f45b9abb2ff.png)

他のツールでも似たような感じでやってみてください。
この時点でやることは
「__誰が__」「__何について話すか__」を積んでいくことです。
施策をやり始めたときはストックされにくいので、リーダーが率先して積んでいきましょう。
ムードメーカーな人に直接お願いするでも良いですね。
リーダーはストックが空にならないように気をつけましょう。

### :hugging: 時間がある時に話す

朝会で実施すると、共有が多かったり進捗相談がたくさんあったりで時間がギリギリになることもあります。
そういうときはスキップしましょう。必ずやる必要はないです。
話す順番については何でも良いですが、古いもの順番に話していくで運用しています。
「みんな〜！どれが聞いてみたいかな〜？」というやり方だと誰も反応してくれない事が多いので、
機械的に進めていくでも良いと思います。

### :blush: 話しながら議事録を作成する

話す内容は決まっているけど、資料だったり文字に起こすの、面倒だなーという心配はいらないです。
話しながら他の人が文字に起こしていきます。議事録とは言わないかもですが。
モニターを共有しながらであれば、検索して画像映すとかもいいですね。
イメージこんな感じで、話しながら書いていくのでこのくらいラフな内容になってます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58330/0c30b9fe-9cfb-c592-1fbb-eb6a4a98906d.png)

議事録最近書いてなくて鈍ってないかなーって人だったり、新卒入社で議事録慣れしようという人に書いてもらうでもいいですね。
特に立候補なければリーダーが書くで良いと思います。
ガッツリ話したい内容があるから先に書いちゃう！でも、もちろん大丈夫です。

## 大事なのは 『思いついた時にやること』 と 『負担にしないこと』
やらなきゃとなると義務感プレッシャーで辛くなるけど、
やりたいと思ったときは簡単に行動できますよね？
きっかけをそのまま発展させず、でも残しておくという感じです。
いざ取り出して始める時も、そんなに完成度は求めなくていいです。
量をこなすことで自然と質は高まります。
そういうイメージでいれば、継続しやすいです。

## 結局成功したのか？

__わかりません！__

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58330/9398eb25-debf-2b4c-b895-8be4ac514a4c.png)

ただ、現時点でトーク内容をまとめた記事を数えたら200件を超えていたので、
現時点では好評のはずです！

皆さんも是非試してみてください！
DockerFileの書き方 メモ

Dockerについて勉強しようと思ったので、メモがてらに書きます。

# Dockerfileとは
このファイルに書いた通りの環境が構築できるような感じです。
どんなイメージをベースにするのか、走らせたいコマンドはあるかなど、ここでちゃんと指定しないと上手く動かなかったり、コンテナごとの設定が変わったりします。

## どうやって指定するのか
主に使われる命令コードは以下のリストです。

```
FROM:	ベース（親）画像を指定します。
LABEL:	メタデータを提供します。 メンテナ情報を含めるのに良い場所です。
ENV:	永続的な環境変数を設定します。
RUN:	コマンドを実行してイメージレイヤを作成します。 パッケージをコンテナにインストールするために使用されます。
COPY:	ファイルとディレクトリをコンテナにコピーします。
ADD:	ファイルとディレクトリをコンテナにコピーします。 ローカルの.tarファイルをアンパックできます。
CMD:	実行中のコンテナにコマンドと引数を提供します。 パラメータは上書きできます。 CMDは1つだけです。
WORKDIR:	あとに続く説明の作業ディレクトリを設定します。
ARG:	ビルド時にDockerに渡す変数を定義します。
ENTRYPOINT:	実行中のコンテナにコマンドと引数を提供します。 引数は存続します。
EXPOSE:	ポートを公開します。
VOLUME:	永続データにアクセスして保存するためのディレクトリマウントポイントを作成します。
```

`docker build`を実行するとこのファイルで指定した命令通りにコンテナが作られます。
RedhatOS設計 history

https://qiita.com/bezeklik/items/56a597acc2eb568860d7

どこかの案件で、historyコマンドを実行したら、日時が表示されて、
Redhatもデフォルト設定変更されたんだって思っていたら自分で設定しないといけないんだね(笑)
Pythonがいくら便利だからってあんまり雑に使っていると痛い目を見る～pandas編～

　Pythonは普通に書いてるだけで勝手に読みやすくなる文法に，型キャストや引数もいろいろ良しなに扱ってくれる便利な言語ですが，だからといって適当に使っていると変なところでハマるよというお話．

## この記事で扱うデータ

```text:sample.csv
Height,Weight,Gender
161.6124725,65.98017883,Female
150.4265289,59.49276352,Female
172.5548706,82.67674255,Male
164.2229767,67.56816864,Female
185.3570404,99.14295197,Male
178.6737518,80.50052643,Male
184.1519165,91.4691925,Male
169.6814117,68.50371552,Female
171.8485107,87.14485931,Male
```
以上のようなcsvファイルを例に扱います．こいつがなかなか曲者なんだ...

## ケース1：DataFrameの行抽出

　DataFrameは条件を指定して行を抽出できます．しかし...

```py:input
df1[df1.Gender == 'Male']
```

```text:output
	Height	Weight	Gender
0	NaN	NaN	NaN
1	NaN	NaN	NaN
2	NaN	NaN	Male
3	NaN	NaN	NaN
4	NaN	NaN	Male
...	...	...	...
995	NaN	NaN	Male
996	NaN	NaN	NaN
997	NaN	NaN	NaN
998	NaN	NaN	NaN
999	NaN	NaN	Male
1000 rows × 3 columns
```

　...なんじゃこりゃ．よく調べてみると，

```py:input
type(df1['Height'])
```

```text:output
pandas.core.frame.DataFrame
```

本来であれば，これはSeries型になるはずです．[参考][df-series]

[df-series]:https://note.nkmk.me/python-pandas-dataframe-series-conversion/

### 解決策

　DataFrameを作り直すと正常に動作しました．

```py:input
ans = pd.DataFrame({'Height': df1['Height'].values.reshape(1000),
                    'Weight': df1['Weight'].values.reshape(1000),
                    'Gender': df1['Gender'].values.reshape(1000)
                   })
ans[ans['Gender'] == 'Male']
```

```text:output
	Height	Weight	Gender
2	172.554871	82.676743	Male
4	185.357040	99.142952	Male
5	178.673752	80.500526	Male
6	184.151916	91.469193	Male
8	171.848511	87.144859	Male
...	...	...	...
989	165.647507	79.347435	Male
992	170.756546	82.422096	Male
994	180.842758	95.315422	Male
995	183.990356	95.574455	Male
999	186.798447	93.485558	Male
514 rows × 3 columns
```



## ケース2：Seabornでのプロット

　Seabornでのエラー．

```py:input
sns.scatterplot(data=df1, x='Height', y='Weight')
plt.show()
```

```text:output
----> 1 sns.scatterplot(data=df1, x='Height', y='Weight')
      2 plt.show()
...
ValueError: If using all scalar values, you must pass an index
```

ドキュメントにも載っているシンプルな書き方ですが，変なエラーが出ました．どうやら辞書型からDataFrameに変換するときにインデックス周りで出るエラーのようで，実際エラー文の途中にそのような処理をしている箇所が書かれていました．

###　解決策

```py:input
plt.scatter(df1.Height.values, df1.Weight.values)
plt.show()
```

![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601748/75065dfa-b9e9-e56a-2302-de043682093d.png)

valuesメソッドでndarray型にしてやれば大丈夫．でもラベルをサクッと貼れないのは不便...


## まとめ

　一時間強ハマってしまいました．自分が調べた限りでは根本的な解決策は見つかりませんでしたが，時間がある時にでもissueを漁ってみようかと思います．
cssをimportしたコンポーネントのjestを実行する

Vue.jsのコンポーネントで、cssをimportしているとjestで転けてしまったので、jest.config.jsに設定を入れて解消します。

エラーの内容はこのような感じです。

```sh
Test suite failed to run

Jest encounterd an unexpecter token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
...
```

いろいろと調べたり試したりしたのですが、最終的に以下の方法でうまくいきました。

`jest-css-modules`をインストールします。

``` sh
npm install -D jest-css-modules
```

ルートの直下に`jest.config.js`を作成し、以下を記述します。

``` js
module.exports = {
  moduleNameMapper: {
    "¥¥.(css|less|scss|sss|styl)$": "<rootDir>/node_modules/jest-css-modules"
  }
}
```

今回使ったのはjest-css-modulesですが、たくさんこれ系のモジュールはいくつかあるみたいなので、自分のプロジェクトに合ったものを使うと良いと思います。

終わり！
Databricks AzureにおけるReposの利用(実践編)

本書は、[Repos Git 統合の場合 \- Azure Databricks \| Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/databricks/repos)の手順を説明したものです。

:::note info
こちらで紹介している方法は、認証にパーソナルアクセストークンを使用する方法です。これ以外に、Azure Active Directoryを使用することもできます。
:::

# Azure DevOpsのセットアップ

[Authenticate with personal access tokens](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page)の手順に従い、Azure DevOpsのプロジェクトにアクセスするためのパーソナルアクセストークンを作成します。

1. AzureポータルからAzure DevOpsにアクセスします。
1. **My Azure DevOps Organizations**のリンクをクリックします。
1. Organizationがない場合には、Organizationを作成します。
1. `dev.azure.com/<Organization名>`にアクセスします。
1. Projectを作成します。
1. Projectにアクセスし、右上の人の形のアイコンをクリックし、メニューを展開します。
1. **Personal access tokens**を選択します。
1. **+ New Token**をクリックします。
![Screen Shot 2021-11-30 at 10.41.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/bdc1dfb5-7465-0f02-60e0-ed07799c50e6.png)
1. Scopeを設定の上、トークン名を入力して**Create**をクリックします。
![Screen Shot 2021-11-30 at 10.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1243feba-1352-d416-8606-09c779f9ada7.png)
1. 表示されるトークンをコピーしておきます。

# Azure Databricksの設定

1. サイドメニューの**Settings > User Settings**を選択します。
1. **Git Integration**タブを開き、以下の内容を指定します。
    - **Git provider**: Azure DevOps Services (personal access token)
    - **Git provider username or email**: Azureのユーザーアドレス
    - **Token**: 上のステップでコピーしたパーソナルアクセストークン
![Screen Shot 2021-11-30 at 10.51.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f1356824-1683-a60e-650d-b288c36a375d.png)

1. **Save**をクリックします。
1. Azure DevOpsのReposをクリックし、**Clone to your computer**に表示されるURLをコピーしておきます。
![Screen Shot 2021-11-30 at 10.58.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b420ba1c-398e-3f1f-de22-cd87ceef34b3.png)

# Repoの追加

1. サイドメニューから**Repos**を選択します。
1. 自身のメールアドレスをクリックし、右上の**Add Repo**をクリックします。
1. ダイアログの**Git repo URL**に上でコピーしたURLを貼り付けます。
1. **Create**をクリックします。

# 動作確認

1. 上で作成したRepoにアクセスしノートブックを追加します。
1. **master**ボタンをクリックします。
1. コメントを入力して**Commit & Push**をクリックします。
![Screen Shot 2021-11-30 at 11.03.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/771b5432-0a0d-0ec1-07f6-2d2f8b10adee.png)
1. Azure DevOps側に変更が反映されていることを確認します。
![Screen Shot 2021-11-30 at 11.09.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/be586b12-bc16-59b9-dedf-06d9bf6b9b55.png)

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Laravel 8 VueでLaravel標準の認証機能を実装

#手順

### １. laravel/uiをインストール

``` ターミナル
composer require laravel/ui
```


### 2.ログイン機能追加
```
php artisan ui vue --auth
```

### 3.マイグレーション(DBに接続する設定は省きます)
```
php artisan migrate
```

### 4.vue-loaderのバージョンを変更
(2021-11-30現在は、変更しないとエラーになるため必須)

```package.json
"vue-loader": "^15.9.7",
↓
"vue-loader": "^15.9.8",
```


### 5.Packageをインストール
```
npm install
```

### 6.buildする(laravel mix)
```
npm run dev
```


### 7.php artisan serve(必須ではない)
(手っ取り早く確認するなら)

```
php artisan serve
```

### 確認
```
http://127.0.0.1:8000/login
```

または、welcomeページからLoginリンクから遷移

![laravel_login.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265907/36e96694-df03-131b-3cd7-fd83cf7fdda2.png)


## 環境
Laravel Framework 8.73.2
M1MacのHomebew3で入れたgitのdiffにdiff-highlightを反映

[検索する](https://www.google.com/search?q=mac+git+diff-highlight)といっぱい出てくるのですが、そこに`diff-highlight`が無いんですよね。結論を言うとHomebrewのインストール先が変更されてたのでパスが変わったようです。

M1MacのHomebewはインストール先が`/usr/local/bin`から`/opt/homebrew/bin`に変わったようです。そういえばインストールした時に`~/.zprofile`に`eval "$(/opt/homebrew/bin/brew shellenv)"`を書けって出ましたね。

以前は`/usr/local/share/git-core/contrib/diff-highlight/diff-highlight`を実行できるようにして`pager`に指定していたのですが`/opt/homebrew/share/git-core/contrib/diff-highlight/diff-highlight`を指定しないとダメなようです。

パスの通ってるとこにシンボリックリンク貼るパターンが多いですが、たぶんgitでしか使わないのでフルパスで指定しちゃいました。

```
# ~/.gitconfig

[pager]
	log = /opt/homebrew/share/git-core/contrib/diff-highlight/diff-highlight | less
	show = /opt/homebrew/share/git-core/contrib/diff-highlight/diff-highlight | less
	diff = /opt/homebrew/share/git-core/contrib/diff-highlight/diff-highlight | less
```
グラスモーフィズムを実装してみました

![glassmorphism.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877812/0ccaef1c-9f1d-fbde-7f9d-8d3b4ea0fb9d.png)



### 言語
 - html
 - css



### 実装例
以下の実装で上記の様に実装できます。

```sample.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="sample.css">
    <title>sample</title>
</head>
<body>
    <div class = "back-img">
        <div class = "glassmorphism">
            <p>Glassmorphism</p>
        </div>
    </div>
</body>
</html>
```

```sample.css
.back-img{
  background-image:url(img/beach.jpg);
  background-repeat: no-repeat; 
  display:flex;
  align-items: center;
  width:1920px;
  height:1107px;
}
.glassmorphism{
  width: 900px;
  height: 600px;
  margin: auto;
  text-align: center;
  border-radius: 2ch;
  background:linear-gradient( rgba(255,255,255,0), rgba(255,255,255,0.5));
  border: 1px solid rgba(255,255,255,0.4);
  border-right-color:rgba(255,255,255,0.2);
  border-bottom-color:rgba(255,255,255,0.2);
  backdrop-filter: blur(7px);
  box-shadow: 0 5px 20px rgba(255,255,255,0.2);
}
p{
  color: rgb(255, 255, 255);
  font-size: 60px;
  height: 450px;
  line-height: 450px;
}
```
@nuxtjs/storybookを入れた時のPostCSSのWARNを消す

# 問題

[@nuxtjs/storybook](https://github.com/nuxt-community/storybook) を Quick Setup 通りに入れて `npm run dev` をすると、下の WARN がめっちゃ出る。消したい。

```
WARN  You did not set any plugins, parser, or stringifier. Right now, PostCSS does nothing. Pick plugins for your case on https://www.postcss.parts/ and use them in postcss.config.js.
```

# 解決方法

`nuxt.config.js` の buildModules に `@nuxt/postcss8` を追加する。

```
 buildModules: [
  ...
  '@nuxt/postcss8'
 ],
```

`@nuxt/postcss8` は個別にインストールしなくてもいいらしい。

# 参考

- [[Docs] postcss@latest was added to the setup requirement but no relevant configuration was added #258](https://github.com/nuxt-community/storybook/issues/258)
GitHub Actions での Commit Message Injection に気をつける

[KINTO Technologies Advent Calendar 2021 - Qiita](https://qiita.com/advent-calendar/2021/kinto-technologies) の2日目の記事です。

## 経緯
GitHub のレポジトリに push して GitHub Actions でビルドを実行して結果を Slack に通知するというユースケースは多いかと思いますが、ある時特定のコミットだけビルドが落ちる現象に遭遇しました。
GitHub Actions のログを調べてみると Slack の API を叩くところで落ちているようでした。

```yml
- name: Slack Notification
  run: |
    jq -n '{
      username: "${{ github.event.repository.name }} ",
      attachments: [
        {
          "author_name": "${{ github.actor }}",
          "author_icon": "${{ github.event.sender.avatar_url }}",
          "title": ${{ github.event.head_commit.message }}
        }
      ]
    }' | curl -H 'Content-Type: application/json' -d @- ${{ secrets.SLACK_WEBHOOK_URL }}
```

やっていることは jq コマンドでリクエストデータを作って curl コマンドでポストしているだけです。しかし、コミットメッセージに特殊記号が含まれていると jq コマンドでエラーになってしまい、ビルドが落ちてしまっているようでした。
ここでふと、コミットメッセージを Slack API のリクエストになるよう書き換えたらインジェクションできてしまうのでは・・？と思い以下のようにリクエストを書き換えて実行すると、なんとインジェクションが成功してしまいました！

```
Commit Message Injection", title_link: "https://www.kinto-technologies.com/
```

ということでサニタイズの処理を入れておきましょう。

## 対応

jq コマンドには `--arg` オプションというものがあるのでこれを使います。　
（補足: `--arg a v set variable $a to value <v>;`）
jq コマンドの1行目を `jq -n --arg msg "${{ github.event.head_commit.message }}` と書き換え、 `${{ github.event.head_commit.message }}` の箇所を `$msg` に書き換えます。

```yml
- name: Slack Notification
  run: |
    jq -n --arg msg "${{ github.event.head_commit.message }} '{
      username: "${{ github.event.repository.name }} ",
      attachments: [
        {
          "author_name": "${{ github.actor }}",
          "author_icon": "${{ github.event.sender.avatar_url }}",
          "title": $msg
        }
      ]
    }' | curl -H 'Content-Type: application/json' -d @- ${{ secrets.SLACK_WEBHOOK_URL }}
```

これでコミットメッセージはただの文字列として扱われるようになり安全にコミットメッセージが Slack にポストされるようになりました :tada: 


当社では、トヨタ車のサブスク「KINTO」等の企画/開発を行っており、エンジニアを募集中です。
[KINTO Technologies コーポレートサイト](https://www.kinto-technologies.com/)
slimを使うとき

## slimの書き方

サンプル

```slim
/ SLIM
doctype html
css:
 h3{color:blue}
h3 何かしら入力
p 表示できる
```



ターミナルでの実行の仕方

```ターミナル
rake

slimrb -p 1115.slim > 1115.html
```



もしくは、エクスプローラーの窓に

```
 cmd /c rake
```

と入力すると一発で出来る。

これはrakeをインストールしてたり、簡単に作成できるrakefileを作っている前提での話。
Javascriptで配列や連想配列を並び替える方法

# きっかけ
インターン先でAPI側から取ってきたデータ（連想配列)をAlphabet順にsortしたかったが、一度もsortメソッドを使ったことがなかったのと比較関数が特殊だったのでまとめてみることにした。
# 概要
配列や連想配列をアルファベット順や数値の昇順、降順に並べたい。下記のarray.sortを使い並び替えてみる。

#### やってみたこと
文字列の配列をアルファベット順にする方法
数値の配列を昇順に並び替える方法
数値の配列を降順に並び替える方法

文字列の配列をアルファベット順に並び替える方法(nameプロパティ）
数値の配列を昇順に並び替える方法(scoreプロパティ）
数値の配列を降順に並び替える方法（scoreプロパティ）

# 配列
```js
arrayAlphabet = ['kamome','ari','tonbo','batta','tomato']
arrayNumber = [3,1,5,8,-1,0]
```
文字列の配列と数値の配列を用意した。
### 1.文字列の配列をアルファベット順に並び替える方法

```js
arrayAlphabet = ['kamome','ari','tonbo','batta','tomato']
arrayAlphabet.sort()
console.log(arrayAlphabet)
```
> Array ["ari", "batta", "kamome", "tomato", "tonbo"]

sortメソッドの引数を空にすればアルファベット順に並び替えることができる！ものすごく簡単

### 2.数値の配列を昇順に並び替える方法

上記のことをなすにはsortメソッドの引数に比較関数を用いなければならない。

##### sortメソッドの引数に比較関数を使用する

引数は配列から2つのa,bという値を取り出す。この2つの値を比較することで配列を並び替える。
関数の戻り値が正の時　→　引数1を引数2の後ろに並べ替え。
関数の戻り値が負の時　→　引数1を引数2の前に並べ替え。
関数の戻り値が0の時　→　何もしない

#### 数値の配列を昇順にするを比較関数を使って書いてみる

```js
arrayNumber = [3,1,5,8,-1,0]
arrayNumber.sort((a,b)=>{
 return a - b
})
console.log(arrayNumber)
```
>  Array [-1, 0, 1, 3, 5, 8]

例えば 3(引数1),1(引数2) を3から１を引いて答えが
正 → ３を１の後ろに加える。
負 → ３を１の前に加える。
0 → 移動しない。

この場合であれば３−１は正であるため3を1の後ろに加える。今回は3,1で考えたが他の要素同士を比較して配列を並び替えることができる。


### 3.数値の配列を降順に並び替える方法

先ほど考え方を使えば降順は下記のようなコードで実装できる

```js
arrayNumber = [3,1,5,8,-1,0]
arrayNumber.sort((a,b)=>{
 return b - a
})
console.log(arrayNumber)
```
> Array [8, 5, 3, 1, 0, -1]

# 連想配列

```js
userList = [{name: 'amazon',score: 72},
            {name: 'google',score: 11},
            {name: 'facebook',score: 100}]
```
上記のような連想配列を作る。

### 1.文字列の配列をアルファベット順に並び替える方法(nameプロパティ）
```js
userList.sort((a,b)=>{ 	
     if(a.name < b.name) return -1;
     else if(a.name > b.name) return 1;
     return 0;
})

console.log(userList)
```
> Array [Object { name: "amazon", score: 72 }, Object { name: "facebook", score: 100 }, Object { name: "google", score: 11 }]

上記では 例えば引数一番目amazon二番目にgoogleをとり、aの名前の方が小さい（アルファベットの最初の方）であれば負の値を返している(配列の最初に持ってくる）

### 補足
大文字の方が基本的に優先されるため、大文字小文字の区別を消すには以下のような記述を比較関数の最初に記述してあげれば良い

```js
	a = a.toString().toLowerCase();
	b = b.toString().toLowerCase();
```

### 2.数値の配列を昇順に並び替える方法(scoreプロパティ）
```js
userList.sort((a,b)=>{
 return a.score - b.score
})

console.log(userList)
```
> Array [Object { name: "google", score: 11 }, Object { name: "amazon", score: 72 }, Object { name: "facebook", score: 100 }]

### 3.数値の配列を降順に並び替える方法（scoreプロパティ）

```js
userList.sort((a,b)=>{
 return b.score - a.score
})

console.log(userList)
```
> Array [Object { name: "facebook", score: 100 }, Object { name: "amazon", score: 72 }, Object { name: "google", score: 11 }]

# まとめ
比較関数は引数を二つしか取らないので気持ち悪い気がする、全ての要素を比べてる感がなかったが使っていくうちに慣れた。またsortメソッドは元の配列を変更してしまう破壊的メソッドなので使い所には注意したい。

# 参考にした記事

https://www.sejuku.net/blog/62904

https://algorithm.joho.info/programming/javascript/sort-alphabet/
Bluefruit LE Sniffer使い方メモ


### 焼き増し生地

こちらも参考にMacOS（BigSur）での利用方法をまとめておく。
基本的にはadafruitのドキュメントを参考に進め、つまづくところをまとめておく。

- https://cdn-learn.adafruit.com/downloads/pdf/introducing-the-adafruit-bluefruit-le-sniffer.pdf

- 仕組みとしてはDriverをインストール後、wiresharkで使う用のpython環境を用意し、プラグインを追加することで、wiresharkでキャプチャできるようになる
![スクリーンショット 2021-11-30 10.43.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188958/83dd1792-5192-07e7-1c51-84ee611102be.png)

- つまづきポイント
    - driverインストール時、許可する権限がわからなくなるので注意
        - デベロッパツールのターミナルにチェック
        - インストールの最後に、システム慣用設定＞一般から、ダウンロードしたアプリケーションの許可するダイアログで、ダウンロードを許可する
    - wiresharkのconfigにプラグインのextcapのディレクトリを作成して、ダウンロードしたNordicのライブラリをコピペする
        - ~/.config/wireshark/extcap/
    - 全て完了したら、コマンドから```Wireshark```を実行してWiresharkを再起動し、設定反映する


### 参考：
- https://qiita.com/ishikawa-takumi/items/00964bd6e775920ba520
みんなで動画視聴するリモート社内勉強会


こんにちは。GxPの3年目の伊藤です。
この記事は[グロースエクスパートナーズ アドベントカレンダーの5日目](https://qiita.com/advent-calendar/2021/gxp)の記事となります。
本日の記事は社内で動画視聴会を開催してやってきたことを記事にしました。
何か参考になればと思います。

# 開催のきっかけ
コロナ禍によって勉強会やカンファレンスのほとんどがオンラインイベントとなり、セッションの動画がアップロードされて後日見れるようになりました。オフラインでは見たいセッションが同時並行で聞けなかったり、参加できなくて見れなかったのが、後日自分の好きなタイミングで視聴できるようになったのはありがたいことですね。
しかし、見たいものがあっても1人だと忙しくて見るの後回しになってしまったり、新しいイベントが開催されてどんどんみたいものが増えて溜まっていってしまうなんてことないでしょうか？
また、動画視聴会を開催することで社外勉強会などに興味を持つ人が増えたらいいなという思いなどもありました。
そこで、slackチャンネルを作成して定期的にみんなで集まって動画を見る会を開催してきました。


# やり方
### 基本的なルール
基本的なルールは以下のの二つだけです。

- **2人以上集まったら開催する**
- **見る動画は集まった人でみたいものを決める**

週に一回ちゃんと開催して長く続けられるようにようにカジュアルにやる方針で集まれる人で集まって見るようにしています。

みんなで動画を見るというのはこちらの勉強会でやっているやり方を参考にしています。

https://distributed-agile-team.connpass.com/

https://kyon-mm.hatenablog.com/entry/2020/09/04/100000

### 開催の仕方
人によっては動画をzoomなどで画面共有して見るとPCが重くなったりするので、各自で動画を開いて開始を一斉にするというスタイルでやりました。
視聴中にコメントを書きながら最後に感想を話し合って1時間ほどしたら終了といった形式です。動画が短かった場合は何本か見たり逆に1時間以上の尺の場合は２週に分けて開催しました。

###工夫
最初はzoomのコメント欄にコメントを書いていたのですが、zoomを閉じてしまうとコメントが消えてしまうので後で見返したり、参加していない人でもどんな感想やコメントが交わされていたのか見れないということがありました。そのため、slackのチャンネルスレッドにコメントを書くようにして、参加していない人でもなんとなく雰囲気がわかるようにして興味を持ってもらい、次回から参加してもらえるようにするといった工夫もしました。
最近は誰が今入ってるとかわかりやすいし参加するのも簡単なのでslackに新しく追加されたハドルミーティングを使って集まってやっています。

###開催風景
YouTubeにアップロードされているRSGTの動画やPodcastなどを聴いたりしています。
見ながらリアルタイムで動画のコメントをしたり、雑談を挟みながら行っています。

**弊社のセッションを見たときのコメントスレッド** 
このときは2人で開催しました。
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906528/b41d6822-fe3b-3296-183a-0561bad702e0.png">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/906528/962ed22e-f37d-28e7-896f-6ba3b19868b0.png">

https://www.youtube.com/watch?v=tynPfIOFsog

# 感想
自分1人で動画を見るときは自分の興味ないものしか見なかったりしますが、みんなで見る動画を決めることで自分では選ばないジャンルだったり、自分は知らなかったけど良い人や有名な人のセッションを見るとこができることもやっていて良いなと思った点です。
また、僕は割と感受性が低いのでサラッと流してしまうところでも他の人がコメントで「ここはすごいね」や自身の経験についてなどのコメントしていて他の人がどう感じるか知ることができました。他の人が普段どんなことを考えているかを知るきっかけにもなって良かったです。
同じものを見て違った意見や感想を知って議論したりすることで自分の見識が広がって学びになりました。これは動画視聴だけに限らず、読書会などでもできると思います。
リモートワークでチーム以外の人とコミュニケーションを取る機会も少なくなってきてしまったので、これからも時間を取って参加を続けていきたいと思います。
RedhatOS設計 ログイン設計①



/etc/pam.d/system-auth(コンソールログイン用) と
/etc/pam.d/password-auth（SSH,FTP用）


上記サイトを確認して、パスワード失敗回数を設定。

```
auth        required      pam_env.so

###追加###
auth        required      pam_tally2.so deny=3
###追加###

auth        required      pam_faildelay.so delay=2000000
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_unix.so
###追加###
account     required      pam_tally2.so
###追加###
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so
```

状況確認コマンド

```
pam_tally2 -u ユーザ名
```

ロック解除手順

```
pam_tally2 -r -u ユーザ名
```

参考サイト
https://hogem.hatenablog.com/entry/20121107/1352297631

https://www.server-world.info/query?os=CentOS_7&p=pam_tally
Vue.jsでaxiosをモック化してテストする！２

axios.createで作成したaxiosのラッパーを使ってテストする方法です。
もっと良いやり方があるよ！という場合はコメントいただけると幸いです。
ひとまずこれでテストはできます。モダンなやり方かはわかりませんのであしからず。

## 必要なライブラリ
* axios-mock-adapter
* vueのjestライブラリ達

## テストコード

### axiosのラッパーをインポート

``` javascript
import { axiosWrapper } from "@/domain/axios"
```

`@/domain/axios`では、axiosWrapperをexportしています。

``` javascript
import axios from "axios"
export const axiosWrapper = axios.create({
  baseURL: xxx,
  timeout: 15000
  ...
})
```

### axiosラッパーをモック化

axios-mock-adapterを利用して、ラッパーをモック化します。

``` javascript
const mockAxios = new MockAdapter(axiosWrapper)
```

### モックの振る舞いを設定

#### getの場合

``` javascript
it("テストケース: get", async () => {
  mockAxios.onGet(【URL】).reply(200, {})
  ...
})
```

URLの部分は、axios.createでbaseURLを設定していれば、baseURL以降のURLでOKです。
baseURLを設定していなければ、httpから始まるAPIのURLを指定する必要があるかと思います。

#### postの場合

``` javascript
it("テストケース: post", async () => {
  mockAxios.onPost(【URL】).reply(200, {})
  ...
})
```

#### ２本分のAPIをモック化する場合

同じ関数内で２本のAPIを呼んでいる場合等、２本分のAPIの戻り値を指定したい場合は、onXxxとreplyを繰り返します。

``` javascript
it("テストケース: API２本呼び出し", async () => {
  mockAxios
    .onGet(【URL1】).reply(200, {})
    .onGet(【URL2】).reply(200, {})
  ...
})
```

同じAPIを呼び出し、1回目と2回目で戻り値を変えたい場合も同じやり方が使えます。その場合はreplyOnceを使うと良いです。

``` javascript
it("テストケース: 同じAPI2回呼び出し", async () => {
  mockAxios
    .onGet(【URL1】).replyOnce(400, {})
    .onGet(【URL1】).replyOnce(200, {})
  ...
})
```

#### タイムアウトやネットワークエラーを戻り値とする

タイムアウトやネットワークエラー時のテストをしたい場合は、replyの部分をtimeoutやnetworkErrorOnceにします。

``` javascript
it("テストケース: タイムアウト", async () => {
  mockAxios
    .onGet(【URL】).timeout()
  ...
})

it("テストケース: ネットワークエラー", async () => {
  mockAxios
    .onGet(【URL】).networkErrorOnce()
  ...
})
```

#### 結果の確認

#### 何回呼ばれた？

history.getが配列になっているため、その配列数で呼ばれた数がわかります。

``` javascript
it("テストケース: API呼び出し回数", async () => {
  mockAxios.onGet(【URL】).reply(200, {})
  ...
  expect(mockAxios.history.get.length).toBe(2)
})
```

#### 呼んだ時のリクエストは何か？

history.get[i]でそれぞれ取れます。

``` javascript
it("テストケース: get", async () => {
  mockAxios.onGet(【URL】).reply(200, {})
  ...
  // header
  expect(mockAxios.history.get[0].header).toEqual({
    token: "xxxxx"
  })
  
  // get parameter
  expect(mockAxios.history.get[0].params).toEqual({
    userId: "xxxxx"
  })
})

it("テストケース: post", async () => {
  mockAxios.onPost(【URL】).reply(200, {})
  ...
  // header
  expect(mockAxios.history.post[0].header).toEqual({
    token: "xxxxx"
  })
  
  // post body
  expect(JSON.parse(mockAxios.history.post[0].data)).toEqual({
    userId: "xxxxx"
  })
})
```

#### リセット

テストケース毎に、終了時にhistoryをリセットします。リセットしないとitを実行するたびにmockAxios.historyに溜まっていきます。

``` javascript
describe("テスト", () => {
  afterEach(() => {
    mockAxios.resetHistory()
  })
})
```

## 蛇足

Axiosとは関係ありませんが、関数をモックしたい場合は以下のようにします。

``` javascript
import * as strUtils from "@/utils/strUtils"
jest.spyOn(strUtils, "isNull").mockReturnValue(false)

// promiseのresolveを返す関数の場合
jest.spyOn(strUtils, "isNull").mockResolvedValue("ok")

// promiseのrejectを返す関数の場合
jest.spyOn(strUtils, "isNull").mockRejectedValue("error")
```

jestのモックを使うときは、リセットを忘れずに。

``` javascript
describe("テスト", () => {
  afterEach(() => {
    jest.clearAllMocks()
  })
})
```
Vim沼に片足、いや親指の先っちょだけでも突っ込んでみない？

#はじめに
この記事で扱うVimはVimキーバインド（あとNeoVim）を主に指します。
お使いのエディタ、IDEにVimプラグインを入れて、
快適なコーディングライフを一緒に送りましょう。

#4つのモードについて
Vimでは4つのモードを行き来して、コーディングを加速させます。

その4つとは、
1.ノーマルモード
2.インサートモード
3.ビジュアルモード
4.コマンドモード
です。

次に、それぞれの特徴を書いていきます。

##ノーマルモード
カーソルの移動や基本操作を行うモードです。

##インサートモード
いつものコードを打つモードです。
このモード中に文字を打つと、エディタにその文字が入力されていきます。

##ビジュアルモード
範囲選択モードに切り替わり、選択した範囲の編集を行うモードです。

##コマンドモード
ファイルの上書き保存、終了などのすこし特殊なコマンド入力を行うモードです。

#片足を突っ込む覚悟を持とう。
親指の先っちょだけでも...なんてタイトルに書いておいてなんですが、
親指の先っちょだけで済むはずがないんですよね。

なので、まずは**覚悟**を決めましょう。
覚悟が決まったらVimの沼へ親指の先っちょだけ突っ込んでみましょう。
大丈夫、きっちりくるぶしくらいまでは浸かります。

##覚悟その1　マウスを手放す覚悟
どうしてもマウスを使わなければいけない場面を除いて、
コーディングに置いて極力マウスは使わないようにすること。
これは腕や手の負担を減らすことにもつながってきます。
が、一番の理由はコーディングを加速させること。
マウスとキーボードを行き来する時間を極力減らすという覚悟を持ちましょう。

##覚悟その2　カーソルキーを手放す覚悟
あなたはもうカーソルキー（←↑↓→）ともさようならする覚悟を決めなければなりません。
カーソルキーを押しているところをVimmerに見つかってしまえば最後。
寝込みを襲われて、もう太陽を見ることは叶わないでしょう。

#ようこそ、Vimの世界へ
覚悟はできましたか？
できたのなら、早速Vimの世界へ飛び込みましょう。
（片足云々はどこいった？）

まずはプラグインを入れましょう。
VSCodeを使ってるなら”VSCode Neovim”を。
IntelliJを使ってるなら”Idea Vim”を入れましょう。
これであなたもVimの救いを受けることができるようになりました。

##モード間の移動
さて、ここからが大事です。
今、あなたのエディタ/IDEはノーマルモードになってます。
Vimはノーマルモードを起点に、他の3つのモードに移動しながらコーディングしていきます。
・iでインサートモードへ（インサートのiで覚えやすいね！！！）
・Escでノーマルモードへ（困った時はEscを5回くらい押しとけば間違いなくノーマルモードだよ！！）
・:（コロン）でコマンドモードへ（ノーマルモードからじゃないとダメだからね？）

初めはこれだけ覚えておけばいいでしょう。
ビジュアルモードはおいおい使っていけばいいと思うので、
とりあえずこの3つのモードを行ったり来たりできるようになりましょう。

##ノーマルモードについて
覚えるべきことは「hjkl」がそれぞれ「←↑↓→」に対応してます。
基本的にこの「hjkl」を使ってコードの海を移動します。

文字の削除は「x」を使います。
改行は「o」でできます。

インサートモードへは「i」、
コマンドモードへは「:」で移動します。

##インサートモードについて
インサートモードは文字を打つモードで、たいしてできることはありません。
ノーマルモードへの戻り方を覚えるだけです。
「Esc」でノーマルモードへ戻ることができます。

##コマンドモードについて
ここはとても重要です。
ファイルを変にさわちゃって、よくわからないままでファイルを上書き保存してしまった。
なんてことが起こらないようにしっかりと覚えましょう。

まず、**保存せず**にファイルを閉じる。これは「q！」です。
「q」で閉じる、「！」は強制的にを意味しています。

とりあえずよくわかんない状態になったら、
「Esc」を10回くらい押して「:q!」を押しておけばファイルは保存されず、編集前の姿でいてくれます。

次にファイルを保存。これは「w」です。
ctrl＋Sと同じ意味合いですね。

この「q」と「w」を組み合わせて「wq」と打つと保存して終了になります。

ノーマルモードへの戻り方は「Esc」です。

#最後に
どうでしたか？Vimと少し仲良くなれそうですか？
「この操作したいんだけどどうすればいいんだー！！」となったらググりましょう。
意地でもコーディングでマウスは触らないんだ！！という意思があなたを強くします。

それでは良きVimライフを。
GitLab CIのartifactsの上限に引っかかった（Uploading artifacts to coordinator... too large archive）

## 元のCI設定

* GitLab.com の GitLab CI を使用
* 「build」ジョブでdocker imageを作成し、「push」ジョブで検証環境にデプロイしている
* ステージ間でイメージを受け渡すために [artifacts](https://gitlab-docs.creationline.com/ee/ci/pipelines/job_artifacts.html) を使用

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308848/deb7091a-ad71-d26d-2d61-e494f50266b4.png)

## artifactsの上限に引っかかった

ある日「build」ジョブで扱うdocker imageを追加したところ、以下のエラーが発生

```
ERROR: Uploading artifacts to coordinator... too large archive  id=xxx responseStatus=413 Request Entity Too Large status=413 Request Entity Too Large token=xxx
FATAL: too large                                   
ERROR: Job failed: exit code 1
```

調べてみると、GitLab.com の GitLab CI で一度に扱える artifacts は **1GB** までとのこと

https://docs.gitlab.com/ee/user/gitlab_com/#gitlab-cicd

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308848/7069a304-cc7b-7b9a-edb7-96c96a88a442.png)

## 対応後のCI設定

* 「build」ジョブを二つに分割して解消

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308848/4772b2bf-eeda-ade7-d657-f4d092678647.png)

## おわり

* 今回は複数のモジュールを1つのジョブで扱おうとしていたので別ジョブにすることで回避できたが、そもそも1つのモジュールが1GBを超えた場合はどうするんだろう...（普通に1GBを超えるケースはあるのでは?）
    * ステージを跨がずに、1つのジョブで build & push をまとめて実施することも考えたがなんとなく抵抗感がある...
* 似たような状況でいい回避策をお持ちの方はコメントください
[TypeScript] 小数点以下の桁数を指定して四捨五入する

```typescript
const roundWithScale = (value: number, scale: number) => {
  return Math.round(value * 10 ** scale) / 10 ** scale;
};

roundWithScale(1.456789, 0) // 1
roundWithScale(1.456789, 1) // 1.5
roundWithScale(1.456789, 2) // 1.46
roundWithScale(1.456789, 3) // 1.457
```
Laravel Duskでブラウザ自動テスト化導入まで

Laravel Duskを使うことになったのでメモ程度に残します。

### Dsukでできる事
>Laravel Duskは、表現力豊かで使いやすいブラウザ自動化およびテストAPIを提供します。

#手順

### 1.laravelをインストール

```
composer create-project laravel/laravel laravel_dusk
```

### 2.Duskをインストール
```
composer require --dev laravel/dusk
```

```
php artisan dusk:install
```


### 3.アプリケーションの環境変数を設定する
※「php artisan serve」で動かす時

```.env
APP_URL=http://127.0.0.1:8000/
```


###4.サーバー起動
※「php artisan serve」で動かす時

```
php artisan serve
```


### 5.テスト生成

```
php artisan dusk:make LoginTest
```
↓作成される

```tests\Browser\LoginTest.php
<?php

namespace Tests\Browser;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class LoginTest extends DuskTestCase
{
    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->assertSee('Laravel');
        });
    }
}

```

※Duskのテストを生成するには、dusk:make Artisanコマンドを使います。生成されたテストは、tests/Browserディレクトリへ設置されます。


### 6.テストの実行

```
php artisan dusk
```


##OKになって入れば成功です。
![dusk_ok.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265907/73a9da90-4b86-d313-3a04-abce01911149.png)




## 環境
- Laravel Framework 8.73.2

---
競プロ小技集

# はじめに
これは、Advent Calender 「競技プログラミングを始めたばかりの人に伝えたいこと」 7日目の記事です

この記事では、個人的に革命的だった競プロの小技を書いていきます

# 拡張機能
## ac-predictor
言わずと知れたパフォーマンス予測システム
順位表からパフォーマンスとレート変化が分かるのである程度安心できる

[ダウンロード](https://greasyfork.org/ja/scripts/369954-ac-predictor)

## AtCoder Language Buttons
提出のところに言語選択のボタンを設置できる。
PythonとC++を使う僕にとっていちいちスライドさせるUI(?)をいじる必要だったり、言語を間違えて提出してペナ、ということが防げるので便利

[ダウンロード](https://greasyfork.org/ja/scripts/421663-atcoderlanguagebuttons)

## atcoder_submit_keyboard_shortcut
TwitterのようにCtrl+Enterで提出できるもの
ツイ廃の僕にとってかなり使いやすい

[ダウンロード](https://greasyfork.org/ja/scripts/378760-atcoder-submit-keyboard-shortcut)

## AtCoder_submit_keyboard_shortcut
コンテスト中でも順位表からその問題のDiffなどのいろんな情報を取得できる
かなり高性能だが、重いので自動更新をするコンテスト中での使用は撤退後がいい

[ダウンロード](https://greasyfork.org/ja/scripts/419541-atcoder-standings-difficulty-analyzer)

他にも、いろいろ便利な拡張機能があるので是非調べみて欲しい

# コーディングテクニック/アルゴリズム
# rep(i, n)
ループを書く時にいちいちforを全て書くのは面倒なので、以下のようにする

```C++
#define rep(i, n) for(ll i = 0; i < (n); ++i)
```

こうすると、rep(i, n)とするだけでn回ループすることができる。
書く量が一気に減るのでかなり便利

# chmin/chmax
変数をもう一つの変数と比較して、もう一つの方が大きかったら(小さかったら)代入して、trueを返す。
比較と代入を一気にできるので意外と便利

```C++
template<typename T> bool chmin(T& a, T b){if(a > b){a = b; return true;} return false;}
template<typename T> bool chmax(T& a, T b){if(a < b){a = b; return true;} return false;}
```
【GitHub Actions】Cypress のスクリーンショットの文字化けを解決した話

# はじめに
※この記事は[mediba Advent Calendar 2021](https://qiita.com/advent-calendar/2021/mediba) の20日目の記事です。

はじめまして、株式会社mediba 新卒エンジニアの[@hrktcy](https://twitter.com/hrktcy)です。年の瀬が近づいてきましたね、4月に入社してからあっという間に過ぎる日々です。

弊社では、2021年9月28日、Ponta ポイントをおトクに使うための活用術やため方を紹介をするサイトとして、[ポイ活診断](https://poikatsu.enjoy.point.auone.jp/shindan/1/)・[ポイ活情報](https://poikatsu.enjoy.point.auone.jp/info/)・[ポイ活の極意](https://poikatsu.enjoy.point.auone.jp/gokui/)をそれぞれローンチしました。私にとってエンジニアとして初めてジョインしたプロダクトです。

# 本題

開発業務の中で、ブラウザ側の挙動のテストを行うために[Cypress](https://www.cypress.io/) を用いてテストコードを書くことがありました。ローカル環境では問題なく動作していたのですが、GitHub リポジトリ内リリース用ブランチにコミットされた際にGitHub Actions 上でCypress を動かすようにワークフローを定義しE2E テストを行うと、テストに失敗した時にArtifact に生成されるスクリーンショットの日本語部分が文字化けしてしまうという事態が起こりました。
これだとテストが失敗した際にどこで失敗したのか判断しにくいですよね。

# 環境

* Next.js
    * 11.1.2
* cypress
    * 8.7.0

# 発生当時のワークフロー

該当部分のソースコードです。[cypress-io/github-action@v2](https://github.com/cypress-io/github-action) を用いています。

```
name: UI Test

on:
  push:
    branches:
      - 'release/**'

jobs:
  run_ui_test:
    runs-on: ubuntu-latest

    defaults:
      run:
        shell: bash

    steps:
      # リポジトリをチェックアウトする
      - name: Checkout branch
        uses: actions/checkout@v2

      # Cypress を起動する
      - name: Run cypress
        uses: cypress-io/github-action@v2
        with:
          build: yarn build
          start: yarn serve
          wait-on: 'http://localhost:3000'
          browser: chrome
          config: screenshotOnRunFailure=true

      # Cypress が失敗したとき、スクリーンショットをArtifact に保存する
      - name: Save screenshots folder
        if: failure()
        uses: actions/upload-artifact@v2
        with:
          name: screenshots
          if-no-files-found: ignore
          path: cypress/screenshots/**
```

# 解決方法

どうやらワークフローで設定した仮想イメージ(Ubuntu-latest) に日本語フォントはプリインストールされていないようです。Cypress を動かす前に[fonts-noto](https://github.com/googlefonts/noto-fonts) パッケージをインストールすることで解決しました。

```
name: UI Test

on:
  push:
    branches:
      - 'release/**'

jobs:
  run_ui_test:
    runs-on: ubuntu-latest

    defaults:
      run:
        shell: bash

    steps:
　　　　　　　　　　　　# リポジトリをチェックアウトする
      - name: Checkout branch
        uses: actions/checkout@v2

      # fonts-noto をインストールする(追加部分)
      - name: Install fonts-noto
        run: sudo apt install fonts-noto

　　　　　　　　　　　# Cypress を起動する
      - name: Run cypress
        uses: cypress-io/github-action@v2
        with:
          build: yarn build
          start: yarn serve
          wait-on: 'http://localhost:3000'
          browser: chrome
          config: screenshotOnRunFailure=true

      # Cypress が失敗したとき、スクリーンショットをArtifact に保存する
      - name: Save screenshots folder
        if: failure()
        uses: actions/upload-artifact@v2
        with:
          name: screenshots
          if-no-files-found: ignore
          path: cypress/screenshots/**
```

# 最後に
薄い内容の記事ではありますが誰かの手助けになればと思います。

-
mediba では一緒にモノづくりができるエンジニアを募集しています。
少しでもご興味がありましたら[こちら](https://www.mediba.jp/recruit/)からどうぞ。
【Nextcloud】curlでNextcloudのAPIを操作する

#実施すること
NextcloudにCLIからcurlを使って操作をしていきます


#目次
・ローカル(Desktop)に存在するファイルをアップロード
・ファイルをローカル(Desktop)にダウンロード
・ファイル名の変更
・ファイルのコピー
・ファイルの削除
・新規フォルダの作成
・ファイルの共有と共有リンク取得
・特定のユーザにファイルの共有
・ファイルの共有削除
・共有ファイルの情報取得

##ローカル(Desktop)に存在するファイルをアップロード
```:構文
curl -X PUT -u [user名]:[パスワード] https://[ホストサーバーのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[アップロードする任意のファイル名] -T ./[ローカルからアップロードするファイル名]
```
<br>

##ファイルをローカル(Desktop)にダウンロード
```:構文
 curl -X GET -u [user名]:[パスワード] https://[ホストサーバーのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[ダウンロードするファイル名] --output [保存先の任意のファイル名]
```
<br>

##ファイル名の変更
```:構文
 curl -u [user名]:[パスワード] -X MOVE 'https://[ホストのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[変更前のファイル名]' -H "Destination:https://[ホストのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[変更後の任意のファイル名]"
```
<br>

##ファイルのコピー
```:構文
 curl -u [user名]:[パスワード] -X COPY 'https://[ホストのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[ファイル名]' -H "Destination:[ホストのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[ファイル名]"
```
<br>

##ファイルの削除
```:構文
curl -X DELETE -u [user名]:[パスワード] https://[ホストのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]/[ファイル名]
```
<br>

##新規フォルダの作成
```:構文
 curl -X MKCOL -u [user名]:[パスワード] https://[ホストのIPアドレス]/remote.php/dav/files/[user名]/[フォルダ名]
```
<br>

##ファイルの共有と共有リンク取得
```:構文
  curl -u [user名]:[パスワード] -X POST 'https://[ホストのIPアドレス]/ocs/v2.php/apps/files_sharing/api/v1/shares?path=/[フォルダ名]/[ファイル名]&shareType=[共有の種類]' -H "OCS-APIRequest:true"
```
<br>

##特定のユーザにファイルの共有
```:構文
  curl -u [user名]:[パスワード] -X POST 'https://[ホストのIPアドレス]/ocs/v2.php/apps/files_sharing/api/v1/shares?path=/[フォルダ名]/[ファイル名]&shareType=0&shareWith=[共有対象のuser名]&permissions=[権限の種類]'  -H "OCS-APIRequest:true"
```
<br>

##ファイルの共有削除
```:構文
curl -u [user名]:[パスワード] -X DELETE "https://[ホストのIPアドレス]/ocs/v2.php/apps/files_sharing/api/v1/shares/[シェアID]"  -H "OCS-APIRequest:true"
```
<br>

##共有ファイルの情報取得
```:構文
curl -u [user名]:[パスワード] -X GET "https://[ホストのIPアドレス]/ocs/v2.php/apps/files_sharing/api/v1/shares"  -H "OCS-APIRequest:true"
```
<br>

##参考記事
[Nextcloudドキュメント](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/basic.html)
[Nextcloud API一覧]
(https://nextcloud.stylez.co.jp/api)
[curlオプション]
(http://www.mit.edu/afs.new/sipb/user/ssen/src/curl-7.11.1/docs/curl.html)
[curlコマンド使い方メモ]
(https://qiita.com/yasuhiroki/items/a569d3371a66e365316f)
【JavaScript】モジュール⑤　Strictモード


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/bafc0070748fea329ced


#目的

* モジュールについての理解を深める

#本題
###1.Strictモード

Strictモードとは、通常JavaScriptで使用できる（許容されている）**一部の書き方を制限**する

 なぜ制限するのかというと主な目的は以下の三つ

* 意図しないバグの混入の防止
* 予約後の確保
* コードのセキュア化

大規模開発に対応できるようにしている

Strictモードを有効化するにはファイルの先頭,もしくは関数内の先頭行に**"use strict"**と記述する

####例1

````main.js
a = 0;
console.log(a);
`````

上記の場合ではそのまま0が出力されるが

````main.js
"use strict"
a = 0;
// ReferenceErrorとなる
console.log(a);
`````

関数も同様

```main.js
a = 0;
console.log(a);

function fn() {
  "use strict"
  b = 1
  console.log(b);
}
fn();
// この場合、bのみエラーとなる
``````

従来のJSでは、エラーとならなかったものをエラーとすることで、バグが発生しにくいように制限を加えている

####例2

予約後の確保の例
将来JSのアップグレードがあった際に変数として使えない単語がある

````main.js
function fn() {
  "use strict"
  // b = 1
  // Uncaught SyntaxError: Unexpected strict mode reserved wordと表示され使用不可
  const implements, interface, packages
}
fn();
// console.log(b);
`````

####例3

セキュアなコードについて

````main.js
function fn() {
  // このthisはWindowオブジェクトをさす
  return this;
}
console.log(fn());
`````

これをstrictモードにすると

````main.js
function fn() {
  "use strict"
  return this;
}
// undefinedと出力
console.log(fn());
`````

####例4

通常の場合、thisはオブジェクトへの参照を取ることになるが,
Strictモードではプリミティブ型も取ることができる


````main.js
function fn() {
  "use strict"
  return this;
}
// callでthisの値を変更
console.log(fn.call(2));
// 2と出力される
// Strictモードを外すとNumber {2}とオブジェクトでラップされたプリミティブ型の値が帰ってくる
// 文字列も同様
console.log(fn.call("2"));
// 2と帰ってくる
``````

###2.Strictモードとクラス

Classのコンストラクターやメソッド内は自動的にstrictモードがオンになっている

####例1

````main.js
// 下記は両方ともundefinedと出力される
// コンストラクターもメソッドも内部で宣言した関数内のthisが表示されない
class C {
    constructor() {
        function fn() {
            console.log(this)
        }
        fn();
    }

    method() {
        function fn() {
            console.log(this)
        }
        fn();
    }
}

const c = new C();
c.method();
``````

今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [Let'sプログラミング JavaScript入門](https://www.javadrive.jp/javascript/)