- 投稿日:2020-03-20T22:24:06+09:00
gatsbyでポートフォリオ作ろうとしたらコマンドが使えなかった話
gatsbyでポートフォリオサイト作ろうとしたら・・・
何をしても
zsh: command not found: gatsby
が表示される
何度もこの表示を見て泣きそうになりました。Success!
とか
Welcome to the Gatsby CLI! Please visit https://www.gatsbyjs.org/docs/gatsby-cli/ for more information.
とか出るくせにgatsby -h
を入力すると
zsh: command not found: gatsby
もうまじで「f○○k ○○u」と心の中で叫んでましたね。
失礼しました。
では次は試したことを試した事
- npmのバージョンアップ
- npmのアンインストール/再インストール
- nodeのアンインストール/再インストール
これらをやったのちに
npm i -g gatsby-cli
を打ってもう一度gatsby -h!!!
zsh: command not found: gatsby
・・・・・・・・・・・
もう諦めようかと思いましたよ。いちよう解決したので次に解決方
やっと解決
ググりまくってやっと解決出来た方法がこちら
npm config delete prefix
npm config set prefix /usr/local
簡単に言うと最新のmacOSではnpm configを更新する必要する必要があるらしく、このコマンドで更新が出来るみたいです。
この後にnpm i -g gatsby-cli
を打ってgatsby -h
をやったらしっかりhelpが出てきてくれました。
やっとgatsbyでポートフォリオサイトが作れます。
npmとかnodeとかyarnとかの知識がまだまだなのでもっと理解をしないとダメだなと思った今日この頃でした。最後に
見てくれた方ありがとうございます。
まだ学習を始めて半年の初心者ですが誰かの役に立てればと思います。
- 投稿日:2020-03-20T14:43:03+09:00
nestjsとTypeORMに入門した
はじめに
node.jsのフレームワークで最近勢いのあるnestjsと、これまた人気が出てるORMのTypeORMを触ってみました。
node.jsのフレームワークは薄いものが多いですが、それらとは違って結構多機能で便利に感じたので、備忘録がてら記事にします。typescript、 eslint、 prettier、 jest、 ホットリロードなどが初めから設定された状態で開発できる
nest new <project-name>
とするだけで初めからいろんなツールチェインが入った状態で開発ができます。
あれを入れて、これを入れて、、とやる手間が省けて楽でした。class-validatorを使ってリクエストボディのバリデーションが書ける
nestjsではリクエストで飛んでくるボディやクエリストリングなどのことをDTOと読んでます。
このDTOはクラスで定義するのですが、そのクラスのプロパティにclass-validatorのデコレータをペタペタ追加していくことで、柔軟なバリデーションをかけることができます。class CreateParams { @IsNotEmpty() hoge: string; } @Controller('sample') export class SampleController { constructor(private sampleService: SampleService) {} // これで、「POST /sample」ではbody内にhoge情報が必須になる @Post() create(@Body() params: CreateParams) { return this.sampleService.create(params); } }またこのバリデーションを有効にするためには以下の記述が必要でした。
参考: https://docs.nestjs.com/pipesmain.tsapp.useGlobalPipes(new ValidationPipe());swaggerを書くのが簡単
swaggerの定義をymlで書くのって割とめんどくさいと思っちゃうんですが、これもデコレーターを使って簡単に書けます。
こんな感じの定義をしておけば、
export class FindByIdParams { @ApiProperty({ description: 'sample_idでの検索', type: Number, }) @IsNumberString() sample_id: number; }他の書き方とかの詳細はこちら: https://docs.nestjs.com/recipes/swagger#openapi-swagger
トランザクションを貼りたい
nestjsとTypeORMのカスタムリポジトリを使っている状態でトランザクションを貼るにはどうやるのがいいのか探していたらこの記事が見つかりました。
こんな感じでトランザクションを貼れました。
@Injectable() export class SampleService { constructor(private sampleRepository: SampleRepository, private connection: Connection) {} create(params: CreateParams): Promise<Sample> { return this.connection.transaction(async (manager) => { const sampleRepository = manager.getCustomRepository(SampleRepository); return sampleRepository.save({ ...params, created_at: new Date(), updated_at: new Date(), }); }); } }TypeORMはトランザクションを貼るにもいろんな方法を提供してくれてます。(3種類くらい?)
ただ、nestjsの方の記事で見つけたのですが、@Transaction
のデコレータを使ってtransactionを貼るのはおすすめしないみたいです。TypeORMのマイグレーションが便利
TypeORMはコードの状態とDBの状態を比較して、そのコードの状態にするためのマイグレーションファイルを自動で作ってくれます。
例えば、こういうsamplesのentityを定義するコードがあるとして、DB上にはsamplesテーブルがなかった場合、
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity('samples') export class Sample { @PrimaryGeneratedColumn() id: number; @Column() hoge: string; @Column() created_at: Date; @Column() updated_at: Date; }samplesをCREATEするマイグレーションファイルを自動で作ってくれます。
import {MigrationInterface, QueryRunner} from "typeorm"; export class CreateSamples1584670197350 implements MigrationInterface { name = 'CreateSamples1584670197350' public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`CREATE TABLE "samples" ("id" SERIAL NOT NULL, "hoge" character varying NOT NULL, "created_at" TIMESTAMP NOT NULL, "updated_at" TIMESTAMP NOT NULL, CONSTRAINT "PK_d68b5b3bd25a6851b033fb63444" PRIMARY KEY ("id"))`, undefined); } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`DROP TABLE "samples"`, undefined); } }このCREATE TABLEの実行後に、entityにカラム追加をした場合は、
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity('samples') export class Sample { @PrimaryGeneratedColumn() id: number; @Column() hoge: string; @Column() huga: string; // 追加 @Column() created_at: Date; @Column() updated_at: Date; }差分となるALTER TABLEのマイグレーションファイルを自動で作ってくれます。
import {MigrationInterface, QueryRunner} from "typeorm"; export class AddHugaColumnToSamples1584682435530 implements MigrationInterface { name = 'AddHugaColumnToSamples1584682435530' public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`ALTER TABLE "samples" ADD "huga" character varying NOT NULL`, undefined); } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`ALTER TABLE "samples" DROP COLUMN "huga"`, undefined); } }また、TypeORMの設定項目の
synchronize
を有効にしておくと、コードのentityに何か変更があった場合、マイグレーションを自動実行してくれるようになるので、開発中にマイグレーション周りの作業をほとんどしなくてよくなります。最後に
他にもnestjsは色々機能があるので、いいと思ったのがあれば加筆していきます。
今回試してみたコードはこちらにあげてます。
https://github.com/pokotyan/nestjs-sample
- 投稿日:2020-03-20T12:15:56+09:00
BLE nobleでPasskey入力する
偉大なnobleを使っていると、BLEペリフェラルとペアリングするときに、BLEペリフェラルが要求するPasskeyを入力したい場合があります。
nobleは、ペアリング方式としてJust Works固定となっているので、ちょっと改造する必要があります。noble/noble
https://github.com/noble/noble以下、そのときの改造個所を備忘録として残しておきます。
Just Works : 現実装
Just Worksは、ペアリングの際によく聞く言葉ですが、実際には認証に使う鍵を生成する方法です。
ペアリングの際の認証鍵をTKと呼びます。そして、TKは、Passkeyから派生させて生成します。
Just Worksは、Passkeyを0 とした場合のことです。
nobleでは、Just Works固定、すなわち、Passkeyが0固定で実装されています。TKで認証が完了すると、鍵を共有します。この鍵をSTKと呼びます。BLE通信が切れると、STKも破棄されます。
認証方法の決定
上述の通り、認証方法は、Just Worksだけではなく、Passkeyを入力する方法があります。
しかしながら、Passkeyを入力する方法として、いくつかの種類があります。なぜならば、PasskeyをBLEペリフェラルとBLEセントラルの双方が互いに知っている必要があるためです。何を言っているかというと、基本的にPasskeyをBLE通信プロトコル上に流してしまうと、盗聴されてしまうため、操作している人自身で、BLEペリフェラルとBLEセントラル双方で共通のPasskeyを交換してもらう必要があるのです。
たとえば、画面がないBLEペリフェラルの場合には、BLEセントラル側でPasskeyを決めて表示し、BLEペリフェラルにPasskeyを入力することになります。また、もしBLEペリフェラルに入力手段がなければ、BLEペリフェラル側でPasskeyを決めて表示し、BLEセントラルにPasskeyを入力することになります。さらに、BLEペリフェラルに入力装置も出力装置も両方ない場合は、固定のPasskeyをBLEペリフェラルに埋め込んでおいて、そのPasskeyをBLEセントラルが何らかの形であらかじめ知っている必要があります。ペアリングとボンディング
ペアリングと一口に言っても、実際は、ペアリングとボンディングの2つに分けられます。
ペアリングは、Passkeyの交換による認証です。認証が完了するとSTKで通信が暗号化されます。
ボンディングは、再度ペアリングするときに毎度Passkeyを交換するのも面倒なので、後々のために、鍵を事前に共有しておくことで、次回の認証時はPasskeyの入力が不要となります。この鍵をLTKと呼びます。noble改造個所
> npm install noble
をした後、node_modules/noble/lib/hci-socket にある、「smp.js」を修正します。
smp.js//<修正前> Smp.prototype.sendPairingRequest = function() { this._preq = new Buffer([ SMP_PAIRING_REQUEST, 0x03, // IO capability: NoInputNoOutput 0x00, // OOB data: Authentication data not present 0x01, // Authentication requirement: Bonding - No MITM 0x10, // Max encryption key size 0x00, // Initiator key distribution: <none> 0x01 // Responder key distribution: EncKey ]); this.write(this._preq); }; //<修正後> var g_io_cap = 0x02; // 0x00, // IO capability: DisplayOnly // 0x01, // IO capability: DisplayYesNo // 0x02, // IO capability: KeyboardOnly // 0x03, // IO capability: NoInputNoOutput // 0x04, // IO capability: KeyboardDisplay Smp.prototype.sendPairingRequest = function() { this._preq = new Buffer([ SMP_PAIRING_REQUEST, // 0x03, // IO capability: NoInputNoOutput g_io_cap, // IO capability 0x00, // OOB data: Authentication data not present // 0x01, // Authentication requirement: Bonding - No MITM 0x04, // Authentication requirement: No Bonding - with MITM 0x10, // Max encryption key size 0x00, // Initiator key distribution: <none> // 0x01 // Responder key distribution: EncKey 0x00 // Responder key distribution: <none> ]); this.write(this._preq); };補足します。
sendPairingRequest の部分です。
IO capabilityは、BLEセントラル側がもつ表示装置と入力装置の有無です。
修正前は、NoInputNoOutput なので、Just Works専用となっていました。また、Authentication requirement のところで、No Bonding(ボンディング無し)にしています。Node.js実行後、LTKを保存して次に使いまわすわけではないためです。
それにともない、Responder key distribution のところも、EncKeyも不要なので、無しにしています。smp.js//<修正前> Smp.prototype.handlePairingResponse = function(data) { this._pres = data; this._tk = new Buffer('00000000000000000000000000000000', 'hex'); this._r = crypto.r(); this.write(Buffer.concat([ new Buffer([SMP_PAIRING_CONFIRM]), crypto.c1(this._tk, this._r, this._pres, this._preq, this._iat, this._ia, this._rat, this._ra) ])); }; //<修正後> var readline = require('readline-sync'); var g_passkey = 0; var g_prompt_passkey = true; Smp.prototype.handlePairingResponse = function(data) { this._pres = data; var input; if( g_prompt_passkey ) input = readline.question('Input Passkey : '); else input = g_passkey; var passkey = new Array(16); for( var i = 0 ; i < 3 ; i++ ) passkey[i] = (input >> (i * 8)) & 0xff; this._tk = Buffer.from(passkey); // this._tk = new Buffer('00000000000000000000000000000000', 'hex'); this._r = crypto.r(); this.write(Buffer.concat([ new Buffer([SMP_PAIRING_CONFIRM]), crypto.c1(this._tk, this._r, this._pres, this._preq, this._iat, this._ia, this._rat, this._ra) ])); };handlePairingResponse の部分です。
g_prompt_passkey がtrueだったら、標準入力からPasskeyを入力してもらいます。
標準入力には今回readline-syncを使いました。
> npm install readline-sync
g_prompt_passkey がfalse だったら、g_passkey をPasskeyとみなして処理を進めます。
Just Worksの場合にはこれが0固定でした。必要に応じてペアリングする
普段は認証無しでアクセスしているが、認証が必要なアクセスがあったときにペアリングするようにします。
認証が必要かどうかは、BLEペリフェラル側が教えてくれます。必要な時には、Security Requestの通知がBLEセントラルに送られてきますので、そのハンドリングを追加します。※なくてもうまくいくような気がしますが。。。
以下のところで、
var SMP_PAIRING_REQUEST = 0x01; var SMP_PAIRING_RESPONSE = 0x02; var SMP_PAIRING_CONFIRM = 0x03; var SMP_PAIRING_RANDOM = 0x04; var SMP_PAIRING_FAILED = 0x05; var SMP_ENCRYPT_INFO = 0x06; var SMP_MASTER_IDENT = 0x07;以下を追加。
var SMP_SECURITY_REQUEST = 0x0b;以下のところを
} else if (SMP_MASTER_IDENT === code) { this.handleMasterIdent(data); }以下のように末尾に追加。
} else if (SMP_MASTER_IDENT === code) { this.handleMasterIdent(data); } else if( SMP_SECURITY_REQUEST == code ){ this.handleSecurityRequest(data); }以下がその実装。
Smp.prototype.handleSecurityRequest = function(data){ this.sendPairingRequest(); };動作
こんな感じで、g_prompt_passkey =true にすると、Passkeyを求められます。
handlePairingResponse Input Passkey : ★ここでPasskeyを入力します。 handlePairingConfirm handlePairingRandom pairing okPasskeyの入力では、BLEペリフェラル側から指定されていた場合にはその値をここで入力し、逆の場合は、ここで入力した値をBLEペリフェラル側にも入力してください。
以上
- 投稿日:2020-03-20T11:41:54+09:00
AutoML Visionを使った鼓膜画像判別Botの作成
概要
普段は耳鼻科の開業医をしています。
今回AutoML Visionで作成した鼓膜画像分類モデルを使った鼓膜画像判別Botを作ってみました。Botが診断するのは法的にまずいので公開はしない予定ですが、名前は鼓膜占いボットということにしておきました(占いならよさそうなので)。前回までの記事はこちら
GCP Cloud AutoML Vision を使った鼓膜画像分類
Node.jsからAutoML Vision の鼓膜画像分類モデルを使ってみる完成動画
AutoMLを使った鼓膜占いBot pic.twitter.com/Vye3d3Bj5K
— 病気のセルフチェック (@Selfcheckhealt1) March 20, 2020概念図
作成
1.必要なパッケージのインストール
npm install --save fetch-base642.プログラムの作成
aombot.js'use strict'; require('dotenv').config(); const fetch = require('fetch-base64'); const express = require('express'); const line = require('@line/bot-sdk'); const PORT = process.env.PORT || 3000; const config = { channelSecret: "自分のチャンネルシークレット", channelAccessToken: "自分のアクセストークン" }; const automl = require('@google-cloud/automl'); // Create client for prediction service. const mlclient = new automl.PredictionServiceClient(); const projectId = "自分のプロジェクト名"; const computeRegion = "us-central1"; const modelId = "自分のモデルID"; const scoreThreshold = "0.5"; // Get the full path of the model. const modelFullId = mlclient.modelPath(projectId, computeRegion, modelId); const aomLabels = { "aom": "急性中耳炎", "ome": "滲出性中耳炎", "normal": "正常鼓膜", }; const app = express(); app.use(express.static('public')); //追加 app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない) app.post('/webhook', line.middleware(config), (req, res) => { console.log(req.body.events); //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。 if (req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff') { res.send('Hello LINE BOT!(POST)'); console.log('疎通確認用'); return; } Promise .all(req.body.events.map(event => handleEvent(event, req))) .then((result) => res.json(result)); }); const client = new line.Client(config); async function handleEvent(event, req) { console.log(req); if (event.type !== 'message' || (event.message.type !== 'text' && event.message.type !== 'image')) { return Promise.resolve(null); } const params = {}; params.score_threshold = scoreThreshold; // Read the file content for prediction. const data = await fetch.remote({ url: `https://api-data.line.me/v2/bot/message/${event.message.id}/content`, headers: { 'Authorization': `Bearer ${process.env.CHANNEL_ACCESS_TOKEN}` } }); const payload = {}; payload.image = { imageBytes: data[0] }; // params is additional domain-specific parameters. // currently there is no additional parameters supported. const [response] = await mlclient.predict({ name: modelFullId, payload: payload, params: params, }); if (response.payload.length === 0) { return client.replyMessage(event.replyToken, { type: 'text', text: `ちょっとわかりませんね・・・` }); } return client.replyMessage(event.replyToken, { type: 'text', text: `出ました!占いではあなたの耳は${aomLabels[response.payload[0].displayName]}と出ています。` }); } app.listen(PORT); console.log(`Server running at ${PORT}`);.envはこちら
GOOGLE_APPLICATION_CREDENTIALS=./ダウンロードしたJsonファイル名 CHANNEL_ACCESS_TOKEN=自分のチャンネルアクセストークン考察
AutoML Visionで作成した鼓膜画像分類モデルを使った鼓膜画像認識Botを作成することが出来ました。実際テストすると急性中耳炎・滲出性中耳炎・正常鼓膜の判別は9割ほどの正解率でした。
最初は信頼度(0~1の間の数字で表される)も同時に表示しようとしたのですが下のねこの写真のように鼓膜以外の写真を送った場合でも高い信頼度(下の写真では1)が表示されてしまいます。
これはモデルは急性中耳炎と滲出性中耳炎と正常鼓膜の3つタグだけで鼓膜以外の画像を教師データとして登録していないためと思われます。
実用性を求めるなら1段回目として鼓膜画像検出を行い(ここに鼓膜以外の教師データを入れる)、2段階目として中耳炎の判定を行うような構成が必要と思われました。
- 投稿日:2020-03-20T10:10:23+09:00
Windows10にSSL通信のWebサーバを作るメモ
はじめに
Windows10にSSL通信のWebサーバを作るための備忘録
いつも忘れるのでメモ必要なもの
- Windows10
- Webサーバ構築する
- nodejsインストール済
- nodejs : v12.13.1
- npm : 6.13.4
- ラズパイ
- オレオレ証明書(SSL証明書)を作る
オレオレ証明書を作る
$ openssl genrsa 2048 > server.key $ openssl req -new -key server.key > server.csr $ openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crtWebサイトを作る
$ mkdir hoge $ cd hoge $ npm init $ npm install express --save $ mkdir ssl $ mkdir wwwroot $ touch wwwroot/test.html $ touch app.js※sslディレクト配下にオレオレ証明書をコピー
PS C:\Users\user\nodejs\hoge> tree /f フォルダー パスの一覧: ボリューム Local Disk ボリューム シリアル番号は XXXX-XXXX です C:. │ app.js │ bk-app.js │ package-lock.json │ package.json │ ├─ssl │ server.crt │ server.csr │ server.key │ └─wwwroot test.htmlwwwroot/test.html<!DOCTYPE html> <html> <head><title>TEST</title></head> <body>Test</body> </html>app.js"use strict"; var express = require("express"); var app = express(); app.use(express.static("wwwroot")); app.get("/", function(req, res) { res.sendFile("wwwroot/index.html"); }); let port1 = 3000; let port2 = 3001; // http サーバ var http = require("http").Server(app); http.listen(port1,function(){ console.log("\tサーバがポート%dで起動しました。モード:%s",port1,app.settings.env) }); // https サーバ var fs = require("fs"); var opt = { key: fs.readFileSync("ssl/server.key"), cert: fs.readFileSync("ssl/server.crt"), passphrase: "password", // オレオレ証明書でのパスワードを書く }; var https = require("https").Server(opt, app); // https サーバを立てる https.listen(port2,function(){ console.log("\tサーバがポート%dで起動しました。モード:%s",port2,app.settings.env) });動作確認
PS C:\Users\user\nodejs\hoge> pwd Path ---- C:\Users\user\nodejs\hoge PS C:\Users\user\nodejs\hoge> node app.js サーバがポート3000で起動しました。モード:development サーバがポート3001で起動しました。モード:developmentブラウザで以下サイトにアクセスできれば成功
- 投稿日:2020-03-20T10:10:23+09:00
Windows10にオレオレ証明書でSSL通信のWebサーバを作るメモ
はじめに
Windows10にSSL通信のWebサーバを作るための備忘録
いつも忘れるのでメモ必要なもの
- Windows10
- Webサーバ構築する
- nodejsインストール済
- nodejs : v12.13.1
- npm : 6.13.4
- ラズパイ
- オレオレ証明書(SSL証明書)を作る
オレオレ証明書を作る
$ openssl genrsa 2048 > server.key $ openssl req -new -key server.key > server.csr $ openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crtWebサイトを作る
$ mkdir hoge $ cd hoge $ npm init $ npm install express --save $ mkdir ssl $ mkdir wwwroot $ touch wwwroot/test.html $ touch app.js※sslディレクト配下にオレオレ証明書をコピー
PS C:\Users\user\nodejs\hoge> tree /f フォルダー パスの一覧: ボリューム Local Disk ボリューム シリアル番号は XXXX-XXXX です C:. │ app.js │ package-lock.json │ package.json │ │ ├─node_modules │ ・・略・・ │ ├─ssl │ server.crt │ server.csr │ server.key │ └─wwwroot test.htmlwwwroot/test.html<!DOCTYPE html> <html> <head><title>TEST</title></head> <body>Test</body> </html>app.js"use strict"; var express = require("express"); var app = express(); app.use(express.static("wwwroot")); app.get("/", function(req, res) { res.sendFile("wwwroot/index.html"); }); let port1 = 3000; let port2 = 3001; // http サーバ var http = require("http").Server(app); http.listen(port1,function(){ console.log("\tサーバがポート%dで起動しました。モード:%s",port1,app.settings.env) }); // https サーバ var fs = require("fs"); var opt = { key: fs.readFileSync("ssl/server.key"), cert: fs.readFileSync("ssl/server.crt"), passphrase: "password", // オレオレ証明書でのパスワードを書く }; var https = require("https").Server(opt, app); // https サーバを立てる https.listen(port2,function(){ console.log("\tサーバがポート%dで起動しました。モード:%s",port2,app.settings.env) });動作確認
PS C:\Users\user\nodejs\hoge> pwd Path ---- C:\Users\user\nodejs\hoge PS C:\Users\user\nodejs\hoge> node app.js サーバがポート3000で起動しました。モード:development サーバがポート3001で起動しました。モード:developmentブラウザで以下サイトにアクセスできれば成功
- 投稿日:2020-03-20T00:16:05+09:00
NestJSで特定のサービスのメソッドを直接実行する
NestJSをLambdaでホストしているとき、特定のサービスのメソッドをダイレクトに実行したい場合があります。
例:cronジョブをCloudWatch Event -> Lambdaで実行する
そういう時はこんな感じのhandlerを作ればOKです。
import { NestFactory } from '@nestjs/core' import { Handler } from 'aws-lambda' // 実行したいサービスのあるモジュール import { SiteModule } from './site.module' // 実行したいサービス import { SiteService } from './site.service' export const handler: Handler = async (event) => { // Create NestJS application const app = await NestFactory.create(SiteModule) // Resolve Dependencies const service = await app.resolve(SiteService) // Execute method const result = await service.listSite(event.username) return result };NestJSをLambdaでってどうなの?
パフォーマンス期待するならやめた方がいいと思います。
Fargateとかその辺覚える労力より先にNestJS使いこなせるようになりたい目的でLambdaに載せてるだけなので・・・ただ、この記事のような形で、すでに動かしているNestJSアプリケーションの実装を使ったバッチ処理をLambdaにやらせるのはありかもしれません。
ジョブのリトライとか通知とかその辺りの便利機能がLambdaにはありますし、バッチ系なら多少立ち上がりが遅くても問題ないですし。