OmniAICreator/Qiita-1.07M huggingface dataset:
Pterodactyl Panelで、2FAコードが取得できなくなってログインできなくなった時の処置

## パスワードを再発行しても、2FA認証は解除されない
2FA認証が出来ない状況でもパスワードの再発行はできましたが、新しいパスワードでログインを試行しても2FAコードが要求されてしまう。

## コントロールパネルには2FA設定を解除する項目が無かった
![screenshot_20200426_220354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620130/64e4903b-2ed0-b25f-d99e-9dc5891c6d9f.png)
![screenshot_20200426_220438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620130/860414e3-5107-8f67-04b6-9d7edfd6e5cf.png)

## 解決策
職人(artisan)に頼み込んで、強制的に2FA認証を取り消す

```bash
php artisan p:user:disable2fa --email=user@example.com
```
~~※チュートリアルページにあるように{}を付けると、~~

```
Too many arguments, expected arguments "command".
```
~~と怒られてしまう~。~~

→{--hello-world}はドキュメント簡略化のためにオプションの意味であると、上部にしっかり書かれていました。お恥ずかしい...

## 環境
```
Version Information
===================

 Panel Version     0.7.17
 Latest Version    0.7.17
 Up-to-Date        Yes
 Unique Identifier user@example.com
```

## 参考リンク
[Artisan CLI - Pterodactyl community](https://pterodactyl.io/community/tutorials/artisan.html)
C++における文字の扱い方について

#はじめに
 文字セットや文字コード、文字を扱う型について混乱するため、調べた内容を備忘録として残していきます。
まだまだ全然分からないので、色々なサイトを歩き回ってまとめてました。


#文字セットについて
　文字セットは大きく分けると以下の2つに大別される。
 **1. マルチバイト文字セット**
　アルファベットは1Byte、日本語は2Byteのように1/2Byteどちらかで表す方式のこと。
 **2. ワイド文字セット**
　1文字を常に2Byteで表す方式のこと
　※Unicodeには4バイトまで拡張されたものもあるが、ワイド文字セットには含まないこととする。

#文字コードについて
 - **Shift_JIS**  
 マルチバイト文字セットで表される日本語を扱うための文字コードの1つ
 - **Unicode**　
 ワイド文字セットで表される世界中の文字を表そうとする文字コード
 ※前述のとおり、4Byteまで拡張されたものも存在している。

#文字を扱う型
 - **char型**  
 マルチバイト文字セットで表す。
 - **wchar_t(WCHAR)型**  
 ワイド文字セットで表す
 - **TCHAR型**
 マルチバイト文字セット・ワイド文字セットのどちらも扱うことができる。  
 どちらの文字セットで扱うかは、以下の設定によって異なる。  
 ユニコードが設定されている場合：ワイド文字セットとして扱う。  
 マルチバイト文字セットが設定されている場合: マルチバイト文字セットして扱う。
 - **LPCSTR**  
 「const char*」であり、charと同様の扱い方。  
 - **LPCWSTR**  
 「const WCHAR*」であり、WCHARと同様の扱い方。
 - **LPCTSTR**  
 「const TCHAR*」であり、TCHARと同様の扱い方。  
 - **CString**  
 「TCHAR*」であり、TCHARと同様の扱い方。  
 - **std::string**  
 「char*」であり、charと同様の扱い方。

# 文字セットの設定
Visual Studioでは、プロジェクトの「プロパティ」→「全般」→「文字セット」から
  以下の2つのどちらかを設定できる。
  **1. Unicode文字セットを使用する**
  **2. マルチバイト文字セットを使用する**

# 文字セットの設定を変更することでの問題
 Visual Studioでは、デフォルトの設定が「Unicode文字セットを使用する」になっており、
 マルチバイト文字セットは非推奨となっている。
 【理由】
　1. shift_JISでは、多言語に対応していないため、文字化けが発生する。

# CStringからstring型への変換
Unicode文字セットを使用する場合、CStringはワイド文字セット、
stringはマルチバイト文字セットで扱われるため、変換ができない。
そこで、以下の2つの方法で変換可能。
**1. 文字セットの設定を「マルチバイト文字セットを使用する」にする。**
**2. WideCharToMultiByte関数を使用する。**

# 終わりに
色々調べてみたが、まだまだよくわからない点が多いなーっといった感想です。
本記事を編集・追記していきながら、文字の扱いについて、本記事を見たら
理解ができることを目指していきたいです。
テキストやボタンの端を丸くする　Android

#はじめに
テキストやボタンの端を丸くする方法を簡単にまとめました。

#1.Layout resource file の作成
layout_width 200dp
layout_height 50dpのTextViewの端を丸くさせます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619313/face476a-87a2-b2b1-1255-85d18ac12713.png"width=50%>

drawableフォルダに`Drawable resource file`を作成する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619313/c1251257-5c85-ca8d-e9dc-24c3bc6af505.png"width=80%>
<img width="313" alt="スクリーンショット 2020-04-26 21.18.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619313/58028afe-eda2-6c52-173d-599ff985d478.png">


#2.背景色と丸み
作成した、`Drawable resource file`で`<shape`タグにし
`<solid android:color="@android:color/holo_orange_light"/>`で色を
`<corners android:radius="25dp"/>`で丸の大きさを決める。
今回はtextviewのhightを50dpにしたので25dpとした。

```kotlin
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="@android:color/holo_orange_light"/>
    <corners android:radius="25dp"/>

</shape>
```
#３.backgrounに反映させる
`TextView`のbackgroundを作成した`Drawable resource file`に指定する。

```kotlin
 <TextView
        android:id="@+id/textView"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="TextView"
        android:background="@drawable/rounded_textview"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
```
丸くする事が出来た！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619313/f0bf4738-79a5-a378-f434-ec75508f996f.png"width=50%>
ボタンも同じように丸く出来ます。

<img width="131" alt="スクリーンショット 2020-04-26 21.50.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619313/5f9efce5-0ebb-68c3-56ba-ad9050afcaa4.png">
#まとめ
端を丸めるデザインが多いので備忘録として残しました。
Flutter で動的に Widget の表示・非表示を制御する方法まとめ

Flutterで条件によってWidgetの表示・非表示を切り替える方法を調べていたらいくつかありそうなのでまとめました。
間違いや気になるところあれば指摘していただけると嬉しいです :pray: 

## 結論

if (Control Flow Collections) を使うのがシンプルで良さそう。

```dart:使用例
Column(
  children: <Widget>[
    if (showHoge) Text('hoge'),
    Text('fuga'),
  ],
),
```

Dart2.3 で導入された機能だそうです。
Widget ツリーに限らず配列に含めるかどうかを `if` で制御できます。
ちなみに `else` や `else if` も使えます。

参考: <https://github.com/dart-lang/language/blob/master/accepted/2.3/control-flow-collections/feature-specification.md>

※pubspec.yaml で sdk を 2.3.0 以上に指定する必要があります。

## その他候補

### Visibility

```dart:使用例
Column(
  children: <Widget>[
    Visibility(
      visible: showHoge,
      child: Text('hoge'),
    ),
    Text('fuga'),
  ],
),
```

そのものって感じな Widget ですね。
プロパティによって非表示時に領域を確保することもできます。

しかし、ドキュメントには「ただ Widget を隠すだけなら Visibility を使う必要はありません。要素を含めないのが一番シンプルです」みたいなことが書かれているので、そのまんま鵜呑みにすると、非表示にするだけなら if を使うのが良いかも。
>Using this widget is not necessary to hide children. The simplest way to hide a child is just to not include it, or, if a child must be given (e.g. because the parent is a StatelessWidget) then to use SizedBox.shrink instead of the child that would otherwise be included.

参考: <https://api.flutter.dev/flutter/widgets/Visibility-class.html>


### 三項演算子 + `SizedBox.shrink`

```dart:使用例
Column(
  children: <Widget>[
    (showHoge) ? Text('hoge') : SizedBox.shrink(),
    Text('fuga'),
  ],
),
```

調べる前はこの方法で実装しようとしていました。
空っぽを示す `SizedBox.shrink()` をわざわざ書くのが少し気持ち悪いので、先述の候補の方が良いと思っています。

※余談①
もし「`showHoge == false` なら別の Widget を表示する」場合、三項演算子でも if-else でも同じことができます。その場合は三項演算子を使うのが個人的には好みなんですが...Control Flow Collections の仕様の中では三項演算子読みづらくない？って言われちゃってますね。
>Users can and do use the conditional operator `(?:)` for cases like this today. It works OK, but isn't very easy on the eyes. And, of course, it falls down in cases where you don't have an "else" widget that you want to use instead of the "then" one.
https://github.com/dart-lang/language/blob/master/accepted/2.3/control-flow-collections/feature-specification.md


※余談②
空の状態を示すWidgetを表現する場合、nullだとエラーになるのでどうするか？について。実装例とかで `Container()` をよく見かける気がしますがレイアウトに影響を与えることがあるので `SizedBox.shrink()` を使うようにしています。
参考: <https://stackoverflow.com/a/55796929>

### その他

Visibility のドキュメントを読むと以下の Widget で部分的に似たようなことをできるようですね。
if や Visibility では要求を叶えられない場合に助けになるかもしれません。

>These widgets provide some of the facets of this one:
>
- Opacity, which can stop its child from being painted.
- Offstage, which can stop its child from being laid out or painted.
- TickerMode, which can stop its child from being animated.
- ExcludeSemantics, which can hide the child from accessibility tools.
- IgnorePointer, which can disable touch interactions with the child.

あと、アニメーションと共に表示・非表示する場合は `Animated` 系の Widget が使えますね。

>- AnimatedSwitcher, which can fade from one child to the next as the subtree changes.
- AnimatedCrossFade, which can fade between two specific children.

<https://api.flutter.dev/flutter/widgets/Visibility-class.html>

## まとめ

結論に書いた通り基本的には if が良さそう。
チームの好みや要件次第では Visibility も良さそうですね。

## 参考

dart - Show/hide widgets in Flutter programmatically - Stack Overflow
<https://stackoverflow.com/a/53044562>
XymonのEnable/Disable機能がリバースプロキシ環境で使えないのを直す

注意：スカイホビット越川のシステム監視ブログ https://ameblo.jp/skyhobbit/entry-12592619048.html と同じ内容です。

XymonにはEnable/Disable という監視を一時停止する機能がありますが、それが使えなくなる事象がありました。
AmazonLinux 2環境のXymon 4.3.30。
Enable/Disable画面の Select what to Disable で「Apply」をクリックしても、なにも反応がありません。

このとき Apache のエラーログには

```:error_log
AH01215: 日付 Enadis POST that is not coming from self or svcstatus (referer=http://example.com/xymon-seccgi/enadis.sh). Ignoring.: /home/xymon/cgi-secure/enadis.sh, referer: http://example.com/xymon-seccgi/enadis.sh
```

とのエラーメッセージが出力されています。
EnadisとはEnable/Disableの略ですね。POSTはhttpのPOSTのことではなく投稿との意味。
Enable/Disableの投稿は自分自身かsvcstatusからは許可されていないとのことです。
リバースプロキシを使って転送している環境なので使えないと出ているようです。

公式メーリングリストを探すと 2019年9月12日 に René Vermareさんからパッチの投稿がありました。
https://lists.xymon.com/archive/2019-September/046708.html から引用。
(注意：字下げはTABです)

```patch:reverse_proxy.patch
--- a/web/enadis.c      2019-07-23 17:29:06.000000000 +0200
+++ b/web/enadis.c      2019-09-11 01:06:33.283642013 +0200
@@ -332,7 +332,8 @@
    int argi, i;
    char *username = getenv("REMOTE_USER");
    char *userhost = getenv("REMOTE_HOST");
-    char *userip   = getenv("REMOTE_ADDR");
+    char *userip   = getenv("HTTP_X_FORWARDED_FOR");
+    if (userip == NULL) userip = getenv("REMOTE_ADDR");
    SBUF_DEFINE(fullmsg);
    char *envarea = NULL;
    int  obeycookies = 1;
--- a/web/acknowledge.c 2019-07-23 17:29:06.000000000 +0200
+++ b/web/acknowledge.c 2019-09-11 01:01:55.493676233 +0200
@@ -374,7 +374,8 @@

    parse_query();
        if (getenv("REMOTE_USER")) {
-            char *remaddr = getenv("REMOTE_ADDR");
+            char *remaddr = getenv("HTTP_X_FORWARDED_FOR");
+            if (remaddr == NULL) remaddr = getenv("REMOTE_ADDR");

            SBUF_MALLOC(acking_user, 1024 + strlen(getenv("REMOTE_USER")) + (remaddr ? strlen(remaddr) : 0));
            snprintf(acking_user, acking_user_buflen, "\nAcked by: %s", getenv("REMOTE_USER"));
```

変更点を見てもらえばわかりますが、REMOTE_ADDRでIPアドレスを拾っているところをHTTP_X_FORWARDED_FORから拾うように変えています。これで良さそうです。

フロントのリバースプロキシをApacheでやっている場合は、

```apache:httpd.conf
ProxyPreserveHost on
```
で転送先にホスト名を送る必要があります。

このパッチをXymonソースコード群の直下に置いて、reverse_proxy.patchとか適当にファイル名をつけて保存。

```console
$ patch -p1 < reverse_proxy.patch
```
で適応したら、あとはビルドし直します。

これで解決しました。
マルチブラウザ対策について

# マルチブラウザとは

アプリケーションが様々なブラウザ上でも同じ動作をすること。
クロスブラウザともほぼ同義であり、マルチブラウザはアプリケーションの製作者が推奨するブラウザで動作することを保証しクロスブラウザは全てのブラウザで動作することを保証することを意味する。



## マルチブラウザ対策の５つの方法

###　1. cssハック
cssハックとは
ブラウザごとに適応させるcssを変えること


```css:css
/* IE11のみ適応 */
@media all and (-ms-high-contrast: none) {
  *::-ms-backdrop, .selector {
    /* 適用したいスタイル */
  }
}

/* FireFoxのみ適用 */
@-moz-document url-prefix() {
	/* 適用したいスタイル */
}
/* Chrome、Safari、Operaのみ適用 */
@media screen and (-webkit-min-device-pixel-ratio:0) {
	/* 適用したいスタイル（Chrome、Safari、Operaのみ適用） */
}
```

###　2. リセットcssの使用
リセットcssとは

ブラウザでは、デフォルトの余白やフォントの大きさを定義しているため、各ブラウザによってデザインの表示が変わってしまうことがある。
この差異を無くすためにデフォルトで適応されているcssをリセットするためのもの

リセットCSSの読み込み方は、下記の記述をhead内に記述する

```html:html
<!DOCTYPE html>
<html lang="jp">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="パス/reset.css">
  <title>Document</title>
</head>
```



###　3. cssの記述法
padding, margin, borderなど要素ごとのレンダリングは、全てのブラウザで異なる。
なのでcssの記述に工夫が必要

```css:css

/* 横幅が100pxもしくは150pxとブラウザによって表示が変わってしまう */
div{
  width:100px;
  padding-left:50px;
}

/* widthとpaddingを分けて記述すればどのブラウザでも同じ幅で表示される */
div{
  width:100px;
}
div p{
  padding-left:50px;
}

```


###　4. jQueryの使用

javascriptでは、ブラウザ毎に記述することを意識しなければならないが、jQueryはクロスブラウザに対応しているのでブラウザの違いを特に意識する必要はない


###　5. ブラウザ対応状況をチェック
HTML5、CSS3はブラウザによっては使えない場合があるので、プロパティーをブラウザ対応状況を簡単にチェックできるサービス[Can I use](https://caniuse.com/)を使う


<img width="700" alt="スクリーンショット 2020-01-31 0.40.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368036/c7d9a1a4-15d1-c921-66fd-6635e61c072b.png">

使い方は　「Can I use ______ ?」の部分に調べたい要素を入力するだけでどのブラウザで対応しているのかを調べることができる。
Node.jsでお天気を取得してみよう

#はじめに
`OpenWeatherMap API`からお天気情報を取得しようという試みです。
色々な方が、さまざまな言語で同様の記事を上げています。
私は、勉強真っ最中の`Node.js`でやってみようと思いました。
[(Node.jsの導入はこちら)][node]

#環境
`wsl`の環境です。

```
Editor: VSCode
Shell : bash version 4.4.20
Ubuntu: 18.04.4 LTS
node  : v10.14.2
```

#1.APIの取得
[OpenWeatherMap][owm]の公式サイトで無料アカウントを作成後、
表示されるAPIキーを控えておいてください。
APIキー取得後は少し時間をおいてか試したほうがいいと思います。
公式もそういってますし。

#2.プロジェクトを作成
##1.任意の位置(緯度経度)のお天気情報を取得
とりあえず福岡市にしてみました。

```js:app.js
'use strict';

const http = require('http');
const MY_WEATHER_APIKEY = {YOUR_API_KEY};
const LAT = 33.60639;  //緯度
const LON = 130.41806;  //経度
const req = 'http://api.openweathermap.org/data/2.5/weather?lat='+LAT+'&lon='+LON+'&appid='+ MY_WEATHER_APIKEY;

http.get(req, res => {
  var body ='';
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
    body += chunk;
  });
  res.on('end', () => {
    res = JSON.parse(body);
    console.log(res);
  });
})
  .on('error', e => {
    console.error(e.message);
});
```
`{YOUR_API_KEY}`に控えておいたAPIキーを入れてください。

**実行結果**

```bash
$ node scripts/app.js 
{ coord: { lon: 130.42, lat: 33.61 },
  weather:
   [ { id: 803,
       main: 'Clouds',
       description: 'broken clouds',
       icon: '04n' } ],
  base: 'stations',
  main:
   { temp: 286.85,
     feels_like: 284.37,
     temp_min: 285.93,
     temp_max: 287.15,
     pressure: 1018,
     humidity: 58 },
  visibility: 10000,
  wind: { speed: 2.1, deg: 300 },
  clouds: { all: 75 },
  dt: 1587901760,
  sys:
   { type: 1,
     id: 7998,
     country: 'JP',
     sunrise: 1587846896,
     sunset: 1587895019 },
  timezone: 32400,
  id: 1863967,
  name: 'Fukuoka',
  cod: 200 }
```
この結果をいろいろ触って特定の情報を抜き出せます。
> weather:
   [ { id: 803,
       main: 'Clouds',
       description: 'broken clouds',
       icon: '04n' } ]

が欲しければ、`console.log(res.weather);`
> main: 'Clouds'

が欲しければ、`console.log(res.weather[0].main);`
という風にすればいいですね。
おぉ、いま福岡の方は曇りなんですね。

##2.モジュール化
うまくいったので、モジュール化しました。
のちのちモジュール化しておいたほうが使いまわしやすいと思います。

```js:app.js
'use strict';
const weather = require('./weatherFunc');
const MY_WEATHER_APIKEY = {YOUR_API_KEY};
weather.clweather(MY_WEATHER_APIKEY);
```
```js:weatherFunc.js
'use strict';
const http = require('http');

function clweather(api){
  const LAT = 33.60639;  //緯度
  const LON = 130.41806;  //経度
  const req = 'http://api.openweathermap.org/data/2.5/weather?lat='+LAT+'&lon='+LON+'&appid='+ api;
  http.get(req, res => {
    let body ='';
    res.setEncoding('utf8');
    res.on('data', (chunk) => {
      body = body.concat(chunk);
    });
    res.on('end', () => {
      res = JSON.parse(body);
      console.log(res);
    });
  })
    .on('error', e => {
      console.error(e.message);
  });
}

module.exports = {
  clweather
}
```

#さいごに
今後の展望としては、現在地の自動取得とか取り入れていけば、
経度、緯度指定にしていることが活きてきて、
もう少し実用的になると思います。

拙い文章でしたしょうが、お付き合いありがとうございました。

さよなら:wave:

#関連記事
- [Linux環境におけるNode.jsの導入から利用][node]


#参考
- [OpenWeatherMap][owm]
- [node.jsでOpenWeatherMap APIから天気情報を取得][api]




[owm]:https://openweathermap.org/
[api]:https://yoheikoga.github.io/2016/08/14/open-weather-map-by-nodejs/
[node]:https://qiita.com/RoaaaA/items/17df30bf9400edfb7fb3
【入門】ソフトウェアテスト

# 1. 記事作成の理由
・職場で結合テストをアサインされたが、人員に限りがあるため、適切にテストケースを絞り込む必要がある。
・仕事で、初めてのテスト設計とテスト実施に取り組んでいるため。

# 2. 参考文献
以下の図書を参考に本記事を作成。
高橋寿一 著、株式会社翔泳社、「知識ゼロから学ぶソフトウェアテスト」、2013年12月
AmazonのURL：https://www.amazon.co.jp/%E7%9F%A5%E8%AD%98%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88-%E3%80%90%E6%94%B9%E8%A8%82%E7%89%88%E3%80%91-%E9%AB%98%E6%A9%8B-%E5%AF%BF%E4%B8%80/dp/4798130605/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1581396780&sr=8-1

# 3. 内容
## 3.1. 目次
参考文献の目次を以下に示す。

```目次
１章：はじめに
２章：ソフトウェアテストの基本（ホワイトボックステスト）
３章：エンジニアが最もよく使う手法（ブラックボックステスト）
４章：探索的テスト
５章：機能あらざるもののテスト、最難関のテストに挑む（非機能要求のテスト）
６章：ソフトウェアテスト運用の基本（テスト成功の方程式）
７章：ソフトウェア品質管理の基本（ソフトウェア品質のメトリックス）
８章：テストの自動化という悪魔（なぜ自動化は失敗するのか）
９章：それでもテストがうまくいかない人へ
```

## 3.2. テスト担当者心得
a)

```
バグを全部見つけるのは無理だと心得よ（Cem Kaner）
```

ソフトウェアは十分複雑な工業製品。
b)

```
バグは特定の部分に偏在している。
```

一説にはバグの47%は、プログラムの4%に偏在しているという。
c)

```
ソフトウェアで重要なのは、どの部分にバグが出やすいのか、
そこにどのようなテスト手法を適用すれば
十分な品質を得られるかを知ることである。
```

闇雲にやるのではなく、バグが起きそうな場所を重点的にやる。

d)

```
「品質向上のための投資は、投資額が修正にかかる費用を超過するか、『もっとマシなことをすべきだ』と誰か言い出すまで増加し続ける。」
```

完璧なソフトウェアは作れないが、適切な品質を担保することで「十分な」品質をもつソフトウェアを作る。


e)

```
テストコードを書ききるのは学生でもできるが、テストケースを書き切るのは難しい。
```

以下のプログラムを例に、テストケースを書き切れるかどうかが重要。

<例題>
「このプログラムでは、ユーザーが三つの整数を入力します。この三つの値は、それぞれ三角形の三辺の長さを表すものとします。
　プログラムは、三角形が
　　不等辺三角形
　　二等辺三角形
　　正三角形
のうちのどれであるかを決めるメッセージを印字する。
このプログラムをテストするのに十分と思われる一連のテストケースを書いて下さい。」

答えは、参考文献を参照ください。

## 3.3. テスト基本(ホワイトボックステスト)
・プログラムの論理構造が正しいかを解析するテスト
・制御パステストは、カバレッジ率をとるために使われるテストであるため、基本的に実施。
　　ステートメントカバレッジ・・・処理単体のテスト。実施は簡易だが、条件漏れなどに対応しきれない。
　　ブランチカバレッジ・・・分岐をテスト。テストケース数が増えるのが欠点。
・カバレッジ基準を設けて、テスト計画を立てる。目処は以下の通り。
　a) 通常の商用テストならば60~90%。
　b) ヒューレットパッカード社の調査では、高いと80%。低いと20%。


## 3.4.　よく使われる手法（ブラックボックステスト）
・ソフトウェアは、以下の四つから構成される。
　a) 入力処理
　b) 出力処理
　c) 計算
　d) データ保存

・同値分割法と境界値分析は、a)入力処理とb)出力処理をチェックできる。
・複雑な入出力のためのテストとして、ディシジョンテーブルテストがある。
　全ての入力の組み合わせを表にし、その入力に対する動作もしくは出力を明記する。

　表には、
　1.状態
　2.ルール（状態の組み合わせ）
　3.動作（アクション）

・状態繊維テストは、GUI、オブジェクト指向ソフトウェア、通信プロトコルテストに有用。
・テストでのバグの発見率は60%程度が現実。とっとと60%のバグを見つけて、そのほかのバグがなぜ発生したか、そしてどうやって防止するかに時間を費やすのが有用。


## 3-5.テストプランの書き方
・テストプランのテンプレートは、「IEEE 829」を使われることが多い。
・テストケースは、再現性が高くないとダメ。ツールを使うと楽。
　ツール例：Testlink
・テストケース数は、10~15行に一つ程度が多い。（日立ソフト）


## 3-6.品質管理の基本
・サイクロマチックメトリクスは有用。

# 4.まとめ
・教科書を読み切った結果、テストだから100%のカバーをしなくてはいけないと肩に力が入っていたが、適度に力が抜けた。
【Laravel】MAMP環境にLaravelをインストールする方法

#①MAMPのhtdocsにディレクトリ移動

ターミナルを開き、下記コマンドを入力。

```
$ cd /Applications/MAMP/htdocs
```

#②Laravelプロジェクト作成

htdocs配下において、下記コマンドを入力。

```
公文）
$ composer create-project laravel/laravel プロジェクト名 --prefer-dist "6.0.*"
例）
$ composer create-project laravel/laravel laravel_test --prefer-dist "6.0.*"
```

#③対象プロジェクトのディレクトリに移動

htdocs配下において、下記コマンドを入力。

```
公文）
$ cd プロジェクト名
例）
$ cd laravel_test
```

#④サーバ起動

③で作成したディレクトリ配下において、下記コマンドを入力。

```
$ php artisan serve
```

#⑤サーバ起動確認

ブラウザを開き、下記にアクセス。
http://127.0.0.1:8000

#⑥サーバ停止

「control」 + 「c」 を同時に押下
買ったばかりのまっさらなmacに最低限の環境構築

何気に初投稿。自分のための覚え書きの意味合いがほとんどなので、間違いや見辛さはご勘弁ください。

## 必要と思われるもの

* homebrew

GUIでインストールできなかったりするものをインストールしてくれるツール
依存関係のパッケージとかもいい感じに入れてくれるやつ
インストールは下のURLからどうぞ
https://brew.sh/index_ja

* xcode

正確にいうとxcode全て必要なわけではなく、「Xcode Command Line Tools」のみインストールできればいいらしい。以前はhomebrewインストールする前に「Xcode Command Line Tools」を入れてる必要があったんだけど、今はhomebrewをインストールすると途中で「Xcode Command Line Toolsも入れる？」って聞いてくれるので、それに従えば一緒に入れてくれる。便利だなぁ。

* nodebrew

Node.jsのバージョン管理ツール。こいつを使ってNode.jsをインストールします。

* Node.js

npm使う時とか必要なんで使う場合は入れましょう。

## GUIでインストールしたもの
* chrome
* vscode
* iterm
* slack
* docker for mac


## 参考記事
* https://fukatsu.tech/homebrew#Xcode_Command_Line_Tools
* https://protoout.studio/posts/mac-setup-202001
RubyでBOM付UTF-8のCSV(Excelで直接読めるCSV)を出力する方法

# Excelで読み取れるCSV

文字コード UTF-8 のCSVファイルをExcelで開くと、以下のように文字化けする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111137/7456b981-c557-60cd-0076-65a27e931116.png)


文字化けをさせないためには先頭にBOM(バイトオーダーマーク)を付ける必要がある。

#RubyでBOMを出力するサンプル
```rb:bom.rb
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

# BOMを出力する
putc 0xEF
putc 0xBB
putc 0xBF
# CSVを出力する
puts 'ID,名前'
puts '1,山田'
puts '2,田中'
puts '3,坂本'
```
# 実行
```
./bom.rb > excel.csv
```
とするとExcelで読み込めるCSVファイル(excel.csv)ができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111137/ef6be30b-c7da-5a34-739b-64d89146ad9f.png)
[systemd] サービスを削除するときのコマンド

# 参考

[こちらがとても分りやすく参考になりました！](https://amzn.to/2zNLPdf)

# 方法
```
systemctl stop [servicename]
systemctl disable [servicename]
rm /etc/systemd/system/[servicename]
rm /etc/systemd/system/[servicename] symlinks that might be related
systemctl daemon-reload
systemctl reset-failed
```
【Linux】コマンド基礎(cd ls cp)

#####CentOS8をインストールしました。
##cdコマンド
作業するディレクトリを移動することが出来る。cd ドキュメントでドキュメントに移動。cdで元のディレクトリに戻る
![ls_cd.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611776/27ef7ab3-1970-ae70-4649-28aa3f44338f.jpeg)

##lsコマンド
ディレクトリの中のディレクトリやファイルを一覧表示する。ディレクトリ参照方法について（*は任意の文字列を示している、?は文字数が分かっている場合に使う）

##lsコマンド　-lオプション
ディレクトリを指定した場合、最初にトータルのブロック数を表示してからディレクトリ内のファイルの情報を表示する。情報が長形式で表示される

##ls　-ltオプション
ファイルが更新時刻の新しい順に並ぶ

##lsコマンド　-laオプション
ドットで始まるファイルは隠しファイル（システム設計が書かれているファイルで主に行われている）-laと下記は全て同じ

```;出力
ls -la
ls -al
ls -l -a
ls -a -l
```

##cpコマンド
lesson01 lesson02というファイルを事前に作り、lesson01のファイルをlesson02のファイルに上書きしました。事前に作ってないLesson07ファイルを、cpコマンドによってlesson01のファイルをlesson07というファイルを新しく作ってその中にlesson01のファイルをコピーしました。
![cp.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611776/03f209dd-8cba-1f3d-f36a-b732f2e8845b.jpeg)


##cp -pオプション
lesson01 と lesson02のタイプスタンプを同一ファイルとしてコピーする

```;
cp -p lesson01 lesson02
```

##mkdirコマンド
ディレクトリを作成する

```;
mkdir  div01 div02
```


##環境構築
#####windowsでLinuxディストリビューションであるCentOS8と仮想化ソフトウェアである[VirtualBox](https://www.virtualbox.org/wiki/Downloads)をインストールしました。参考文献は[Linux標準教科書](https://linuc.org/textbooks/linux/)をダウンロードしました。

## 参考文献
> CentOSはサーバーで活躍しているOSだ。仕事ならRedHat系。
[【目的別】初心者におすすめのLinuxディストリビューション7選](https://eng-entrance.com/linux_beginner_distribution#_Debian)
ActiveModel::SerializerのRspec

### はじめに

SerializerのRSpecについて備忘録で残しておきます。

参考にしたのは[こちらのドキュメント](https://www.rubydoc.info/gems/active_model_serializers/0.9.4)

### ソースコード

Serializerを使って、`id`、`name`、`email`のみを返すjsonを実装しました。

```rb:user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  attribute :id
  attribute :name
  attribute :email
end
```

そのテストコードがこちら

ポイントだと思うところはこちらの2つ
1. **Serializerのインスタンス**を生成する必要がある
2. **`.to_json`メソッドのオプション**を使用して、返ってくるデータのカラムを指定する必要がある

アソシエーションがある場合は、`include`オプションを利用するとうまいこと書けると思います。

```rb:user_serializer_spec.rb
require 'rails_helper'

RSpec.describe "UserSerializer", type: :serializer do
  context "when create user" do
    let(:user) { create(:user) }
    it "matches to serialized JSON" do
      serializer = UserSerializer.new(user)
      expect(serializer.to_json).to eq(user.to_json(:only => [:id, :name, :email]))
    end
  end
end
```
競技プログラミングでよく出てくる書き方

input = gets.split.map(&:to_i)

gets・・キーボードで入力した値を文字列で取得

split・・文字列を分割して配列にする、引数を指定しないばあい、空白文字で区切られる

map・・配列の要素の数だけ繰り返し処理を行う、collectと同じ
あやしいアクセス元の3分調査方法(初心者向け)

ふと怪しいアクセス元を見つけてしまったときに、どのくらい危険かをなんとなく3分くらいで調査する方法です。
本格的な調査の必要があるかどうかの判断材料の一つとして使えると思います。
なお、白の証明をするものではないので、ご注意ください。

## 役立つケース
* サイト運営をしていて、アクセス解析で極端に数の多いアクセスを見つけて、不安になってしまったとき
* Webサイトのアクセスログを確認すると、不審なリクエストが含まれていて、不安になってしまったとき

## 活用サイト
| サイト名 | 概要 | URL |
| ---- | ---- | ---- |
|  AbuseIPDB | 悪意のある活動(ポートスキャンや脆弱性スキャン等)に関連付けられたIPアドレスを報告、検索可能なサイト | https://www.abuseipdb.com/ |
|  SANS Internet Storm Center | インターネット定点観測のデータを検索可能なサイト | https://isc.sans.edu/ |
|  AlienVault - Open Threat Exchang | IoC(Indicator of Compromise)※情報を交換できるプラットフォーム | https://otx.alienvault.com/ |
※攻撃されたことを示す痕跡の情報であり、代表的なものとしてURL、Domain、IPアドレス、ハッシュ値等がある。

## 活用方法（例）
* 調査対象IPアドレス(自分のブログのIPアドレス、無害なもの)  
  13.115.18.61
  (https://moneymog.hatenablog.com/)

### AbuseIPDB
IPアドレスの概要と悪意のある活動報告を確認します。

1-1. IPアドレスの入力
<img width="552" alt="1-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/4d287385-aefe-32fc-22eb-16ea38560abb.png">

1-2. IPアドレス概要の確認
<img width="268" alt="1-2-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/814e0938-9524-b2d3-71dd-a6927154d4e4.png">

(参考)悪意のある活動報告がある場合の表示
Confidence(信頼性)が高いほど黒っぽいと判定
<img width="268" alt="1-2-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/536dceaf-f1bb-8af7-be24-3934252889ac.png">

1-3. 悪意のある活動報告の有無を確認(今回はなし)
<img width="559" alt="1-3-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/e6dc9bb8-7426-01a0-9394-c8c638378332.png">

(参考)悪意のある活動報告がある場合の表示
<img width="553" alt="1-3-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/081ad5e7-443b-d36d-bd78-2d3490093f08.png">

### SANS Internet Storm Center
定点観測上のデータにIPアドレスからアクセスが記録されているかどうかを確認します。

2-1.IPアドレスの入力
<img width="320" alt="2-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/4d6a506f-a4b2-e4c6-2ad1-571dbd1b3d41.png">

2-2.定点観測上のデータを確認(今回はなし)
<img width="641" alt="2-2-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/7bf37da1-c793-0a2a-61fe-7c6b2c975101.png">

(参考)定点観測上のデータがある場合の表示(Reportの数字をクリック)
<img width="143" alt="2-3-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/942c28b2-9337-4964-3741-56c9dc51a6eb.png"> → <img width="628" alt="2-3-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/e45639b2-f3a1-7926-12ed-2de5db6bd8cb.png">

### AlienVault - Open Threat Exchang
IPアドレスに関係する攻撃情報を確認します。

3-1. IPアドレスを入力(虫眼鏡をクリックしてから入力)
<img width="271" alt="3-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/bc72df57-c63c-fc13-a78d-d8e50aafab82.png">

3-2. Related Plusesの有無の確認
今回は有りですが特定の攻撃に紐づくIoCではないため、黒判断は要検討です。
<img width="479" alt="3-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43704/b55eb365-9abc-783e-6e38-5762bf12bb69.png">


##
各ブログ（[はてブ](https://moneymog.hatenablog.com/)、[Qiita](https://qiita.com/moneymog)、[Note](https://note.com/moneymog)）の更新やセキュリティニュース等を
Twitter（[@moneymog](https://twitter.com/moneymog)）でお知らせしています。
よろしければ、フォローください。
[Swift]Realm Swift #2 - サンプル

iOS で`Realm　Swift`  を 利用し、サンプルを作成してみました。

## 目次
[・Realm Swift #1 クラス](https://qiita.com/mario7/items/2df2c3e172f15f1d07cb)
・ Realm Swift #2 サンプル
[・ Realm Swift #3 トラブル対応](
https://qiita.com/mario7/items/d10170fb649acd05dcd3)

#  サンプル
※　Source: [RealmStudentAccess.swift](https://github.com/mario7/studyForiOS/blob/realmJsonSample/realmAndJsonSample/realm/RealmStudentAccess.swift)

##Ream 定義

```Student.swift
import RealmSwift
class Student: Object, Codable, NSCopying {
    @objc dynamic var studentId = ""
    @objc dynamic var name = ""
    @objc dynamic var age = 0
    
    override static func primaryKey() -> String? {
        return "studentId"
    }
```
[JSON]

```json
{
"name": "jane",
"age": 12,
"studentId": "1"
}
```

##レコードの追加

```RealmStudentAccess.swift
 //guard let data = dataStudentStr.data(using: .utf8) else {...}
 let obj = try JSONDecoder().decode(Student.self, from: data)
 try manager.add(obj: obj)
```
[結果ログ]
<img width="355" alt="スクリーンショット 2020-04-26 22.23.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101832/92600e07-d735-eb3d-c7a4-da1846c0b208.png">


##レコードの更新

```RealmStudentAccess.swift
try manager.update(obj: student) {
     student.name = "test"
     student.age = 20
     print("2.update => findFirst updateStudent:" + student.description  )
}
```
[結果ログ]
<img width="372" alt="スクリーンショット 2020-04-26 22.17.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101832/d6d9607c-ccfa-1a52-99fd-45b4fe1cb1c6.png">


##レコードの削除

```RealmStudentAccess.swift
//guard let primaryKey = manager.getPrimaryKey() else {...}
try manager.deleteWithQuery(query: "\(primaryKey) == '2' ")

```
[結果ログ]
<img width="314" alt="スクリーンショット 2020-04-26 22.17.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101832/c7ad8aea-7726-c94e-e4b7-923e5fd2e300.png">


##レコード検索

```filter
let student =  manager.findByPrimaryKey(key: "1") 
```
[結果ログ]
<img width="333" alt="スクリーンショット 2020-04-26 22.17.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101832/2dda726b-ad2e-a51a-eaf3-a5a336e3d412.png">

# index

[≪　Realm Swift #1  クラス](https://qiita.com/mario7/items/2df2c3e172f15f1d07cb)　　ーーー　　[Realm Swift #3 トラブル対応 ≫](
https://qiita.com/mario7/items/d10170fb649acd05dcd3)
CFBundle、NSBundleからAPIで参照できるディレクトリ一覧

## 概要

CFBundleやNSBundleからはAPI経由で動的にBundle内の標準ディレクトリを参照できますが、それぞれ具体的にどこだったら分からなくなるため、SafariをBundleとした場合を例にまとめました。

## 手順

以下のコードで`/Applications/Safari.app`をからBundleオブジェクトを作成したあと、各種パスを取得しました。

```C++:CFBundleの場合
/* Safariの場所を指定してCFURLを作成 */
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
                                                   CFSTR("/Applications/Safari.app"),
                                                   kCFURLPOSIXPathStyle,
                                                   true);
/* SafariのBundleを作成 */
CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);

/* 各種パスのURLを取得 */
CFURLRef folderURL = /* 今回試すAPIのいずれか */

/* CFURLから絶対パスを取得してログに表示 */
UInt8 buffer[512] = {0};
CFURLGetFileSystemRepresentation(folderURL,
                                 true,
                                 buffer,
                                 sizeof(buffer));
CFStringRef path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, 
                                                              (char*)buffer);
CFShow(path);

CFRelease(path)
CFRelease(bundleURL);
CFRelease(bundle);
```

```objc:NSBundleの場合
/* Safariのパスを渡してNSBundleを作成 */
NSBundle* bundle = [NSBundle bundleWithPath:@"/Applicaitons/Safari.app"];
NSURL* url = [bundle /* 今回試すAPIのいずれか */];
printf("%s", url.fileSystemRepresentation);
```

## CFBundle

CFBundleからはCFURLRefの形で返却されます。
絶対パスに直したものを記載しています。

|API |返却されるパス |
|--------|--------|
| CFBundleCopyBundleURL | /Applications/Safari.app |
| CFBundleCopyAuxiliaryExecutableURL [^1] | /Applications/Safari.app/Contents/MacOS/Safari |
| CFBundleCopyBuiltInPlugInsURL | /Applications/Safari.app/Contents/PlugIns |
| CFBundleCopyExecutableURL | /Applications/Safari.app/Contents/MacOS/Safari |
| CFBundleCopyPrivateFrameworksURL | /Applications/Safari.app/Contents/Frameworks |
| CFBundleCopyResourcesDirectoryURL | /Applications/Safari.app/Contents/Resources |
| CFBundleCopySharedFrameworksURL | /Applications/Safari.app/Contents/SharedFrameworks |
| CFBundleCopySharedSupportURL | /Applications/Safari.app/Contents/SharedSupport |
| CFBundleCopySupportFilesDirectoryURL | /Applications/Safari.app/Contents |

## NSBundle

CFBundleとほぼ同じですが、`SupportFilesDirectoryURL`が消え`appStoreReceiptURL`が増えています。
今回はNSURLを取得しましたが、NSStringの形でpathを取得することもできます。


|API |返却されるパス |
|--------|--------|
| bundleURL | /Applications/Safari.app |
| URLForAuxiliaryExecutable [^2] | /Applications/Safari.app/Contents/MacOS/Safari |
| builtInPlugInsURL | /Applications/Safari.app/Contents/PlugIns |
| executableURL | /Applications/Safari.app/Contents/MacOS/Safari |
| privateFrameworksURL | /Applications/Safari.app/Contents/Frameworks |
| resourcesURL | /Applications/Safari.app/Contents/Resources |
| sharedFrameworksURL | /Applications/Safari.app/Contents/SharedFrameworks |
| sharedSupportURL | /Applications/Safari.app/Contents/SharedSupport |
| appStoreReceiptURL | /Applications/Safari.app/Contents/_MASReceipt/receipt |



[^1]: 第2引数にはNULLを指定。
[^2]: 引数には"Safari"を指定。
個人的に自主学習に向く言語（メモ）

プログラミング学習におすすめな言語

クライアントサイド：HTML・CSS・JavaScript
サーバサイド：Java・PHP・Python

クライアントサイドは元々これしか種類が無いので、割愛。
デザイナー職でないなら、基本のみ抑えておけばそれでOK。

サーバサイドの言語それぞれの利点
①Java
迷ったらコレ。基礎を学ぶ上で非常に整理されている。
企業で多く採用され、規模の大きいプロジェクトでもよく使用される。
②PHP
基礎よりも、とにかく作ってみる人向け。Javaよりも習得が容易。
小回り重視の仕事が多く、改善や提供を繰り返すような仕事に多い。
ベンチャー向け。
ミニマムなVue.jsコンポーネントプログラミングその2(ルータ実装)

前回、"Hello, vue.js"を静的にレンダリングするだけのミニマムなシングルコンポーネントを持ったプロジェクトを作成しましたので、それをベースに拡張していきたいと思います。今回の趣旨はミニマムなルータ制御です。SPA的なクライアントアプリを組むためにはルータ機能が必要です。

やるべきことは、以下です。

- App.vueは(ほぼ)抽象的なアプリケーションコンポーネント(画面の入れ物)とする。
- 唯一の画面として、Home画面(コンポーネント)を追加する。
- vue-routerでHome画面を表示させる。

#Home画面作成
h1要素を持つだけのシンプルなコンポーネントです。vue-cliが自動生成してくれるようなフォルダ構成でちまちま作っていきます。

src/vies/Home.vue

```html
<template>
  <div>
      <h1>これはほーむがめんです</h1>
  </div>
</template>

<script>
export default {
    name: 'Home'
}
</script>
```

#ルータ追加
画面遷移をコントロールするルータを追加します。

(1)ルータライブラリインストール

```
npm install vue-router
```

(2)ルータ実装(src/router/index.js)

```javascript
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue' 

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    }
]

const router = new VueRouter({
    routes
})

export default router
```
ルート('/')とHome画面(コンポーネント)を連結させただけの
ミニマムなルータです。


(3) Vueインスタンスにルータ追加(src/main.js)

```javascript

import Vue from 'vue'
import App from './App.vue'
import router from './router'    <== ココ

Vue.config.productionTip = false

new Vue({
  router,                        <== ココ
  render: h => h(App),
}).$mount('#app')
```
こうやって、Vueインスタンスにいろんな機能モジュール(コンポーネント)を突っ込んでおくと、Vueインスタンスに対してフレームワークがいろいろよしなにさばいてくれるんですねぇ。

こうしてながめると、router/index.jsで作ったルータも一種のコンポーネントとしてとらえたほうがいいかな。


(4) Appコンポーネントにルータ(によるView)を埋め込む(src/App.vue)

```html

<template>
  <div>
    <router-view/>    <== ココ
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
```
npm run serveして、localhost:8081すると、
![範囲を選択_012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244766/0c3596ad-1773-cc6b-7210-2d56c368ac46.png)


#補足
今回のやったことはつまり、

1. 抽象的なアプリケーションコンポーネントを用意する。
   (複数の画面を持つアプリケーションとして、Appコンポーネントを定義する)
2. HOME画面を用意する。
3. '/'をHOME画面と接続したルータ用意。
4. アプリケーションにルータをジョイント。

って感じです。

次はサブコンポーネントを扱っていきたいと思います。
Azure SDK for Goを使う上での開発者向けツール

「[Azure SDK for Go documentation](https://docs.microsoft.com/ja-jp/azure/developer/go/)」サイトの「[Tools for developers using the Azure SDK for Go](https://docs.microsoft.com/ja-jp/azure/developer/go/azure-sdk-tools)」ページを読み進めました。

本セクションでは、Azure SDK for Goを使用する上でGoコードを効率的に記述したりAzureサービスとシームレスに連携したりする開発者向けツールが紹介されています。

ここでは、対象ページの内容をベースとして、私なりの解説を加えてみます。

### Azure CLI

AzureにはAPIを操作する方法として、WebブラウザーでログインしてのGUI操作、Azure SDKを使ってのコード操作の他に、Azure CLIによるコマンドライン操作が用意されています。

- [Install the Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)

Azure CLIは az コマンドで操作を行い、Windowsは実行バイナリーで、macOSとLinuxはPython 3スクリプトでインストールされます。またDockerやAzure Cloud shellでも実行可能です。

CLIのメリットは、コマンドライン上で他のコマンドと組み合わせて一連の処理をスクリプト化して実行できる柔軟性の良さが挙げられます。

個人的には、Goのマルチプラットフォーム向けに処理速度の良さも含めた実行バイナリーを提供できるメリットを生かして「Azure CLIこそGoで！」と思うのですが、如何でしょうか？（Google社のパブリッククラウド「[Google Cloud Platform](https://cloud.google.com/)」のCLIツールである[gcloud](https://cloud.google.com/sdk/gcloud)コマンドにも同様に思うところ）

### Visual Studio Code

Visual Studio Code（以下、vscode）は、Microsoft社が提供しているオープンソースのコードエディターで、エクステンション（いわゆるプラグイン）をインストールすることで機能拡張でき、オートコンプリート、実装テンプレート、リファクタリング、デバッグなどの機能が追加されます。

- [Install Visual Studio Code](https://code.visualstudio.com/Download)

Goコードを効率的にコーディングするためのエクステンションとして「ms-vscode.Go」がMicrosoft社員にて開発＆サポートされており、デバッガーとして「[delve](https://github.com/go-delve/delve)」が対応しています。

- [Get the Visual Studio Code Go extension](https://code.visualstudio.com/docs/languages/go)

2015年11月のvscodeのベータ版の公開時にms-vscode.Goも紹介され、当時はGopherとして「Microsoft社がGoへの取り組みもしっかり行なっている！」と感動しました。

- [［速報］無償のコードエディタ「Visual Studio Code」が、Go言語/Pascal/Reactなどに対応。ベータ版にも到達。Microsoft Connect(); 2015 － Publickey](https://www.publickey1.jp/blog/15/visual_studio_code_go_pascal.html)

本セクションでは、Azure サービスと連携するためのエクステンションがまとめられた「Azure Extension Pack」も紹介されていますが、

- [Get the Visual Studio Code Azure Tools extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-azureextensionpack)

リンク先のエクステンション提供サイト「[Marketplace](https://marketplace.visualstudio.com/vscode)」では非公開（unpublished）になっているため、今後は個々のAzureサービス用のエクステンションをインストールして使用することになります。

### Azure DevOps プロジェクトでのCI/CD

Azure上にデプロイしているGoアプリケーションを継続的インティグレーション／継続的デリバリー（CI/CD：Continuous Integration／Continuous Delivery）するには、Azure DevOps Project パイプラインを使用します。これにより、gitリポジトリー上のGoアプリケーションのソースコードを直接Azureにデプロイしてテストすることができます。

- [Learn how to create a CI/CD pipeline with Azure DevOpw project](https://docs.microsoft.com/en-us/azure/devops-project/azure-devops-project-go)

### depによる依存関係管理

Azure SDK for Goは、パッケージ（ライブラリー）の依存関係管理にdepを使用しています。

- [Get the dep dependency manager](https://github.com/golang/dep)

depはGoでパッケージ依存管理を行うためのプロジェクトとしてスタートしました。現在のGo本体には、これらの成果を反映した「[Go Modules](https://github.com/golang/go/wiki/Modules)」が実装されています。Go Moludesの採用によりdepの開発も収束しており、今後はAzure SDK for GoもGo Modules化が進むと思われます。
Railsのダウングレードでハマった話

#Railsのダウングレードでハマった話
Railsのダウングレードでハマってしまった内容を記録します。
初歩的なミスですが、同じような初心者の方に参考になればと思います。

## 目次
* [動作環境](#動作環境)
* [問題](#問題)
* [原因と解決法](#原因と解決法)
* [学んだこと](#学んだこと)

---------------------------------------
## 動作環境
`OS : macOS Mojave 10.14.6`
`ruby : 2.6.3p62`
`rails : 5.2.4.2 -> 5.2.3`

##問題
ローカル開発環境をRails 5.2.4.2 -> 5.2.3にダウングレードする必要がありました。
Railsをアンインストール -> 指定バージョンをインストールしても、
なかなかバージョンのダウングレードができない状況でした。

#### 既存バージョンのRailsのアンインストール
`1. gem uninstall rails 5.2.4.2`
`2. gem uninstall railties 5.2.4.2`

#### 指定バージョンのRailsのインストール
```bash
gem 'rails', '~> 5.2.3' # Gemfileに記載
```
```bash
bundle install 
```
```bash
rails -v #バージョン確認
Rails 5.2.4.2 #変わっていない。
```

## 原因と解決法
Gemfile内のこの~>部分がある場合は指定されたバージョン以上で最新のものが利用されるとのこと。
つまり 5.2.3を利用するなら~>を使わずに記載します。

*バージョン指定についてはこちらの記事が参考になりました。
https://qiita.com/awakia/items/5745938c192ca1139c63

```bash:誤
gem 'rails', '~> 5.2.3' # 5.2.3以上5.3.0未満のなかで最新のもの。5.2.4.2がインストールされてしまう。
```

```bash:正
gem 'rails', '5.2.3' # 5.2.3を使用!
```

```bash:
bundle install #改めてgemをインストール
rails -v 
Rails 5.2.3 #指定のバージョンに変わりました。
```

## 学んだこと

今回の件で以下のことを学びました。
1. `gemfile`の`~>`は記載されたバージョン以上で最新のものがインストールされる
windows10にpython3.8+venvでjupyter notebookを作成する

# 前言
anacondaを推奨していますが、でも重いなあで、今回はpipを使ってインストールしています。
# Pythonをインストール
割愛します。
# venv仮想環境の作成
```
python -m venv myvenv
```
# venv仮想環境を有効化
PowerShellに実行するとき、「セキュリティ エラー: (: ) []、PSSecurityException」エラーの場合、管理者でPowerShellを起動して、「Set-ExecutionPolicy RemoteSigned」を実行します。

```
Set-ExecutionPolicy RemoteSigned
.\myvenv\Scripts\activate
```
# venv仮想環境を無効化(必要な場合)
```
deactivate
```
# venv仮想環境を削除(必要な場合)
```
rm -rf myvenv #delete folder
```
# Jupyterをインストール
```
pip install jupyter
```
# 好きなFolderにJupyterを起動
```
cd xxxx
jupyter notebook
```
localhost:8888にサーバーが立ち上がり、自動的にブラウザが開かれます。
AWSのCI/CDを体験するのに「Amazon Web Services アプリ 開発運用入門」をトレースして詰まったところ一覧

今自社のサービスをAWS上で運用していますが、CI/CDの仕組みを整備しなければなあと思っていたところで、ひとまずAWS上で提供されているCI/CDサービスをさらっと理解したく、「Amazon Web Services アプリ 開発運用入門」をトレースしてみました。

https://www.amazon.co.jp/dp/B07PHQS6NZ/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

AWSが提供するCI/CDサービスの中で、本書では以下の利用を体験できます。

- CodeCommit : ソースコード管理サービス
- CodeBuild : ビルドサービス
- CodeDeploy : デプロイサービス
- CodePipeline : リリースプロセスの自動化サービス

いずれもAWSではごく当たり前となっているフルマネージドサービスで、利用者からするとごく簡単なCUI, GUI経由の操作だけで環境構築ができます。

参考までに、フルマネージドサービスの定義を[こちら](https://www.gixo.jp/blog/4611/)から引用しておきます。

>「フルマネージドのサービス」は、利用者がサービスを利用する際に、「コンピュータ障害監視・バックアップ・ソフトウェアのバージョンアップ」など「運用に関わる作業」をクラウド業者が行ってくれる形態のサービス

最終目的である、CodePipelineでのCI/CIパイプラインの構築がChapter4（全部でChapter8あります）ですが、Chapter4まで終えるのに、自分の場合2時間程度で済みました。

内容がそんなに濃くない？とも言えますが笑、さらっと体験したい方には打ってつけではあると思います。

さて、本書の内容は手取り足取り丁寧な内容となっているので、書籍の発行日が2019年2月1日で本記事執筆日(2020/4/26)から1年以上前であるものの、多少の画面の変更はありつつ、今でも十分トレースできる内容となっています。

ですが、一瞬詰まったところがないではなく、せっかくなのでメモしておきます。

### Chapter2-2 Step9 Gitクライアントの設定

GitクライアントにAWS CLIの認証情報ヘルパーを使用する設定するプロセスがあります。

ここで以下のコマンドを実行しろ、とあります。

```sh
$ git config --global credential.helper "!aws codecommit credential-helper $@"
```

しかしこのまま先のプロセスに進むと、ローカルレポジトリからコミットをプッシュする`git pull`時にusernameを聞かれてしまい、認証情報の設定がうまくいっていないことが分かります。

原因と対処方法は[こちらの記事](https://qiita.com/Masayuki-M/items/2f92aea42fa415d44cc5)にありました。

`vi ~/.gitconfig`でgitconfigの内容を確認してみると、

```
[credential]
helper = "aws --version codecommit credential-helper "
```

となっているので、これを修正しましょう。

```
[credential]
helper = "!aws codecommit credential-helper $@"
```

### Chapter2-3 Step1 CodeCommitリポジトリURLを取得

リポジトリのURLのクローンのところで、「HTTPSのクローン」が指定されています。

これで初回のリポジトリアクセスは可能なのですが、しばらく経ってからアクセスすると、

```sh
$ git pull origin master
fatal: unable to access 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/awesome-app/': The requested URL returned error: 403
```

と、403エラーが返ってきてしまいます。

これの原因と対処方法ですが、[こちらの記事](https://qiita.com/szk3/items/f346d5c1804653d8b35a)にありました。以下、引用します。

>OSXにプリインストールされているGitは、credentialを保存するのにKeychain Accessを使います。ですが、セキュリティ上の理由からCodeCommitへアクセスするためのcredentialはテンポラリなものであるため、リポジトリに初回アクセスした際に保存されたcredentialは約15分後には使えなくなります。

なんと。そういう仕様にせざるを得ないんでしょうか。

とにかく、Keychain Accessは運用上は使えないので、引用記事中に示されているいずれかの方法を代替として対処する必要があります。

個人的には、sshでアクセスするのが最も楽で、環境も汚さなくて良いと思います。

手順は以下公式にある通り。手順通りにやれば問題なくできます。

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-ssh-unixes.html

### Chapter4-3 Step1 アプリケーションの差分ファイルをリポジトリにマージ

最後に、些細な点。

アプリケーションの差分ファイルが含まれる4-3.zipのsrcディレクトリに、Application.javaが含まれていないので、srcディレクトリごと上書きするとbuildに失敗します。

ここは表示メッセージを書き換えるだけですし、HelloWorldController.javaを直接書き換えてしまうのが良いと思います。

### AWSのCI/CDサービスに対する所感

実際にCodePipelineでリリースプロセスの自動化を体験してみましたが、一度パイプラインを作ってしまえばデプロイまでは非常に早く、開発環境のようにテスターとインタラクティブにやりとりしたい環境ではなかなか有用ではないかと思いました。

CodeCommitについてはGitHubやBitbucketといった他のVCSと比較して細かい機能が十分でないという話を聞いたりするので、実際に業務で利用するには「痒いところに手が届かない」があるのかもしれませんが、CodeCommitの代わりにGitHubを使うことはできるので、マイクロサービスとしての利点を生かせばやはり有用なのかなと思っています。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-github-pull-request.html

あとはAWSのサービスに限らないですが、CI/CDのプロセスを作り込むことでリリースプロセスの柔軟性はなくなるわけなので、人間がプロセスに合わせていくのか、プロセスを人間に合わせていくのか、という問題は残るかと思います。
Unity ContentSiaeFitterのHorizontalFitのモードをスクリプトから選ぶ方法

これも分かり辛かったのでメモ。

```c#
var fitter = object.GetComponent<ContentSizeFitter>();
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
```

最後のPreferredSizeはモードの種類なので、好きなものを選んでください。
Python（Python 3.7.7 ）のインストールおよび基本文法

pythonをインストールして基本文法を平たくまとめました。
何らかのPG言語に取り組んだ事のある人であれば見ただけで理解できるような記事にします
**都度ブラッシュアップしていきたいと思います**

##インストール
[　■インストールパッケージ](https://www.python.org/downloads/)
　　必要なVersionをダウンロード（今回は3.7.7のWindows x86-64 web-based installerを選択）して、インストールします。Install for all usersの☑は外しました。完了すると下記にファイルが作成されます。
　　`C:\Users\XXX\AppData\Local\Programs\Python`

![プレゼンテーション1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/dd865fb9-cdb8-3653-c894-fc945e15a005.png)

##IDELの利用
　インストールが完了すると、図のようにPythonがメニューに追加されます。
　　　<img width="109" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/43f4334b-50dd-ff69-e577-5e0ea825f003.png">
　代表的な開発支援ツールとしてPyCharmやMicrosoft Visual Studioやeclipse(PyDevアドイン)などありますが、本ページではデフォルトインストールされている開発ツールであるIDELを利用します。

<img width="336" alt="無題1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/472fc751-abe7-b7c4-e70e-9eaf66175f25.png">

1. IDELを選択、起動します。
　 画面が真っ白で嫌いな人はOption→configIDLE→HighlightsでIDLE Darkを選択。

2. File　→　New Fileを選択すると別ウインドウが開きます。

3. 別ウインドウにpythonで命令文を記載し、保存（Ctrl+S）　→　Run Module(F5) を実行するとShell画面上で処理が実行されます。

###基本文法
　ざっと使い方を記載します。解説はコメントをご参照ください。
　最低これだけあれば、なんとなく読めるようになると思います。

```
#コメントはシャープです。

# ＜ その１：hello world　・・・printの前にspaceは入れない、全角スペースも禁止 ＞
print('hello world')

# ＜ その２：print関数の引数について ＞
print('hello world',10,10.5)         #複数の引数での出力
print('hello world',10,10.5,sep=':')  #区切り文字

# ＜ その３：変数（型は自動変換）とデータ入力（inputだと型は数字入れてもStrになります） ＞
test = input('何か入れてください')
print(test)             #変数の出力
print((int(test))*1.08) #計算するときはstrをintに変換にして計算する  

# ＜ その４：文字列操作のやり方 ＞
test ='SAMPLE'.replace('A','I') #文字列置換
print(test)

# ＜ その５：条件分岐 ＞
test = input('馬番をいれてください')
if test.isdigit():  #数値かどうかの判定(逆の場合は　if not)
    umaban = int(test)
    if umaban <6 :  #6以下の場合(条件文のネスト)
        print('内枠')
    elif umaban <12 :  #12以下の場合
        print('中枠')
    else:  #12以下でない場合
        print('外枠')
else:  #数値でない場合
    print('数値をいれてください')

# ＜ その６：ループ for文 ＞
dayOfWeek =['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
for day in dayOfWeek : #配列のリストすべて
    print(day)
print('--------------------')
for day in dayOfWeek[1:6] : #配列のリスト2番目から5番目まで
    print(day)
print('--------------------')
for test2 in range(5) : #5回繰り返す
    print(test2)
    test2 = test2 + 1
print('--------------------')
for test3 in range(6,11) : #6が10回まで繰り返す
    print(test3,'カウンタ')
    test3 = test3 + 2 #実験。test3
    print(test3,'手動で加算したとき')
print('--------------------')

# ＜ その6.5：while文 ＞
gunshikin = 50000
while gunshikin >= 0 :
    print(gunshikin)
    gunshikin = gunshikin -15000

# ＜ その７：関数の定義 ＞
def method1(): #引数なし
    print('みんな','のコメント１')
def method2(other): #引数あり
    print(other,'のコメント２')

method1()
method2('ほげほげ')
print('--------------------')
```

以上です。
Nextjsでビルド時ではなく、アプリ起動時に環境変数を読み込ませる方法

## 概要

Nextjsで**ビルド時**ではなく、**アプリ起動時**に環境変数を設定する方法を調べたのでメモとして残している。

## `next.config.js`の設定

以下のように設定する。

```js
// .envファイルから読み込むように設定している。
require("dotenv").config();

module.exports = {
  // ビルド時に利用できる環境変数
  env: {
    STEP: process.env.MY_STEP,
  },
  // 実行時かつ、サーバサイドで利用できる
  serverRuntimeConfig: {
    MY_SECRET: process.env.MY_SECRET,
  },
  // 実行寺かつ、サーバサイド、クライアントサイドのどちらでも利用できる
  publicRuntimeConfig: {
    API_ENDPOINT: "/my/api/version/1",
  },
};
```

## `next.config.js`で設定した値を読み込む方法

**例: `pages/index.js`で読み込む場合**

```js
import getConfig from "next/config";

// next.config.jsで設定した値を取得する
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();

// クライアントサイド: API_ENDPOINTは参照できるが、MY_SECRETは参照不可になっている。
export default function Index(props) {
  return (
    <div>
      API_ENDPOINT: {publicRuntimeConfig.API_ENDPOINT}
      MY_SECRET: {serverRuntimeConfig.MY_SECRET}
      <pre>{JSON.stringify(props, null, 4)}</pre>
    </div>
  );
}

// サーバサイド： MY_SECRETとAPI_ENDPOINTはどちらも参照可能
export const getServerSideProps = () => {
  return {
    props: {
      MY_SECRET: serverRuntimeConfig.MY_SECRET,
      API_ENDPOINT: publicRuntimeConfig.API_ENDPOINT,
    },
  };
};
```
Teams会議でPowerPointの発表者ビューを使う

#Teamsの会議で発表者ビューを使いたかった
この記事は2020年4月26日時点のものです．ソフトウェアのアップデート等で挙動が変わっている可能性があります．

#前提条件
ブラウザ版ではなくダウンロード版のTeamsアプリを使用する．
ブラウザ版だとウィンドウの共有ができないかもしれない．

#参考文献
[Presenter mode, notes and thumbnails in Teams. | Microsoft Teams](https://techcommunity.microsoft.com/t5/microsoft-teams/presenter-mode-notes-and-thumbnails-in-teams/m-p/281045)

#macOS Catalinaの場合
現在のところ，macOSだとウィンドウの共有からスライドショーを選択すると，他の人には白い画面が表示され，うまくいかない．画面が2つ以上ある人は，ローカルでPowerPointのスライドショーを開始して，スライドの画面（デスクトップ）を共有することで発表者ビューを使える．

#Windows10の場合
Windows10の場合，2画面あればmacOSの場合と同様に，スライドの画面を共有することで発表者ビューを使える．以下に紹介する方法は1画面しかない人向けだ．
1. Teams会議に参加する．
2. ローカルで共有したいPowerPointを起動する．
3. 起動したPowerPointのスライドショーを開始する．
4. Alt + TabでTeams会議のウィンドウに移動する．
5. Teams会議の方で，「共有」を選択する．下の画像の左から3つ目のやつ．![共有マーク_スクショ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369267/e3650eab-d26c-877a-3263-ed42cdd011f9.png)
6. 「ウィンドウ」にある「PowerPoint スライドショー」を選択する．下の画像では1番右を選択する．![共有_スクショ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369267/ee36ee2f-73d2-a054-0201-14a460768c1e.png)
7. スライドが表示されるので，スライドの上で右クリックし，発表者ツールを表示する．

#macOSで1画面しかない人は？
諦めてモニターを購入しよう．
他の解決策を知っている人は教えてください！！
Rails attr_accessorを使って、より良いコードを書いてみよう。

どうもチャンクノです。
今個人アプリで勝率を表示するページを作っています。
メソッド作成に困リ果てた結果、attr_accessorを使って解決したお話です。
今回は少し長くなります。
初学者の方が見ると参考になる部分があるかもしれません。

まずは下記のコードを見てみましょう。


```
viewの記述

<%= @trade.win_rate(current_user) %>
```

```
model側の記述

def win_rate(current_user)
  trades     = Trade.where("trades.user_id" => current_user.id)
  win_trades = trades.where("trades.result" => "勝").count
  (win_trades / trades.count.to_f * 100).floor
end
```

これで一応勝率が導き出せます。
が！！！
はっきり言ってこれは全然よくないコードです。
なぜだかわかりますか？

なぜかというと、月ごとの勝率を出すなど他のパターンが出てきた場合。

```
メソッド名だけ変えて記述します。

def month_win_rate(current_user)
  trades     = Trade.where("trades.user_id" => current_user.id)
  win_trades = trades.where("trades.result" => "資産増").count
  (win_trades / trades.count.to_f * 100).floor
end
```

こういう感じでメソッドを作るたびに必ず引数にcurrent_userを取る必要が出てきます。
また、同じ処理を何回も書いてしまう羽目にもなります。
これは保守性に優れていなく、非常によろしくないです。

全体の勝率を表示するだけなら10000歩譲っていいかもしれません。
が、自分は月ごとの勝率などを出すことも考えているのでこのままではダメでした。

そこで何を使ったかというとタイトルにある通りattr_accessorです。
attr_accessorの内容まで書いてしまうと非常に長くなるのでご自身で調べてみてください🙇‍♂️

参考までに
https://qiita.com/Hassan/items/0e034a1d42b2335936e6

attr_accessorを使った結果先ほどのコードがどのように変化するかというと、、、

```
controlller

def index
  @trade = Trade.new(current_user_id: current_user.id)
end

```

```
view

<%= @trade.win_rate %>
```

```
model

attr_accessor :current_user_id

def win_rate
  (search_win_trades_count / search_user_trades.count.to_f * 100)
end

def search_user_trades
  Trade.where("trades.user_id" => current_user_id)
end

def search_win_trades_count
  search_user_trades.where("trades.result" => "勝").count
end
```

メソッドを作るたびにcurrent_userを引数に取る必要がなくなり、とてもスッキリしましたね。
また、メソッドの処理も別のメソッドに切り分けることで、変更点があっても容易になりました。
同じクラス内にあるメソッドは他のメソッド内でも使うことができるので覚えておくといいと思います。

ちなみに初学者の方がこの内容を理解できたら天才だと思います。
そんなものがあるんだな程度で頭の片隅に置いとけば大丈夫です。
では長くなりましたが今日はこの辺で！
皆様よきプログラミングライフを🙏
偉そうに書いてしまいましたが、これがクソコードである場合は遠慮なくお教えください。