gba-3のメモ

てきとー

Go言語で順列を実装

permute.go

package main

func Permute(nums []int) [][]int {
    ans := calc(nums)
    return ans
}

func calc(nums []int) [][]int {
    if len(nums) == 0 {
        return [][]int{}
    }
    var ans [][]int
    for i := range nums {
        arr := []int{}
        for j := range nums {
            if i != j {
                arr = append(arr, nums[j])
            }
        }
        childs := calc(arr)
        if len(childs) == 0 {
            ans = append(ans, []int{nums[i]})
            return ans
        }
        for _, child := range childs {
            pattern := append([]int{nums[i]}, child...)
            ans = append(ans, pattern)
        }
    }
    return ans
}

main.go

package main

import (
    "fmt"
)

func main() {
    nums := []int{1, 2, 3}
    for _, v := range Permute(nums) {
        fmt.Println(v)
    }
}

実行結果

[1 2 3]
[1 3 2]
[2 1 3]
[2 3 1]
[3 1 2]
[3 2 1]

inline-blockで上寄せさせたい時

はじめに

inline-blockで横並びさせる時、要素の高さがバラバラだと一番高い要素の下面に合わせて配置される。
上寄せさせたいため、その方法を記載する。

方法

inline-blockなのでvertical-alignが使用できる。
以下のように記載することで上寄せすることができる。

クラス名 {
  display: inline-block;
  vertical-align: 'top';
}

参考文献

developer.mozilla.org

laravel passportでユーザー情報を取得(laravel6)

はじめに

laravelを学習し始めたのでlaravel passportを利用してユーザー情報の取得を行った
ログイン機能の作成部分まではlaravelのドキュメントを流用しているのでそちらをみるとより正確な情報を得ることができるので、ぜひそちらを見てください

環境

  • laravel 6.5.1
  • mysql 5.7

手順

laravel passportのパッケージをインストール

$ composer require laravel/passport

クライアントとアクセストークンを保存しておくためのテーブルを作成

$ php artisan migrate

App\UserモデルにLaravel\Passport\HasApiTokensトレイトを追加する

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens; // 追加

class User extends Authenticatable
{
    use HasApiTokens, Notifiable; // HasApiTokensを追加
}

AuthServiceProvider.php内でアクセストークンの発行、失効のためにPassport::routesメソッドを呼び出す

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport; // 追加

class AuthServiceProvider extends ServiceProvider
{
    /**
     * アプリケーションのポリシーのマップ
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy', // 最初はコメントされているのでコメントを削除する
    ];

    /**
     * 全認証/認可サービスの登録
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes(); // 追加
    }
}

config/auth.php内のガードのapi認証のdriverオプションをtokenからpassportに変更する

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport', // token => passport
        'provider' => 'users',
    ],
],

アクセストークンを生成するために必要な暗号キーの作成

$ php artisan passport:install

コントローラーの作成

$ php artisan make:controller Api/AuthController

Api/AuthControllerにloginメソッドを作成

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\JsonResponse;


class AuthController extends Controller
{
    public function login(Request $request): JsonResponse
    {
        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            $user = Auth::user();
            $token = $user->createToken('Laravel Password Grant Client')->accessToken;
            return new JsonResponse(['token' => $token], 200);
        }

        return new JsonResponse([
            'message' => 'Unauthenticated.'
        ], 401);
    }
}

routes/api.phpにログイン用のルートを追加

Route::post('/login', 'Api\AuthController@login');

ユーザーの作成

$ php artisan tinker
$ $user = new App\User;
$ $user->name = 'testuser';
$ $user->email = 'test@email.com';
$ $user->password = Hash::make('testtest');
$ $user->save();

Tokenをリクエストする

$ curl -X POST http://localhost:8000/api/login -d email=test@email.com -d password=testtest

レスポンス

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI2IiwianRpIjoiZmU1YWE4OGY1MTRkYzdmZDUyOTlkYzMyZDE3NmIwNGM0YWE0MDRhNWZkMzBkYmFmYjJhYzExMDhiYWNkNDJiOTc0ZDY4OTQ1MWU5MTcwYWMiLCJpYXQiOjE1NzQwOTI4MjMsIm5iZiI6MTU3NDA5MjgyMywiZXhwIjoxNjA1NzE1MjIzLCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.B6FoP_dLWwCN9S17WxMUplPKVZyLwaW7zIRzVJJm-sFlCQ65JOxtGYgsVWeAHmadnmwOJ3yL3Yz1mHHpBFk9ZFD3mGy23UQIqGM71JUyrvjrAlDLmiyqNGz1PUM-7_ta3FM4-KDn7OWCiUnYHZMWJtylP9wvQ8b3ArglC4DeaQxgGvCQS7_vavB1_o0I7kEkqRjHuXl0-7I_w9E2FQXJHrw7tFPdznAy6rkeOYMLKdDEvAOdSlNXCwwhiARPFWiTk7NaBAlfa0Wjf8MeJSFIlUf9AiJo7lLu8r28A4Miik7J_Y9dRxipUcdCjiz7gPjPqFXeeqhH1NQk_qC-6Fy2u2xzx6pAU-Lu1vp32TANn9ZQ5Vn0xFxJJBTJ0FoOzqcQ44fb5T93K9sCIc_1L_X75K3g5KsY96N4h_bZr84e_VUvB_WHQ0iq8VJO2F-Lj1tsSJiUOUwepB1d2eIWbFzWTc1Ur56crUoBr27GoilhFT-8qp5Md2qoOeottu5qO1v5ybOj9DGZIKeZVN_z4L4awb-IuseMGQQCbfquMNmBaLAmgFTlhA3usoiArp9sX4WC1uphf9u9bhAr5tCiqdeVI5K-lLo_qESfP_Zney2IZtmLNCrNpjwxk7BJA7Sl4oI0clUYg-NJnrhRIRW7DHg1Z7eHZsaItDORCkr78HMlHr4"}

Tokenからユーザー情報を取得

$ curl -X GET http://localhost:8000/api/user -H 'Content-Type: application/json' -H 'Authorization: Bearer 取得したToken'

レスポンス

{"id":1,"name":"test","email":"test@email.com","email_verified_at":null,"created_at":"2019-11-18 10:56:18","updated_at":"2019-11-18 10:56:18"}

以上でユーザー情報の取得をできるようになりました。

参考文献

Vue.js 学習記録1

はじめに

Vue.jsでpropsを使っていてネストしたオブジェクトのkeyが存在するかを判定する方法について記録

実装方法

export default 外にpropsで必須のkeyを指定する

const propsDefault = () => ({
  id: 1,
  name: '',
  body: ''
})

props内でvalidatorを設定する

props: {
  item: {
    type: Object,
    validator: v => {
      return Object.key(v).sort().join() === Object.keys(propsDefault).sort().join()
    }
  }
}

これでpropsで受け取ったネストしたオブジェクトのkeyが存在するかを判定できる

UbuntuでもMacみたいにトラックパッドでワークスペースを変える

はじめに

ノートパソコンにUbuntuを入れたけどMacみたいにトラックパッドワークスペースが切り替えれない。 なのでトラックパッドワークスペースを切り替えれるようにしました。

環境

パッケージのインストール

# ユーザーをinput groupに入れる
$ sudo gpasswd -a $USER input

# ライブラリをインストール
$ sudo apt install xdotool wmctrl libinput-tools

# クローンとインストール
$ git clone http://github.com/bulletmark/libinput-gestures

$ cd libinput-gestures

$ sudo ./libinput-gestures-setup install

PCを再起動する

$ touch ~/.config/libinput-gestures.conf

中身は以下のようにした

gesture swipe left 4 xdotool key alt+control+Down
gesture swipe right 4 xdotool key alt+control+Up

libinput-gestures-setup restartを実行して再読込する。 これで4つ指でワークスペースを切り替えることができるようになりました。

Javascriptでメモ帳作成 クソコードを書いてしまった

はじめに

Javascriptの勉強をしててそういえばメモ帳作ってないなと思い作ってみました。

しかし、クソコード。

クソコードでも一応記録として残しとく。

作成したもの

f:id:gba-3:20190430172431p:plain
メモ帳

作った機能

  • 保存機能
  • 編集機能
  • 削除機能

作れなかった機能

  • 選択範囲太字機能
  • 選択範囲斜体機能
  • 選択範囲下線機能

ソースコード

const MEMO_APP = () => {

  let currentIndex = 0; // 作業中のインデックス番号
  class Item {
    constructor(id, title, text) {
      this.id = id;
      this.title = title;
      this.text = text;
    }
  }

  const initState = () => {
    if (!localStorage.id) {
      localStorage.setItem('id', 0);
    } else {
      Model._stateAll = JSON.parse(localStorage.memos);
    }
  }

  const Model = {
    _stateAll : [],

    /**
     * 
     * @param {String} type 
     * @param {*} arg 
     */
    setItem(type, arg) {
      switch(type) {
        case 'add':
          this._stateAll.push(arg);
          localStorage.setItem('memos', JSON.stringify(this._stateAll));
          localStorage.id ++;
          break;
        case 'edit':
          this._stateAll[arg.id - 1].title = arg.title;
          this._stateAll[arg.id - 1].text = arg.text;
          localStorage.setItem('memos', JSON.stringify(this._stateAll));
          break;
        default:
          throw Error('The value of the argument is invalid');
      } 
    },
    /**
     * 
     * @param {String} type 
     * @param {*} arg 
     */
    removeItem(type, arg) {
      switch (type) {
        case 'remove':
          let count = 0;
          for (let value of this._stateAll) {
            if (value.id === arg) {
              this._stateAll.splice(count, 1);
            }
          }
          console.log(this._stateAll)
          localStorage.setItem('memos', JSON.stringify(this._stateAll));
          break;
        default:
          throw Error('The value of the argument is invalid');
      }
    }
  }
  
  /**
   * イベント
   */
  const setFormEvent = (memoId) => {
    const form = document.querySelector('form');
    
    /**
     * 初期化
     */
    const initForm = () => {
      form.reset();
      currentIndex = 0;
    }
    /**
     * セーブ
     */
    const saveForm = () => {
      const editTitle = document.querySelector('#editTitle');
      const editText = document.querySelector('#editText');
     
      if (!currentIndex) {
        let memo = new Item(JSON.parse(localStorage.id)+1, editTitle.value, editText.value);
        Model.setItem('add', memo);
      } else {
        let memo = new Item(currentIndex, editTitle.value, editText.value);
        Model.setItem('edit', memo);
      }

      render();
    }

    /**
     * 削除 
     */
    const trashMemo = () => {
      console.log(currentIndex)
      Model.removeItem('remove', currentIndex);
      initForm();
      render();
    }

    /**
     * セーブイベント
     */
    const saveEvnet = () => {
      const saveBtn = document.querySelector('.fa-save');
      //saveBtn.removeEventListener('click', editForm, { passive: false });
      saveBtn.addEventListener('click', saveForm, { passive: false });
      
    }
    
    /**
     * 追加イベント
     */
    const addEvent = () => {
      const plusBtn = document.querySelector('.fa-plus');
      plusBtn.addEventListener('click', initForm, { passive: false })
    }

    /**
     * 削除イベント
     */
    const trashEvent = () => {
      const trashBtn = document.querySelector('.fa-trash');
      trashBtn.addEventListener('click', trashMemo, { passive: false });
    }

    addEvent();
    saveEvnet();
    trashEvent();
  }

  const renderMemoList = (value) => {
    const div = document.createElement('div');
    div.classList.add('memo');
    div.textContent = `${value.title}`;
    memoList.appendChild(div);
    
    div.addEventListener('click', function () {
      const editTitle = document.querySelector('#editTitle');
      const editText = document.querySelector('#editText');
      editTitle.value = value.title;
      editText.value = value.text;
      currentIndex = value.id;
      //setFormEvent(value.id);
    })
  }

  /**
   * 描画関数
   */
  const render = () => {
    const memoList = document.querySelector('#memoList');
    const memos = JSON.parse(localStorage.memos);
    memoList.textContent = ""; //初期化
    for (let value of memos) {
      renderMemoList(value);      
    }
  }

  const start = () => {
    setFormEvent();
    initState();
  }

  start();
  if (localStorage.memos) {
    render();
  }
}

MEMO_APP();

中身について

currentIndexは作業中のメモのidを保持するための変数

idとmemosというkeyで分けている idは最新のid番号の保持の役割をしていて、新規メモ作成時のmemos.idはlocalStorage.idを使う。 localStorageのステートの変更はすべてsetItemメソッドで行っておりModel._stateAllのステートを更新してから行う。

まとめ

どこをどうみてもクソコードすぎる。 初心者の方がまだましなコードが書けそう。 プログラム設計についてしっかり考えないといけないと思いました。