OmniAICreator/Qiita-1.07M huggingface dataset:
アノテーションの引数の書き方まとめ

# はじめに

別記事で書いたようにアノテーション全盛期（？）にJavaをあまり触っていなかったので、アノテーションの引数ルールがよくわからず、ググっても需要を満たすものがなかったので自分で書きます。今後同じ疑問を持った方のために。

以下、例を示すアノテーションは[@RequestMapping](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html)を使います。

# 用語定義

正確じゃないかもしれないけど以下ではこういう意味で使ってます。

<dl>
<dt>引数</dt><dd>アノテーション書くときに自分で指定する値および値を対応付ける名前。</dd>
<dt>要素</dt><dd>リファレンスに書いてある、アノテーションが受け付ける名前。</dd>
</dl>

# ルール1：デフォルト値があるものは省略できる

`@RequestMapping`のリファレンスを見るといくつか要素が書かれているが全部デフォルト値が指定されているので以下のように書いてもよい。各要素デフォルト値が使われる。

```java
@RequestMapping
```

# ルール2：引数名がvalueの場合は省略できる

以下は同じ意味

```java
@RequestMapping(value = "/")
```

```java
@RequestMapping("/")
```

Springの場合、`@AliasFor`というものが用意されていて「Mappingのvalueってどういう意味？」となるところをpathと書けるようにもなっている。どの要素がvalueの別名かはリファレンスを見よう。大体感覚通りなものが別名になっていると思う。

```java
@RequestMapping(path = "/")
```

# ルール3：要素の型が配列の場合でもスカラー値で引数を書いてもよい

コンパイラが配列に拡張してくれる。

```java
// value -> {"/"}
@RequestMapping("/")
```

自分で{}書いても書かなくてもいい。ただし次の説明する引数二つ以上書く場合は{}要る。

```java
// value -> {"/", "/index"}
@RequestMapping("/", "/index")
```

```java
// value -> {"/", "/index"}
@RequestMapping({"/", "/index"})
```

# ルール4：引数が二つ以上の場合は引数名必須

Pythonのデフォルト値引数みたいに必須引数とオプション引数みたいになってるものだと思ったのでこれがわかりにくかった。

```java
@RequestMapping(value = "/", method = RequestMethod.GET)

// Pythonのデコレーションみたく以下のようには書けない
@RequestMapping("/", method = RequestMethod.GET)
```
【解決済】SwiftUIのtutorialでエラーが発生した件

#はじめに
Appleのチュートリアルの一つ[Building Lists and Navigation](https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation)のですが、チュートリアル通りに書いても下記のようにエラーが発生してしまいました。

```エラー
Use of unresolved identifier 'NavigationLink'; 
```

![スクリーンショット 2019-07-03 22.23.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104887/2e2e3f8f-bf76-ea05-44dd-1a55ec4e95dc.png)

#結論
7/2より、X-code 11.0 beta 3が展開されましたが、これによってNavigationButtonからNavigationLinkに変更され、無事ビルドが通るようになりました。

コメントで御指摘いただき、ありがとうございます。

#環境
- macOS 10.14.5
- Xcode 11.0 beta

#変更プログラム
今回はLandmarkListのbodyを書き換えました

```swift:LandmarkList.swift
import SwiftUI

struct LandmarkList: View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                    NavigationLink(destination: LandmarkDetail()) {
                        LandmarkRow(landmark: landmark)
                    }
                }
                .navigationBarTitle(Text("Landmarks"), displayMode: .large)
        }
    }
}

#if DEBUG
struct LandmarkList_Previews: PreviewProvider {
 '''
}
#endif
```

#やり方1 (古いバージョンのやり方)
 NavigationLinkをNavigationButtonに変更

```swift:LandmarkList.swift
import SwiftUI

struct LandmarkList: View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                    NavigationLink(destination: LandmarkDetail()) { //変更
                        LandmarkRow(landmark: landmark)
                    }
                }
                .navigationBarTitle(Text("Landmarks"), displayMode: .large)
        }
    }
}
```
一応これでビルドは通りました。

#参考
[SwiftUIチュートリアルをやってみた その１](https://medium.com/swift-column/swiftui-tutorial-1-690de7cf5076)
Qiitaマークダウン記法まとめ

初投稿です。
投稿の練習も兼ねてマークダウン記法についてまとめてみました。

# 目次

| 内容 | 書き方 | 内容 | 書き方 |
|:-:|---|:-:|---|
| [テーブル](#テーブル) | 列数x行数  | [リンク](#リンク) | \[タイトル](リンク先) |
| [見出し](#見出し) | #見出し | [インライン表示](#インライン表示) | \`テキスト` |
| [コード](#コード) | <br>\`\`\`言語:title <br>code<br>\`\`\` | [リスト](#リスト) | \- リスト<br>\* リスト<br>\+ リスト<br>1. リスト |
| [引用](#引用) | >テキスト<br>>>テキスト | [改行](#改行) | \<br> |
| [取消線](#取消線) | ``テキスト  | [マークダウンの<br>エスケープ](#マークダウンのエスケープ) | \マークダウン |

# テーブル
`列数x行数`と入力することでテーブルの挿入ができる。

* 入力

```
例1:
4x4  ;;4列x4行のテーブル 

例2:
| 内容| 書き方 | 内容 | 書き方 |
|:-:|:-:|:-:|:-:|
| テーブル | 列数x行数  | リンク | \[タイトル](リンク先) |
| 見出し | #見出し | インライン表示 | \`テキスト` |
```

* 出力

例1:

| 1 | 2 | 3 | 4 |
|:-:|:-:|:-:|:-:|
|   |   |   |   |
|   |   |   |   |
|   |   |   |   |
|   |   |   |   |

例2:

| 内容| 書き方 | 内容 | 書き方 |
|:-:|:-:|:-:|:-:|
| テーブル | 列数x行数  | リンク | \[タイトル](リンク先) |
| 見出し | #見出し | インライン表示 | \`テキスト` |


# リンク
`[タイトル](リンク先)`でリンクを紐づけることができる。
他ページにリンクするときは、リンク先のURLを書く。
ページ内リンクの場合は、`(リンク先)`の部分に(`#`+`見出し`)と書く。
見出し2以下であっても`#`の数は1つであることに注意。

#### 入力<br>

```
[スクール東京](http://schooltokyo.jp/)
```

#### 出力
[スクール東京](http://schooltokyo.jp/)

# 見出し
`#見出し名`で見出しをつけることができる。

#### 入力

```
#見出し1
##見出し2
###見出し3
####見出し4
#####見出し5
```

#### 出力

#見出し1

##見出し2

###見出し3

####見出し4

#####見出し5

# インライン表示
``  `テキスト`  ``とすることでインライン表示ができる。


#### 入力

```
`var x = 0`
```

#### 出力
`var x = 0`

# コード
ブロックの始めと終わりにバッククォートを3つ(\`\`\`)またはチルダを3つ(~~~)入力することでコードを表示できる。
ブロックの始めに`言語：タイトル`と入力することでタイトルを表示できる。


#### 入力

>\`\`\`javascript:hello.js
>console.log("Hello, World!");
>\`\`\`

#### 出力

```javascript:hello.js
console.log("Hello, World!");
```

# リスト
ハイフン`-`、アスタリスク`*`、プラス`+`を用いることでリスト表記ができる。
`1.リスト`とすることで番号付きにできる。

#### 入力

```
- リスト１
  - リスト1-1
     - リスト1-1-1
* リスト１
  * リスト1-1
     * リスト1-1-1
+ リスト１
  + リスト1-1
     + リスト1-1-1
1. リスト１
2. リスト２
3. リスト３
```

#### 出力

- リスト１
  - リスト1-1
     - リスト1-1-1
* リスト１
  * リスト1-1
     * リスト1-1-1
+ リスト１
  + リスト1-1
     + リスト1-1-1
1. リスト１
2. リスト２
3. リスト３

# 引用
冒頭に`>`を入力することで可能。
`1.リスト`とすることで番号付きにできる。

#### 入力

```
>「考える」×「時間」＝「合格力」
>>考える力を鍛えることで、短時間での合格を実現します。ゼミ、個別指導などで質疑応答を通して考える力を養います。
```

#### 出力
>「考える」×「時間」＝「合格力」
>>考える力を鍛えることで、短時間での合格を実現します。ゼミ、個別指導などで質疑応答を通して考える力を養います。

# 改行
改行は`<br>`

#### 入力

```
テキスト
<br>
テキスト2
```

#### 出力
テキスト<br>
テキスト2

# 取消線
チルダ2つ(~~)で取消線が表示される。

#### 入力

```
~~法律は難しい~~
```

#### 出力
~~法律は難しい~~

# マークダウンのエスケープ
マークダウンの前に`/`を入れることでマークダウンが非表示になる。

#### 入力

```
\`インライン表示`
```

#### 出力
\`インライン表示`

# 終わりに
以上のマークダウンを押さえておけばこのページが作れるはず。
マークダウンは他にもあるみたいなので気になる人は調べてみてください。

# 参考にしたサイト
* [Qiita マークダウン記法 一覧表・チートシート](https://qiita.com/kamorits/items/6f342da395ad57468ae3)
* [Markdown (マークダウン)チュートリアル](https://qiita.com/ozin/items/0be04ada3e66eb88175d)
* [Qiitaのテーブルの書き方についてまとめた](https://qiita.com/zakuroishikuro/items/f33929eab9d55c5bd073)
* [[Qiita Markdown記法]ページ内リンク・注釈・折りたたみ等](https://qiita.com/aymikmts/items/71e550bf2c10f36883e9)
LaravelのEloquentについてメモ（DB接続編）


Laravelの経験が少ないので、公式を見ながら少しずつメモ。

#Eloquent ORMとは？
LaravelのDB操作のこと。CRUD。

#DBの接続情報の設定
下記ファイルに設定

```
config/database.php
```

#モデルファイル
モデルファイルはappディレクトリ配下に設置。
composer.jsonファイルにオートロードするように指定した場合は、どこでも設置可能。

全てのEloquentモデルは、```Illuminate\Database\Eloquent\Model```を拡張する必要あり。

#Artisanコマンドでモデル生成
下記コマンドで生成

```
php artisan make:model User
```

app/user.phpが生成される。

```php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    //
}
```

#テーブル名
生成したモデルにどのテーブルを使用するか。
テーブル名を指定しない場合は、<font color="Red">クラス名を複数形のスネークケースにしたものが、自動的にテーブル名とされる。</font>

```
Userモデル　→　userテーブル
```

テーブル名を指定するときは、tableプロパティを定義する。

```php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    //テーブル名指定
    protected $table = 'test_user';
}
```

#タイムスタンプ
EloquentはDBのcreated_atとupdated_atを自動更新してくれる。
自動更新してほしくないときは、timestampsプロパティをfalseにする。

```php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    //タイムスタンプを自動更新しないように設定
    public $timestamps = false;
}
```

タイムスタンプを保存するカラム名もカスタム可能。

```php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'last_update';
}
```

#別のDBに切り替え
EloquentモデルはDBを指定しない場合は、デフォルトに設定されているデータベースに接続する。
データベースを指定したい場合は、connectionプロパティを使用する。

```php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    //コネクション名を指定
    protected $connection = 'mysql2';
}
```

データベースの接続情報は、
config/database.phpに記載する。
defaultキーでデフォルトDBの接続情報を指定している。

```php:database.php
'default' => 'mysql',

'connections' => [
    'mysql' => [
        'driver'    => 'mysql',
        'host'      => env('DB_HOST_ONE', 'localhost'),
        'database'  => env('DB_DATABASE_ONE', 'forge'),
        'username'  => env('DB_USERNAME_ONE', 'forge'),
        'password'  => env('DB_PASSWORD_ONE', ''),
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict'    => false,
    ],
    'mysql2' => [
        'driver'    => 'mysql',
        'host'      => env('DB_HOST_TWO', 'localhost'),
        'database'  => env('DB_DATABASE_TWO', 'forge'),
        'username'  => env('DB_USERNAME_TWO', 'forge'),
        'password'  => env('DB_PASSWORD_TWO', ''),
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict'    => false,
   ],
],
```

公式
https://readouble.com/laravel/5.8/ja/eloquent.html#introduction

実際にまとめてみると、理解が深まる。
【CSS, JS】フロントデザインの備忘録

# はじめに
Webアプリケーションのフロントデザイン時に毎回調べている内容をまとめた。
随時更新していく。

## CSS初期化
normalize.cssなどもあるが、自分で指定したほうが確認しやすい

```css
/* 初期化 */
body, header, main, footer, section, div, nav, p, a, h1, h2, h3, h4, ul, ol, li, form, input, span{
  padding: 0;
  margin: 0;
  border: none;
}
body {
  font-size: 62.5%;
}
a, a:visited, a:hover{
  text-decoration: none;
  color: inherit;
  font-size: inherit;
  font-family: inherit;
}
main{
  display: block;
}
ul, ol{
  list-style: none;
}
```

## レスポンシブ対応

* viewport設定

``<head>``タグ内に記述

```html
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
```

* ブレークポイント
    * PC：1024px
    * タブレット：896px
    * スマホ：480px

```css
@media screen and (max-width: 481px) {}
```

* フォントサイズ
ベースサイズを10pxに。
1em = 10px

```css
body{
  font-size: 62.5%;
}
```

## jQuery使う

* jQueryファイルダウンロードするか、CDN使うか
[公式CDN](https://code.jquery.com/)
* GoogleのCDN使うほうが良い（らしい）
[ここから](https://developers.google.com/speed/libraries/#jquery)

## jQuery使わない

* [DOM操作](https://www.w3schools.com/jsref/prop_element_classlist.asp)

クラス付与や削除は良く使うので下記にコード

```js
document.getElementById("myid").classList.add("new-class");
document.getElementById("myid").classList.remove("new-class");
document.getElementById("myid").classList.togle("new-class");
```

* CSSアニメーション

CSSアニメーションでjQueryみたいなことだいぶできる

## ハンバーガーメニュー
* スマホページによく使われるメニュー

## Flexbox
* 左寄せに``float: left;``を使わないほうがデザインしやすいので、``display: flex-box;``使うほうが良い

```css
display: flex;

/*子要素の横幅が勝手に縮小されないようにするため*/
flex-shrink: 0;
```

## ``height: 100%``の設定

* 画面の高さと要素高さを等しくしたい場合、``html``と``body``も``height: 100%;``にする。

```css
html, body{
  height: 100%;
}

/* 高さを画面の高さにしたい要素 */
.hoge{
  height: 100%;
}
```

## aタグ
* aタグの外（親要素）からフォント指定しても反映されない

```html
<div>
  <a href="html/huga.html">hogehoge</a>
</div>
```
このときCSSで``div{color: red;}``と指定しても、``hogehoge``という文字列は赤色にならない。
そこで、``a{color: inherit}``として親要素の文字色を継承するようにすれば解決。
（CSSの初期化の部分ですでに対応しているが、メモとして残したいので記載）

## 上下左右中央寄せ
``Flexbox``を使うのが手っ取り早い。ただし、対応していなブラウザに注意。

```html
<div class="outer">
  <div>
    これを中央寄せしたい
  </div>
</div>
```

```css
.outer{
  display: flex;
  justify-content: center;
  align-items: center;
}
```

## 参考サイト
* https://www.seojuku.com/blog/responsive-mediaquery.html
    * レスポンシブデザインのブレークポイント
* https://www.okuni.me/entry/css-slide-animation-keyframes
    * CSSアニメーション
* https://www.nxworld.net/tips/12-css-hamburger-menu-active-effect.html
    * ハンバーガーメニュー
* https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet
    * Flexbox
* https://www.granfairs.com/blog/staff/centering-by-css
    * 上下左右中央寄せ
AtCoder Beginner Contest 056 C問題の解説の補足

https://atcoder.jp/contests/abc056/tasks/arc070_a

C問題の解説を読んだり、他の人の解答を読んでも何故そうなるのかがわからなかったが、最終的に証明っぽいことができたので復習のために記録。



解答例としては与えられた X 以上となるまで初期値1,等差数列1の数列の和を算出し続けていく、和がX以上になった時、それまでの数列の数が解答となる。
https://atcoder.jp/contests/abc056/submissions/6222759


## 証明
等差数列の和が`X`超えた時の等差数列の和を`Sum`、最後に足した数値を`N`、`Sum`のために足した数列数値の数を`T`とする。

ここで`Sum > X`である。
また、`Sum - X < N`である。
(もし`Sum - X = N`なら、解答は`T-1`となるためである)

ここで、`Sum`はカンガルーが毎秒右にジャンプした時に到達する距離を表している。

`Sum - N < N`なので、`1 ~ N-1`の中で`Sum - N`の手番にその場にとどまることによって手番 N での到達距離を X 丁度にできる。
Leetcode #733: Flood Fill

```swift
func floodFill(_ image: [[Int]], _ sr: Int, _ sc: Int, _ newColor: Int) -> [[Int]] {
    if image[sr][sc] == newColor {
        return image
    }
    var image = image
    helper(&image, sr, sc, newColor, image[sr][sc])
    return image
}

private func helper(_ image: inout [[Int]], _ i: Int, _ j: Int, _ newColor: Int, _ originalColor: Int) {
    if i < 0 || i >= image.count || j < 0 || j >= image[i].count || image[i][j] != originalColor {
        return
    }
    image[i][j] = newColor
    helper(&image, i-1, j, newColor, originalColor)
    helper(&image, i+1, j, newColor, originalColor)
    helper(&image, i, j-1, newColor, originalColor)
    helper(&image, i, j+1, newColor, originalColor)
}
```
Lightsail LAMPのMySQLに外部のDBクライアントから接続する

LightsailのLAMP(PHP7)イメージ内に設定されているMySQLに外部から接続しようと思って**Sequel Pro**や**MySQL Workbench**などでアクセスしようとしたらうまくいかなくて困ったのでメモ。

# 接続方法はSSH経由

DBクライアントを使いたいけど、さすがに直で外部接続を許可するのは不安なので、SSH経由でのアクセスしたい。

## 設定内容

SSHホスト: [LightsailのパブリックIP]
ポート: 22
ユーザ: bitnami (Lightsailのデフォルト)
SSH鍵: [Lightsailに登録済みのもの]
MySQLホスト: 127.0.0.1
ポート: 3306
ユーザー: [MySQLのユーザ名]
パスワード: [MySQLパスワード]

で接続すると

`Access denied for user 'ユーザ名'@'127.0.0.1'`

という感じのエラーがでて接続できない。

##解決方法

```
mysql> SELECT User, Host FROM mysql.user;
+---------------+-----------+
| User          | Host      |
+---------------+-----------+
| [ユーザー名]    | localhost |
・・・・
| root          | localhost |
+---------------+-----------+
```

↑　こういう感じのときに、[ユーザー名]を使ってアクセスしたいときには

```
+---------------+-----------+
| User          | Host      |
+---------------+-----------+
| [ユーザー名]    | 127.0.0.1 |　<-- これを追加
| [ユーザー名]    | localhost |
・・・・
| root          | localhost |
+---------------+-----------+
```

これで、接続できるようになりました。

ユーザーの追加クエリ（ざっくり）

```
grant all privileges on [DB名].* to [ユーザー名]@"127.0.0.1" identified by '[パスワード]' with grant option;
```

- [DB名]　接続を許可するデータベース
- [ユーザー名]　追加するMySQLユーザ
- [パスワード] ユーザの接続パスワード
- 詳しくは検索してください。（権限とか）

### まとめ

- localhostと127.0.0.1は同じ意味ではないらしい。
- 同じ要領でユーザを増やしたり権限を調整できると思う
- LightsailのMySQLにDBクライアントからアクセスできると便利です。
2019-07-03 STM32L476 > FreeRTOSでLチカ (環境: Ubuntu 18.04 LTS + STM32CubeMX + STM32CubeIDE)

```txt:動作環境
Ubuntu 18.04 LTS
STM32CubeMX v5.2.1
STM32CubeIDE v1.0.1
FreeRTOS Kernel V10.0.1
基板:STM32L476RGT6 64 PINS
```

### 概要

- FreeRTOSでSTM32L476をLチカする
    - [STM32L476RGT6](https://qiita.com/7of9/items/31487b5ea527edd65a5b)
    
[Ubuntu 18.04 LTS > STM32L476 > 環境構築 (STM32CubeMX + STM32CubeIDE) + Lチカ || TrueStudioとの連携は失敗](https://qiita.com/7of9/items/31487b5ea527edd65a5b)
ではRTOSなしでLチカをしたが、RTOSを用いるLチカを実施してみた。

### 参考

- [STM32マイコンでFreeRTOSを用いてLEDを制御する(Lチカ)](https://qiita.com/46sayu/items/50b43477e7dfd55c9e21) by @46sayuさん


上記は2017年の記事で、自分の環境とはいくつか違う部分があった。FreeRTOSのバージョンの違いに起因するのだろうか?

### 実施

以下におおまかな流れを示す。一部、上記の @46sayu さんの手順を参考にしているが、自分の環境と異なる部分は適宜変更をした。

1. STM32CubeIDEを起動する
2. STM32Projectを新規作成する
3. MCU/MPU Selectorにて「STM32L476RG」で検索 (Part Number Search)
4. MCUs/MPUs Listにて「STM32L476RG」を選択しプロジェクトを作成 
    - Project Name: 任意 (例: L476_RTOS_LedDrive_190703)
    - Next
    - Finishにてプロジェクト作成
5. Pinoutにて「21(PA5)」をGPIO_Outputに変更 
    - あとでこのピンをLチカする
6. Pinout & Configurationにおいて左メニューの「MiddleWare」を選択
    - FREERTOSを選択
    - ModeのInterfaceを変更
        - DisableからCMSYS_V1へ
    - ConfigurationのTasks and Queuesを選択
    - TasksにてAddして、以下のように変更する
        - TaskName: LedTask (任意の名前)
        - Priority: osPriorityAboveNormal
        - Entry Function: StartLedTask (任意の名前)
    - OKを押してタスクを追加する
7. Timerbase Sourceを変更する
    - Pinout & ConfigurationのCategoriesにてSystem Coreを選択
    - SYSを選択
    - Timerbase SourceをSysTickから変更 (理由は@46sayu さんの[記事](https://qiita.com/46sayu/items/50b43477e7dfd55c9e21)参照)
        - TIM17にしてみた
7. File -> Save Allする
    - 「Do you want generate Code?」にてYesを選択
    - Src/にfreertos.cが追加される

以上でRTOSの準備はできた。

### LEDタスク

Src/main.cの中にLedTaskがある。

```main.c
void StartLedTask(void const * argument)
{
  /* USER CODE BEGIN StartLedTask */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartLedTask */
}
```

上記を以下のようにする。

```main.c
void StartLedTask(void const * argument)
{
  /* USER CODE BEGIN StartLedTask */
  /* Infinite loop */
  for(;;)
  {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    osDelay(1000); // msec
  }
  /* USER CODE END StartLedTask */
}
```

1秒ごとのLED点灯、消灯になる。

### ビルドから実行まで

- `9 ビルドする
- `10 Debug Asにて「STM32 MCU C/C++ Application」を選択する
- `11 Edit configurationにてOKを押す
- `12 デバッグ画面になるのでResumeを押して実行する

LD2という部分が1秒おきに点灯、消灯します。

### 実行例

緑色に点灯しているのがLD2です。

![IMG_0898.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/51dc49ba-876e-a2d4-c57d-0342cfe2dfa9.jpeg)

### 所感

RTOSがこんなに簡単に使えるというのはすごい。

### リンク

以下の記事の方が画像が多くわかりやすいかもです。

- [STM32CubeIDEで速攻FreeRTOS](https://qiita.com/imagou/items/8af2ad999b2a80009c6f)
rails ルーティングについて

#　実装につきルーティングについてまとめ

###　ルートとはURLとアクションを紐付ける役割をになっている。

つまり、viewで受け取ったURLをコントローラー内に定義したアクションメッソッドに割り当てる。

get "URL" :コントローラー名#アクションメッソッド

config/routes.rbに自身でHTTPメソッドとURLとアクションの紐付けを行うのは少々手間がかかります。

そこでresourceメソッドを使用し自動でHTTPメソッド（GET,POST,PATH,PUT,DELETE)とアクション（index、create、new、edit、show、update、destroyの標準的な機能）との紐付けを生成します。

- 記述方法

resource :リソース名

- resourcesをネストする方法

resource :リソース名 do
    resources :リソース名　　　※対象が複数ある場合が複数形
end

Rails.application.routes.draw do
  # 実際はここに devise_for :users (ログイン・ログアウト機能など)
  resources :tweets do
    resources :comments, only: [:create]
  end
  resources :users, only: [:show]

end

```ruby:qiita.rb
Rails.application.routes.draw do
  # 実際はここに devise_for :users (ログイン・ログアウト機能など)
  resources :tweets do
    resources :comments, only: [:create]
  end
  resources :users, only: [:show]

end

# の'resources :tweets　〜　only: [:show]'はすなわち

GET    '/tweets'          => 'tweets#index'   # 一覧画面を生成
GET    '/tweets/:id'      => 'tweets#show'    # 詳細画面を生成
GET    '/tweets/new'      => 'tweets#new'     # 登録画面を生成
POST   '/tweets/create'   => 'tweets#create'  # 登録処理
GET    '/tweets/:id/edit' => 'tweets#edit'    # 編集画面を生成
PUT    '/tweets/:id'      => 'tweets#update'  # 更新処理
DELETE '/tweets/:id'      => 'tweets#destroy' # 削除処理

POST   '/tweets/:id/comments' => 'comments#create' # ツイートにコメント

GET    '/users/:id'       => 'users#show'     # ユーザーのマイページを表示 

```

ターミナル　rails routesにてルーティングの確認。
Gitコマンド、一時退避編


```vim
$ git stash save
```
> 退避

```vim
$ git stash save "コメント"
```
> 退避（メッセージ付き）

```vim
$ git stash list
```
> 退避した一覧を取得

```vim
$ git stash show -a stash@{0}
```
> 最初に退避された内容が表示される

```vim
$ git stash pop
```
> 退避していた内容を適用かつ退避データは削除される

```vim
$ git stash apply
```
> 退避していた内容を適用かつ退避データは残る

```vim
$ git stash drop
```
> 退避していた内容の削除

```vim
$ git stash clear
```
> 退避していた内容、全て消去される

```vim
$ git diff HEAD.. stash@{0}
```
> 退避していた内容と最新との差分確認

```vim
$ tig stash@{0}
```
> 退避内容とのこれまでの履歴閲覧
Leetcode #904: Fruit Into Baskets

```swift
func totalFruit(_ tree: [Int]) -> Int {
    var start = 0
    var end = 0
    var answer = 0
    var dict = [Int: Int]()
    while end < tree.count {
        dict[tree[end]] = end
        if dict.keys.count > 2 {
            answer = max(answer, end - start)
            var minValue = tree.count
            var removedKey = 0
            for key in dict.keys {
                if dict[key]! < minValue {
                    minValue = dict[key]!
                    removedKey = key
                }
            }
            dict.removeValue(forKey: removedKey)
            start = minValue + 1
        } else {
            answer = max(answer, end - start + 1)
        }
        end+=1
    }
    return answer
}
```
picoCTF 2018 shellcode - Points: 200

#問題

https://2018game.picoctf.com/problems

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/afb171a4-18c6-e813-c551-6e3de24e7c29.png)

#解いてみた

ソースとプログラムをリンクからダウンロードします。
ソースを開いてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/62f49c98-4eb5-d9bd-e2be-e23489e829e1.png)

結構短めのソースです。
文字を入力してそれを出力してます。
最後のやつはなんでしょう。

```
((void (*)())buf)();
```

サーバを見てみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/ae7680d6-e11d-dc62-c8df-3628afb59ab6.png)

サーバを確認するとflag.txtがあるので、実行ファイルからflag.txtを呼び出す問題のようです。

ではさっきの謎の処理を調べてみます。

[(\*(void (\*)())shellcode) - Qiita](https://qiita.com/miyagaw61/items/b59428d0528286d2b241)
[(\*(void(\*)()) shellcode) - Electric Sheep and Androids](https://yktsr.github.io/security/void_pointer/)

上記2サイト読めば一応理解できました。
とりあえず入力した文字列がここで実行されるということです。

ということは、flag.txtを表示すればいいので

```
cat flag.txt
```

と入力すれば良いのでしょうか。
やってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/eb16ed0e-5712-f9c2-1fdc-4e5c0b840fbf.png)

大事なところは「Segmentation fault (core dumped)」になってしまっています。
やはりshellcodeを書く必要がありそうです。

書けません。

とりあえず流れとしては以下

```
vulnを実行
↓
/bin/shを実行するshellcodeを入力
↓
cat flag.txtでフラグを表示させる
```

/bin/shを実行するshellcodeが書けないので探します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/b249bc1c-6fb8-971d-a92c-487f9d98ece0.png)

ヒントにもshellcode探しましょうのようなことが書かれてますね。

「shellcode」で検索していると検索サイトのようなものを見つけた。
[Shellcodes Database - shell-storm](http://shell-storm.org/shellcode/)

種類がたくさんありすぎてどれを採用すればよいのかわからないので、ひとまず環境を確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/9e23f275-31ad-3ea0-7d5f-ee481f244662.png)

Ubuntuの64bitのようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/1b2e9a86-cdd4-c4ae-b370-28b9f242bac9.png)

これでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/af0b4566-9a38-98c0-d266-1f99fe3c9855.png)

strに書かれている長い文字を放り込めばよさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/cd51845b-70b5-bbb8-34ed-f98edcfe0ca1.png)

Segmentation faultですね。
調べてみると

```
echo -e "xxx" | ./aaa
```

という形ではなく

```
(echo -e "xxx";cat) | ./aaa
```

という形にしないと入力を待ち受けてくれないそうです。
ということでこれでやり直し。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/a35b2e41-6015-fb55-8518-a12090d4fde7.png)

入力は待ち受けるようになったので進めた感はありますが、結果は同じSegmentation faultです。
ということはshellcodeが違うということです。

ふと思ったのがOSは64bitということで64bitのshellcode使用していたけど、そうじゃなくてソフトが何bitかということが大事なんじゃないかと思いました。
普段Linuxあまり使用しませんが、Windowsが64bitだとしてもソフトは32bitでも64bitどちらでも基本的には実行できますし。

ということでソフトが何bitか調べる必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/9b7268da-ecc5-f761-aac4-6cf4c107eaa6.png)

fileコマンドを実行してみると32bitだということがわかりました。
なので32bitのshellcodeを探します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/77c5e88f-6620-37fb-2861-a734e50d0aee.png)

これですかね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/23343895-4228-ac52-eca5-7c2650a1e49e.png)

できましたー。
スケールフリーなライフゲーム

## 目的

ライフゲームの作例を検索してみると、固定長二次元配列を使った作例が多く見られます。しかし二次元配列を用いる場合、

- 二次元配列のサイズをどのくらいにとるのが妥当なのか？
- 二次元配列上はほぼいつも空なのに全画面について計算するのは無駄では？
- 配列の端の存在が全体の計算結果にどんな影響を与えるのか？

など疑問が出てきます。

生きているセルの座標点の集合として取り扱えば、無限の空間に広がり続けるパターンをシミュレーションすることができます。ここでは、Python の set を使ってライフゲームを実装してみます。

## ルールを実装する

set に生きている（「生」状態の）セルの座標が入っていて、set にない座標はすべて「死」であると定義します。この場合、以下の手順でライフゲームの次のステップでの生きているセルを得ることができます。

1. 生きているセルの座標点の集合が与えられます。
2. 生きているセルに隣接する座標すべてのリストを得ます。
3. 上で得たリストに含まれる座標について、その座標が何回リスト上に出現するか個数を数えます。
4. 「次のステップで生きているセルとなる可能性のある座標すべてについて、当該座標に隣接する現時点で生きているセルの個数(隣接生存セル数と呼ぶことにします)」が上記までの手順で得られます。
5. 得られた座標と、隣接生存セル数のペアについて、以下のルールで次ステップの「生」「死」を判定します：
 * 隣接生存セルの数が 3 なら、その座標のセルは元の状態に依らず無条件に「生」です。
 * 隣接生存セルの数が 2 なら、その座標のセルの元の状態が「生」なら「生」、「死」なら「死」です。
 * それ以外の座標については元の状態に依らずすべて「死」です。
6. 判定結果を次ステップの生存セルの座標 set として返します。

このような考えで、リスト内包表記を使って実装したのが以下です。一行が長くなっても構わないならば、一行に収めて書くこともできます：


```python
import collections

def life(dots):
    u'''ライフゲームのルールに従って、与えられた「生」セルの座標 set を元に
    次のステップの「生」セルの座標 set を返す。
    --------
    dots: Set[Tuple[int, int]]
        「生」セルの座標の set

    Returns
    --------
    next_dots: Set[Tuple[int, int]]
        次のステップでの「生」セルの座標の set
    '''
    return {point
            for point, n in collections.Counter([(x + i, y + j)
                                                 for (x, y) in dots
                                                 for i in range(-1, 2)
                                                 for j in range(-1, 2)
                                                 if i != 0 or j != 0]).items()
            if n == 3 or (n == 2 and point in dots)}
```
実際に、これがどのくらい実用的（？）に使えるものなのか気になったので、pygame で作った簡単な画面に出しながら実行できるようにしてみました。
「どんぐり」をファイルで与えると画面いっぱい、いや、画面をはみ出してでもさらに広い領域に広がっていきます。「どんぐり」は無限の彼方に飛んでいくグライダーをいくつも生成しますが、画面サイズに制約されない計算方式なので好きなだけ長時間継続して見ていることができます。

```python
import sys
import life_display
import life_file

def main():
    u'''Life1.05 形式のファイルから初期状態を読み込んで実行する。
    '''
    if len(sys.argv) < 2:
        print('test: <life file>')
        sys.exit(0)
    fps = 200  # フレームレート
    path = sys.argv[1]
    # ファイルから読み込む
    dots = life_file.read_life_105_file(0, 0, path)
    life_file.write_life_105(dots)
    # pygames フロントエンドで表示しながら実行する場合
    # display = life_display.LifeDisplayAndGenerate()
    # pygames フロントエンドで表示しながらアニメーション GIF を作成する場合
    display = life_display.LifeDisplayAndGenerateImages()
    for i in range(1, 1000):
        display.draw(dots)
        dots = life(dots)
        display.clock_tick(fps)
    display.generate_animation_gif('/tmp/life.gif', duration=0)
if __name__ == '__main__':
    main()
```

![acorn_mini.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412308/a9a6407e-9e1e-de3d-a2b3-b4d20b9c1d00.gif)


しょぼい GIF アニメーションですみません。もっと長時間動いている画像をお見せ出来ないのが残念です。

[画面表示](https://qiita.com/tadashi9e/items/31514172144daf0f5b17)、[ファイルからの初期パターンの読み込み](https://qiita.com/tadashi9e/items/b2ff031dd17172d5bb39)については別記事で投稿します。

## まとめ

set を使ってスケールフリーなライフゲームを実装しました。
set とリスト内包を使って書いてみると、なんとなく APL 版ライフゲームを思い起こします。

[github にソースコードを公開しました。](https://github.com/tadashi9e/life_game_in_python)
【初心者向け】pythonで入力されたデータをデータベースに反映する方法

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている山田です。

Pythonについて学習のアウトプットとして投稿します。

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

#データベースに関して苦しんだ点

既にプログラミング学習を始めてしばらく経った方やプログラミングを業務として行なっている方にとっては、今や当然のこととして、忘れてしまった感覚があると思います。

そこで、データベースとの連携に苦しんだ点を初心者としての目線でお伝えできればなと思います。

私は今でこそ、データベースの基本について理解したつもりですが、最初は「データがどのように存在しているか」といった概念を理解するのに非常に苦しみました。

そのため、「POSTで送る」といった言葉や「テーブルに追加する」という言葉が分かっているようで、きちんと理解できていませんでした。

そこで今回は、初心者が苦しむ「データがどのように存在しているのか」といった点に重きを置きながらpythonで入力されたデータをデータベースに反映する方法について紹介していきます。

#入力フォームで入力されたデータを次のページに送る方法

例えば、年齢や身長を入力するフォームを作って、次のページにデータを送る場合、コードは以下のようになります。

```input.py
# 以下のコードを書かないと、htmlとして読み込んでもらえない。
print("Content-type: text/html; charset=utf-8")

print(

"""
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>入力フォーム</title>
</head>

<body>
    
    <form name="form" method="post" action="confirm.py">
      年齢:<br>
        <input name="age"><br>
      身長:<br>
        <input name="height"><br>

<input type="submit" value="送信">
    
</form>
</body>
</html>
"""
)
```
このコードから言えることとしては、このような入力フォームの「年齢:」の後ろに入力された数字(年齢)は、「age」という変数として(身長も同様)、「post」という形式で、「confirm.py」という指定されたページに送られます。
そのため、操作画面で「送信」ボタンを押すと、「input.py」から「confirm.py」に移り、「age」というデータも移ります。


#前のページから送られたデータをデータベースに反映する方法

データをいつでも自由に取り出したり暑かったりするためには、データベースに反映する必要があります。
今回は、SQlite3を使った方法を紹介します。
データベースに反映するための大きな流れとしては以下のようになります。
1.データベースファイルを作る
2.テーブル(データを入れる箱のようなもの)を作成する
3.前のページから送られてきたデータを取得して変数にセット
4.テーブルにデータを挿入する

これをコードで表すと以下のようになります。

```confirm.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cgi
import sys
import io
import sqlite3

#データベースファイルの作成
conn = sqlite3.connect('sample.db')

#カーソルオブジェクトを作成
c = conn.cursor()

#テーブルを作成し、データの挿入ができるように値を取得して変数にセット。
curs.execute("CREATE TABLE if not exists data(id INTEGER PRIMARY KEY AUTOINCREMENT, age, height)");
form = cgi.FieldStorage()
age = form.getfirst('age')
height=form.getfirst('height')

# データの挿入
c.execute('INSERT INTO id(nennrei,shintyo) VALUES(?,?)',[age, height])

# 挿入した結果を保存（コミット）する
conn.commit()

# データベースへのアクセスが終わったら close する
conn.close()
```

今回は、初心者が陥りがちなそもそもデータという概念を理解する難しさを踏まえた上でご紹介しました。

私自身も初心者には変わりないので、間違いがありましたら、ぜひご指摘ください。
退職エントリを毎日自動で集めるBlogを作った

# 概要
退職エントリって良いですよね。
人生色々ですよね。

# 作ったもの
[退職エントリまとめ](https://retirement-entry.hatenablog.jp/)
これ自体は、ただのはてなブログです。

## 退職エントリをあつめる

`cheerio-httpcli`で、タイトルに「退職しました」や、「退職します」が付いてるサイトのURLを
Google検索結果から集めます。

```javascript
const client = require('cheerio-httpcli');

// "退職しました"を検索する。"&tbs=qdr:d"を付与すると24時間以内の検索になる。
const BASE_URL_GOOGLE =
  'https://www.google.com/search?q=%22%E9%80%80%E8%81%B7%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%22&tbs=qdr:d&start=';

// はてブなど、除外したいサイトを登録しておく。
const IGNORE_SITES = [
  'https://b.hatena.ne.jp/',
  'https://newstopics.jp/',
];

// 退職エントリとみなすキーワードを持たせておく。
const RETIREMENT_WORDS = ['退職します', '退職しました'];

const includesIgnoreSites = value => IGNORE_SITES.some(_ => value.includes(_));

const includesRetirementWords = value =>
  RETIREMENT_WORDS.some(_ => value.includes(_));

const getEntries = async () => {
  const retirementEntries = [];
  for (let i = 0; ; i += 10) { // 検索結果10件ずつを取得
    const res = await client.fetch(`${BASE_URL_GOOGLE}${i}`);
    const contents = res.$('div.r > a > h3');
    if (contents.length === 0) {
      // 検索結果が無くなったら終わり
      break;
    }
    contents.each((index, elm) => {
      const url = elm.parent.attribs.href;
      const title = elm.childNodes[0].data;
      if (!title) {
        return;
      }
      if (!includesIgnoreSites(url) && includesRetirementWords(title)) {
        retirementEntries.push({ url: url, title: title });
      }
    });
  }
  return retirementEntries;
};
```

## はてなブログAPIで投稿する

APIの説明は[ここ](http://developer.hatena.ne.jp/ja/documents/blog/apis/atom)に載ってるので割愛。
`axios`を使ってPOSTしてみます。

```javascript
const axios = require('axios').default;

const postBlog = async entries => { // さっき取得したエントリ情報を引数に
  const title = `${new Date().toLocaleDateString()}の退職エントリ`;
  let content = '';
  for (const entry of entries) {
    if (content !== '') {
      content += '\r\n';
    }
    content += `[${entry.url}:embed:cite]`; // はてなのカード形式で出るようにする。
  }
  if (content === '') {
    return;
  }
  const data = `<?xml version="1.0" encoding="utf-8"?>
  <entry xmlns="http://www.w3.org/2005/Atom"
         xmlns:app="http://www.w3.org/2007/app">
    <title>${title}</title>
    <content type="text/x-markdown">
${content}
    </content>
  </entry>`;

  await axios.post(
    'https://blog.hatena.ne.jp/{はてなID}/{ブログID}/atom/entry',
    data,
    { auth: { username: /* はてなID */, password: /* APIキー */ } }
  );
};
```

## 自動投稿する

上記のコードをGoogle Cloud Functionsに登録して、毎日1回定期実行すればOK。
[こんな記事](https://retirement-entry.hatenablog.jp/entry/2019/07/02/181311)ができます。

良いですね。

# 2019/7/5 追記

[続編](https://qiita.com/obuchi3/items/161a645f9a7312e13397)書きました。
もし今後プログラムを１行も書かなくなったとしても、あんなプログラマになりたいと思う人が一人でもいる限りプログラマとして生きていると定義する。

「今後プログラムを１行も書かなくなったとしても、あんなプログラマになりたいと思う人が一人でもいる限りプログラマとして生きていると定義する。」という題を決めて文章を書き始める。


この記述は、ある学会の幕間に、あんなプログラマになりたいという人物像に登場したという話を聞いたことを発端として書き始める。

そう人が亡くなっても、人の心に生き続ける限り、その人が生きるという。

プログラマの書いたソースコードが生き続ける限り、そのプログラマが生き続けるという仮説をたてよう。

それだけでは面白くないかもしれない。

あんなプログラマになりたいと思う人が一人でもいる限りプログラマとして生きているという定義も容認するのはどうだろう。

もう１種類くらいあってもいいかもしれない。

また今度。


少し表現が変わった。

やっぱ、ソースコードが生きてりゃいいよね。
GO言語でサーバーを立ち上げてみる。

##Go言語でHelloと表示してみる
ド初心者ですが、
GO言語でWEBサーバーを立ち上げてHelloと表示してみます。

##webサーバーの起動

![スクリーンショット 2019-07-03 21.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/0e7ae1d4-6b9e-a42b-e3ba-3aa902919616.png)

**hello.go**のファイルを作成して、
上記の内容を記入。

```$ go run hello.go```でサーバーが立ち上がります。

![スクリーンショット 2019-07-03 21.39.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/bec59768-265e-6e78-be40-a011f2716e1d.png)

簡単にしか記載してませんが、
これで**Hello**と表示されました。

引き続き**Ruby**の勉強と並行しながら、
色々調べながら試して見ようと思います！
wsl2でsshサーバを起動し、外部からそこに接続

# やりたいこと
以下のような構成のLANで、Host2からwsl2にssh接続する。
![lan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101023/008d92b2-0e78-cb20-0089-36b35baf0a5e.png)

# wsl2ではネットワーク構成が変更された
wsl1では良くも悪くもWindowsとLinuxが混ざり合っていました。
wsl1ではWindowsとLinuxが同じネットワークインターフェースを参照していました。
![wsl1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101023/0d284fc0-bdb0-9cf4-c284-7f433c601136.png)


そのため、例えばwsl1のポート22でsshサーバを起動し、そこにHost2から接続したい場合、Host2はWindowsのポート22に接続するだけで、wsl1のsshサーバに接続できました。　

wsl2の場合、LinuxはWindowsと仮想ネットワークで接続された別ホストとして扱われます。
![wsl2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101023/0a886cb7-32e0-6c51-c9ad-a71db1f6aad8.png)

そのため、Host2からWindowsのポート22に接続しても、wsl2のsshサーバに接続することはできません。
そこで、Windowsのポート22からwsl2のポート22に対してポートフォワーディングを行う必要があります。

# ssh サービスの起動 (wsl2)
wsl2 で以下を実行

```
sudo service ssh restart
```

# ポートフォワーディング設定 (cmd)
以下のコマンドで、Windows(listenaddress)のポート22(listenport)に来たパケットをwsl2(connectaddress)のポート22(connectport)に転送する設定が行えます。
(実行するには管理者権限が必要)

```
> netsh.exe interface portproxy add v4tov4 listenaddress=localhost listenport=22 connectaddress=[ip_addr_of_wsl2] connectport=22
```

例: Windowsのポート22に来たパケットをwsl2のポート22に転送 (listenaddress, connectportは省略)

```
> netsh.exe interface portproxy add v4tov4 listenport=22 connectaddress=192.168.100.200
```

ポートフォワーディングを動作させるためには、`IP Helper` サービスを起動する必要があります。

```
> sc.exe config iphlpsvc start=auto # ブート時の自動起動設定
> sc.exe start  iphlpsvc            # サービスの起動
```

以上のコマンドを発行した時点で、ポートフォワーディングが有効になります(再起動不要)。
Windoswのファイアウォールやwsl2のsshサーバの設定が適切であれば、Host2からssh接続が可能となります。

設定確認

```
> netsh.exe interface portproxy show v4tov4
Listen on ipv4:             Connect to ipv4:

Address         Port        Address         Port
--------------- ----------  --------------- ----------
*               22          192.168.100.200  22
```

(左から listenaddress, listenport, connectaddress, connectport)

設定削除

```
> netsh.exe interface portproxy delete v4tov4 listenport=22
```

(listenport=22 connectaddress=192.168.100.200 connectport=22 のように絞り込んでも良い)



# 自動化
Windowsの起動時にポートフォワーディングの設定を自動的に行う方法を示します。

wsl2からnetsh.exeを叩き、ポートフォワーディングの設定を行うport_forwarding_22.shを以下に示します。

```/opt/bin/port_forwarding_22.sh
#!/bin/bash

IP=$(ifconfig eth0 | grep 'inet ' | awk '{print $2}')

netsh.exe interface portproxy delete v4tov4 listenport=22
netsh.exe interface portproxy add    v4tov4 listenport=22 connectaddress=$IP

sc.exe config iphlpsvc start=auto
sc.exe start  iphlpsvc
```

ポートフォワーディングの設定には、wsl2のIPアドレスが必要となります。
そのため、設定はwsl2側から行います。
(コメント欄で、Windowsから設定を行う方法が紹介されています)
また、wsl2のIPアドレスはWindowsが再起動するたびに変化するので、ポートフォワーディングの設定を行う前に、古い設定を削除する必要があります。

Windows側からport_forwarding_22.shをwsl2上で実行させるport_forwarding_22.batを以下に示します。

```port_forwarding_22.bat
wsl --exec bash /opt/bin/port_forwarding_22.sh

rem ディストリビューションを指定する場合の例
rem wsl -d Ubuntu-18.04 --exec bash /opt/bin/port_forwarding_22.sh 
```

このスクリプトを、タスクスケジューラでログオン時に自動起動するように設定すれば完了です。
注意点としては、タスクのプロパティにおいて、
`General -> Security options -> Run with highest privileges`
にチェックを入れる必要があります。
SchemaSpy を使ってみる

* [SchemaSpy](http://schemaspy.org/)を使って既存のDBからドキュメントを作ってみます

* Dockerで試してみます
  * [docker hub schemaspy/schemaspy](https://hub.docker.com/r/schemaspy/schemaspy/)

# やり方

1. PostgreSQLを用意します
  * [PostgreSQLを用意する](https://qiita.com/hiro9/items/e6e41ec822a7077c3568#postgresql%E3%82%92%E7%94%A8%E6%84%8F%E3%81%99%E3%82%8B) を参考にDockerでPostgreSQLを立ち上げてください

1. SchemaSpyを実行します

    ```
docker pull schemaspy/schemaspy
docker run -v "$PWD/schema:/output" --net="host" schemaspy/schemaspy -t pgsql -host localhost:5555 -db testdb -u root -p password
    ```

1. 作成された`schema`ディレクトリの中にある`index.html`をブラウザで確認してください

<img width="1341" alt="スクリーンショット 2019-07-03 21.32.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268273/ab2e9dbe-f74a-57c5-41d1-b691afa96ade.png">
【Mac】使用しているポート番号とそのポートを動かしているプログラムの確認方法

Macで、使用しているポート番号を確認したり、そのポート番号を動かしているプログラムを確認したりします。

##使用しているポート番号の確認

まずは、ネットワークユーティリティを起動します。
<img width="675" alt="スクリーンショット 2019-07-02 15.46.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270696/4998cf23-a989-4898-5f6c-7b606f9d9a9f.png">

Infoタブを選択し、現在のIPアドレスを確認します。次にPortsscanタブを選択し、先ほどのIPアドレスを入力してScanしてください。

以下のように、使用しているポート番号が表示されます。

<img width="913" alt="スクリーンショット 2019-07-02 16.36.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270696/0acd5181-ded1-6b3d-de4a-9f7cca57abc5.png">

##(例)88番ポートを動かしているプログラムを確認する場合
ターミナルを開いて

```:ターミナル
$ sudo lsof -i:88
```
と入力します。(lsofコマンドに関しては[こちらの記事](https://qiita.com/hypermkt/items/905139168b0bc5c28ef2)がとても分かりやすいです。)

```
COMMAND PID USER   FD   TYPE            DEVICE SIZE/OFF NODE NAME
kdc     101 root    4u  IPv6 0x5b18a7c443e3bf3      0t0  UDP *:kerberos
kdc     101 root    5u  IPv6 0x5b18a7c41b69fa3      0t0  TCP *:kerberos (LISTEN)
kdc     101 root    6u  IPv4 0x5b18a7c443e393b      0t0  UDP *:kerberos
kdc     101 root    7u  IPv4 0x5b18a7c41b6e6a3      0t0  TCP *:kerberos (LISTEN)
```
上記のような結果が返ってくるので、

```:ターミナル
$ sudo kill 101
```
と指定することで、そのポート番号を閉じることができます。

以上です。
Cloud Speech-to-TextのAPIキーが取得できなかったときに試したこと

(初めてQiitaの記事を書きます。)

GoogleのCloud Speech-to-Textを使用するために[公式のクイックスタートガイド](https://cloud.google.com/speech-to-text/docs/quickstart-protocol?hl=ja)を参照しながら進めてみたものの、APIキーが取得できず詰まった。

次の方法で無事に解決し、クイックスタートを完了することができた。


環境 : mac


## 引っかかっていたエラー

**`ここでは、ダウンロードした秘密鍵をservice-account-file.jsonと表記します。`**

[公式のクイックスタートガイド](https://cloud.google.com/speech-to-text/docs/quickstart-protocol?hl=ja)の、「始める前に」の「2. 環境変数の設定」より次のように設定。

```bash
$ export GOOGLE_APPLICATION_CREDENTIALS="~/Download/service-account-file.json"
```
それから、「音声文字変換をリクエストする」の「2. curlを使用して~」より次のように実行すると次のエラーが発生した。

```bash
$ curl -s -H "Content-Type: application/json" \
    -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
    https://speech.googleapis.com/v1/speech:recognize \
    -d @sync-request.json
ERROR: (gcloud.auth.application-default.print-access-token) File ~/Download/service-account-file.json (pointed by GOOGLE_APPLICATION_CREDENTIALS environment variable) does not exist!
{
  "error": {
    "code": 403,
    "message": "The request is missing a valid API key.",
    "status": "PERMISSION_DENIED"
  }
}
```

## 解決できた方法
`service-account-file.json`を、`~/Download`ではなく、カレントディレクトリ`./`に置いて

```bash
$ export GOOGLE_APPLICATION_CREDENTIALS="./service-account-file.json" 
```
として、`curl`を実行した。
すると、正常にレスポンスが表示された。

## 問題だったと思われること
[公式のクイックスタートガイド](https://cloud.google.com/speech-to-text/docs/quickstart-protocol?hl=ja)の、「始める前に」の「2. 環境変数の設定」の例で、

```bash
$ export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"`
```

としていたため、それに習って**`service-account-file.json`を、`~/Download`(カレントディレクトリではない場所)に置いていた。**
これが原因だったと思われる。

しかし、以下のように確認すると`service-account-file.json`がreadできていないことが確認できた。

```bash
$ gcloud auth activate-service-account --key-file=~/Downloads/creative-mochi-ce695e1b1e22.json
ERROR: (gcloud.auth.activate-service-account) Unable to read file [~/Downloads/service-account-file.json]: [Errno 2] No such file or directory: '~/Downloads/service-account-file.json'
```

そこで試しに`service-account-file.json`をカレントディレクトリ`./`に置いてみると

```bash
$ gcloud auth activate-service-account --key-file=./service-account-file.json
Activated service account credentials for: [username@XXXX.com]
```
無事に認証することができた。


## 解決できるまでに試していたこと・確認したこと
- [トラブルシューティング](https://cloud.google.com/speech-to-text/docs/troubleshooting?hl=ja)を読む
- Google CloudのコンソールでAPIが有効になっているか
- `service-account-file.json`のアクセス権限の確認(readすることができるか)
- プロキシに引っかかっていないか
- `service-account-file.json`のパスは正しく指定されているか

## 感想
解決するまでに20時間くらい悩んでしまったのでとても疲れた、Google大先生の公式のクイックスタートでこんなに詰まることがあるとは思わなかった。

一応、.jsonの場所を変えることで解決はできたが、何故カレントディレクトリでないと正常に実行できなかったかが不明のままなので、理由を見つけてスッキリしたい。


##  追記
今日初めてQiitaの記事(これ)を書いた。
習慣的に今後も書くようにしたい。
ターミナルのユーザ名などがおかしくなってから解決するまでの道のり

MacOSを使っているなかで、不意にターミナルの見た目を変えてみたくなりました。
なので、以下の記事を参考にしながら`zshシェル`へのカスタマイズを進めることにしました。

[初心者向け：Zshの導入 - Qiita](https://qiita.com/iwaseasahi/items/a2b00b65ebd06785b443)

また、**見た目もかっこよくしたかった**ので以下の記事を参考にさせてもらいつつ進めました。

[お前らのターミナルはダサい - Qiita](https://qiita.com/kinchiki/items/57e9391128d07819c321)

ですが、ターミナルが`zsh`シェルに変わった途端に表示がおかしな文字列へと変貌を遂げてしまいました。

```zsh:Terminal
~
> PS1='\e[1;32m\W \t \e[1;31m\u \e[1;32m$ \e[0m'
```

## 解決までに至った道のり
曖昧な知識で設定ファイルを弄るのはとても怖かったので、とりあえず`zsh`と名のつくファイルを手当たり次第に探して、表示名と似たような記述がないかを確認しました。
すると、ホーム直下の「zshrc」というファイルに下記のように似た、というより同じ記述がありました。

```zsh:.zshrc
#
# Executes commands at the start of an interactive session.
#

（中略）

export PS1='\e[1;32m\W \t \e[1;31m\u \e[1;32m$ \e[0m'

if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi
```

以下の記事の**「表示する内容を変える」**という部分を見て、完全に設定ファイルに対する不安を無くしてから下記の通り該当するであろう部分をコメント化しました。

[【Bash】ターミナルのプロンプトのカスタマイズ方法まとめ - Qiita](https://qiita.com/hmmrjn/items/60d2a64c9e5bf7c0fe60)

```zsh:.zshrc
# export PS1='\e[1;32m\W \t \e[1;31m\u \e[1;32m$ \e[0m'
```

すると、以下の画像のようにおかしくなっていた表示名もなくなりスッキリしました！

<img width="1478" alt="スクリーンショット 2019-07-03 21.21.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425008/982d8a07-6ebe-89ce-683d-97ade2bc3aa4.png">

## ユーザ名などの表示がおかしくなった原因
これは確実に自分の設定手順が定まってなかったからです。
いつも参考にする記事を２つ以上用意しないと不安になってしまうので、参考にする記事を途中で間違えてしまっていました。
今後はこういうミスが起こらいような設定の手順を踏んでいきたいと思います。
Raspberry Pi 上の clang のバグっぽい挙動

先日。
Raspberry Pi 上の clang のバグっぽい挙動に遭遇したので報告。

# 現象
三角関数の計算を間違える。

# 環境

```text
$ uname -a
Linux raspberrypi 4.19.50-v7+ #896 SMP Thu Jun 20 16:11:44 BST 2019 armv7l GNU/Linux
$ cat /etc/debian_version 
10.0
$ clang --version
clang version 7.0.1-8+rpi1 (tags/RELEASE_701/final)
Target: armv6k-unknown-linux-gnueabihf
Thread model: posix
InstalledDir: /usr/bin
$ apt info clang
Package: clang
Version: 1:7.0-47
Priority: optional
Section: devel
Source: llvm-defaults (0.47)
Maintainer: LLVM Packaging Team <pkg-llvm-team@lists.alioth.debian.org>
Installed-Size: 23.6 kB
Depends: clang-7 (>= 7~)
Breaks: clang-3.2, clang-3.3, clang-3.4 (<< 1:3.4.2-7~exp1), clang-3.5 (<< 1:3.5~+rc1-3~exp1)
Replaces: clang (<< 3.2-1~exp2), clang-3.2, clang-3.3, clang-3.4 (<< 1:3.4.2-7~exp1), clang-3.5 (<< 1:3.5~+rc1-3~exp1)
Download-Size: 7,468 B
APT-Manual-Installed: yes
APT-Sources: http://raspbian.raspberrypi.org/raspbian buster/main armhf Packages
Description: C, C++ and Objective-C compiler (LLVM based)
 Clang project is a C, C++, Objective C and Objective C++ front-end
 for the LLVM compiler. Its goal is to offer a replacement to the GNU Compiler
 Collection (GCC).
 .
 Clang implements all of the ISO C++ 1998, 11 and 14 standards and also
 provides most of the support of C++17.
 .
 This is a dependency package providing the default clang compiler.
```

# 再現方法

まずはソースコード：

```c++:clangsin.cpp
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdint>

template< typename t >
void dump( char const * name, t * v )
{
  auto p = reinterpret_cast<std::uint8_t const *>(v);
  std::cout << name << "=";
  for( auto it = p ; it != p+sizeof(*v) ; ++it ){
    std::printf( "%02x ", *it );
  }
  std::cout << "\n";
}

int main()
{
  float f = std::cos( 3.45f );
  double d = std::cos( 3.45 );
  std::cout << "f=" << f << "  d=" << d << std::endl;
  std::printf( "f=%g  d=%g\n", f, d );
  dump("f", &f);
  dump("d", &d);
  return 0;
}
```

そして実行結果：

```text
$ clang++ -Wall clangsin.cpp && ./a.out
f=-9.32929e-17  d=2.11371e-314
f=3.45  d=6.20896e-312
f=cd cc 5c 40 
d=9a 99 99 99 24 01 00 00
```

```
$ g++-8 -Wall clangsin.cpp && ./a.out
f=-0.952818  d=-0.952818
f=-0.952818  d=-0.952818
f=e5 eb 73 bf 
d=98 e6 d6 9f 7c 7d ee bf 
```

# おかしなところ

## 計算結果

計算結果は、g++-8 のものが正しい。clang の結果は間違っている

ていうか。
`f` の値なんて、絶対値が `1` を遥かに超えているし、入力の `3.45f` そのまんまだし、一体何なんだ。

## float と double

`float` と `double` はほぼ同じ値になるべきだが、そうなっていない

## printf と cout

`printf` と `cout` は同じ変数を参照しているはずなのに、まったく違う値を出している。困る。
ダンプの結果と整合するのは `printf` の方である。

```ruby
"cd cc 5c 40".split(" ").map{|e|e.to_i(16).chr}.join.unpack("f")
#=> [3.450000047683716]
"9a 99 99 99 24 01 00 00".split(" ").map{|e|e.to_i(16).chr}.join.unpack("d")
#=> [6.208959684366e-312]
```

# 原因

さっぱりわからない

# 対策

当面は Raspberry Pi 上で clang を使うのをやめることにした。
kubectl editしたくない人のためのkubectl patchコマンド

## kubectl patchコマンド
`kubectl edit`コマンドで立ち上がるエディタでリソースを編集するのが煩わしい我々のために🤔
`kubectl patch`コマンドが用意されている、ありがたく活用させてもらおう。

patchコマンドならエディタで手書きする必要がなくなるのが嬉しいポイントだ。
ワンライナーでリソースを変更できるのでシェルスクリプトなどに組み込むのにも向いている。

## 例1 コンテナイメージを変更する

イメージを変更するワンライナー

``` shell
kubectl patch deployment sample-deployment -p '{"spec":{"template":{"spec":{"containers":[{"name":"sample-app","image":"sample-image:1.0"}]}}}}'
```

一時的にイメージのバージョンを変更したい場合などに活用できる。

## 例2 レプリカ数を変更する

レプリカ数を変更するワンライナー

``` shell
kubectl patch deployment sample-deployment -p '{"spec":{"replicas":0}}'
```

一時的にレプリカ数を変更したい場合に活用できる。
ちなみに0も指定でき、簡易的なアンデプロイ状態になる。

## 例3 ServiceのTypeを変更する

`Type`を`NodePort`に変更するワンライナー

``` shell
kubectl patch service sample-service -p '{"spec":{"type":"NodePort"}}'
```

とりいそぎ`ClusterIP`から`NodePort`に変更してアクセスしたい場合などに活用できる。

実行例

``` shell
# before
$ kubectl get svc sample-service -o jsonpath='{.spec.type}'
ClusterIP

# patch実行
$ kubectl patch service sample-service -p '{"spec":{"type":"NodePort"}}'
service/sample-service patched

# after
$ kubectl get svc sample-service -o jsonpath='{.spec.type}'
NodePort
$ kubectl get svc sample-service -o jsonpath='{.spec.ports[0].nodePort}'
32206
$
```


上記のように`-o jsonpath=`に確認したいパスを指定すると値を確認できるが、以下のように`jq`で絞り込む方が記号が少なく簡潔に書けるのでおすすめである。

``` shell
kubectl get svc sample-service -o json | jq -r .spec.type
kubectl get svc sample-service -o json | jq -r .spec.ports[0].nodePort
```
初めての自動テスト(1章 テストのピラミッド)

知識整理のために投稿しています。
本は `初めての自動テスト ~Webシステムのための自動テスト基礎~ (O'REILY)`です。

## 先人の教訓

1. 全ての自動テストが同等の力を持つわけではない
2. テストを「書くことができる」状態が、「書くべき」だという理由にはならない
3. スピードとフィードバックが重要

つまり、1つのテストが万能薬のように働くことはない！
→ **うまく組み合わせて用いること**が必要

## テストのピラミッド

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390780/0e68ad80-e3a8-cc79-6be2-3bbe69d24389.png)

### UIテスト

[利点]

- エンドツーエンドで動く
- ユーザと同じ対象を見る

[欠点]

- 高コストで遅い

### 統合テスト

[利点]

- WebサービスとAPIがテストできる
- つながりを見られる

[欠点]

- 詳細さに欠ける

### ユニットテスト

[利点]

- 超高速
- 多目的に利用できる

[欠点]

- 結合部分の確認に弱い

## 自動テストの方針

- UIテストよりユニットテストを優先する
- ユニットテストで埋められない部分を統合テストでカバーする
- UIテストは限定的に使う
- **全てを自動化しようとせず、代わりに、過不足なく自動化すること**
- 上位と下位のテストがかぶることもある
  - ただしそれらはスコープが違う
  - **協調して無意味な重複を避けていくことが大事**
- 探索的テスト(手順化されてないテスト)も忘れないこと
xserverにAnacondaを導入する話(python環境構築)

ローカル環境でflaskで開発したwebアプリをxserverで公開したかったのだので、いろいろ奮闘した結果、anacondaを導入することでできたよ！っていう話。

Xserverを契約。x１０プラン。
初期設定等はいろいろググった。

契約後、flaskを導入するため、ssh等の設定もする。

前提として、xserverはroot権限がないので、標準で内蔵しているpythonでpipを使うのは無理…
やり方としては
①pyenvで仮想環境を作って、そこにpythonを入れる、pipを入れる…ってやっていく方法。
②linuxbrewを使ってpythonをインストールする方法。

まず、手をつけたのは、①．
以下サイトを参考に進めていったところ、

http://www.wanna-continue.com/entry/2017/02/02/Xserver%E3%81%A7Flask%EF%BC%88Python%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%EF%BC%89%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95#Flask%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C


詰まる。
pyenvの導入まではできる。が、

`$ pyenv install 3.x.x`

の実行がムリ。格闘すること二日諦める…


続いて実行に移したのが②．参考にしたのは以下サイト。

https://note.mu/coeeff/n/neab8acfde97e

しかし、これは初手の
`$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"`
が実行できない…

絶望した。打つ手がないのか、あきらめざるを得ないのか…

そう思って最後に、プログラミングを教えてくれた先生に相談したところ、

`$ sh Anaconda3-5.0.1-Linux-x86_64.sh`
で直接anacondaを取り込めばよいというありがたいお言葉をいただいた。

https://www.anaconda.com/distribution/

を参考にした。

具体的には
https://www.anaconda.com/distribution/

から自分のPCにanaconnda3をインストールしたのち、それをsshを用いて、xserverに持っていき、

`$ sh Anaconda3-5.0.1-Linux-x86_64.sh`

でanacondaをインストール。
`$ export PATH=/home/ユーザ名/anaconda3/bin:$PATH`
でpathをしっかり通して完了。

`conda pip`
でpipをインストールして、pipを使ってモジュールをインストールしまくれました。

おかげでflaskで動かせました！！

以上まとめると
pyenvとlinuxbrewでpythonインストールできなくても、泣くな！
手はあるよ！むしろ簡単って話！