エンジニアの備忘録

学んだ事をアウトプットしていきます

プロジェクト工程の各フェーズの役割

picture_pc_713febd69ea445f40922900998dd5a80.jpg

要件定義

やること/やらないことを明確にする

  • 業務要件

    • システムの概要
    • ユースケース
      • →管理者やユーザーの出来る事を図等で記載
  • 機能要件

    • アプリの種類
      • →PCのみか?スマホはやるのか?
    • 外部システム連携
      • →どのAPIを引っ張ってくるか?
    • 機能一覧

(例) | カテゴリー | 機能 | 実装方法 | 必須 | 備考 | |:-:|:-:|:-:|:-:|:-:| |フロント機能|会員登録フォーム|会員登録 | | | | | | クレカ登録 | | |

  • 非機能要件
    • インフラ構成
    • キャパシティプランニング
      • →ユーザー数、コンテンツ数等の規模は?7
    • 性能要件
      • →画面表示はx秒を目標etc.機能目標を記載
    • 可用性
      • →システムが動く時間は?(99.9%等)
      • →可用性を満たす為の対処は?
    • 死活監視
      • →システムは正常に作動しているか?
      • →何を用いて監視するか?
      • →作動してない場合どう対処するか?

補足:図を挟む場合はUMLを用いる

要件定義における成果物一覧と書き方 https://pm-rasinban.com/rd-write

設計

誰に対して? 何を行う?
基本設計(外部設計) 顧客(システム開発の依頼者 ) 顧客が理解できる範囲で可能な限り使用を決めるフェーズ
・画面デザイン、インフラ構成、バッチの挙動
詳細設計(内部設計) PG どうやって実装すべきかを設計する
・クラス図、シーケンス図

基本設計

要件定義書を元に顧客と詳細な仕様を決める 顧客に向けての成果物なので、IT用語は極力避ける 決定事項は「基本設計書」に記載する

  1. 表紙
  2. 改訂履歴
  3. 目次
  4. 機能一覧 →要件定義書でおおまかに固めて、基本設計書で細かい部分を決める
  5. システム構成 →インフラ・サーバー側の構成図 →draw.io等で作成
  6. 画面設計 →画面遷移図 →ドキュメントよりもモックアップツールで作成がおすすめ
  7. 帳票設計 →帳票=PDF・CVSのファイルや印刷物の事 →帳票がなければ必要はない
  8. バッチ設計 →バッチ=自動で動くプログラムの事 →バッチ一覧:クレジットカードの月額課金バッチetc. →バッチ詳細:目的・トリガー・処理フローで構成
  9. データ移行設計 →旧システムのDBから新システムのDBにリプレイスする事 →新規開発であれば必要はない

基本設計書のサンプル https://www.dennogo.jp/assets/templat... https://www.cc.nitech.ac.jp/public/de...

詳細設計

「基本設計の内容の反映」と「PGに最低限の材料を渡す」 クラス図などのUMLを「詳細設計書」に記載するのが一般的 詳細設計書を基に単体テストを行う 運用保守時の調査資料になる

最低限作成するべきモノ

  • テーブル定義書
    • 少しずつより、一気に作るのが良い
  • データ転送表・更新表
    • 基本設計で決めた内容をベースに作成
    • OP処理はデータの取得元を
    • IP処理はデータの更新先を記載
  • 画面・帳票レイアウト
    • 基本設計で決めた内容をベースに作成
    • 桁数、入力順、日本語の使用可否等、細かい所は補足する
  • エラーチェック

参考URL: 「詳細設計書」を作ってみる https://qiita.com/minimumskills/items/556e963c54e95c0a540a

テスト

image.png

単体テスト

  • 機能単位のテスト
  • 関数単位・画面のパーツ単位など、出来るだけ小さな単位でテストを行う

単体テスト仕様書

(一例) | テスト対象 | テスト内容 | 期待結果 | テスト結果 | ステータス | 担当 | バグ内容 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:| | ログインフォーム | 正しいemailとパスを入力してログインボタンをクリック | ログイン成功→マイページへ遷移 |〇 | | | 田中 |

結合テスト

機能同士を組み合わせたテスト

(例1) 管理者:動画を公開 ユーザー:動画を見る ↓  管理者が投稿した動画を、ユーザーは動画を見る事が出来るか?

(例2) ユーザー:カード情報を登録 ↓ カード決済外部システム:正しいカード番号か? ↓  正しければ月額課金がスタートされる

総合テスト

  • 機能テスト
    • 本番環境+本番データで行う
    • 全体をシナリオでテスト
      • 管理者が投稿→ユーザーが入会→ログイン→投稿閲覧 のように正しい順序で機能を順番に使用できるか?
  • 非機能テスト
    • 性能試験
      • 要件定義書で定めた機能以外の要件を満たしているか?
      • x秒で画面は返されるか?
      • サーバーに負荷をかけても稼働するか?
    • 監視試験など
      • システムが止まった場合の対処は稼働しているか?

Reactをver.17でインストールする手順

React17のインストールから起動まで

  1. npx create-react-app react-testでreactファイル作成
  2. dependenciesを下記に書き替える
    "@testing-library/jest-dom": "^5.16.2", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", "react": "^17.0.2", "react-beautiful-dnd": "^13.1.0", "react-dom": "^17.0.2", "react-scripts": "5.0.0", "web-vitals": "^0.2.4"
  3. package-lock.jsonとnode_modulesを削除
  4. npm install で再インストール
  5. index.jsを下記に書き替える

import React from 'react';
import ReactDOM from 'react-dom';

const App = () => {
return (
<>
<.h1>こんにちは
>
);
}

ReactDOM.render(, document.getElementById("root"));

6.App.jsを下記のように書く

const App = () => {
return (
<>
<.h1>こんにちは</h1>
</>
);
}

ReactDOM.render(<App />, document.getElementById("root"));

7, npm start react-test で表示されたらOK

Git コマンドメモ

githubにアップするまでの流れ

  1. githubリポジトリ作成
  2. githubにアップする為のディレクトリを作成(既に準備されている場合は不要)
  3. githubにアップしたいディレクトリ配下でgit initを叩く
  4. git add .を叩く
  5. git commitを叩く
  6. コメントの入力を求められるので、コメントを記載してエディターを閉じる
  7. git remote add origin https://github.com/gyan94/<作成したリポジトリ名>.gitを叩く(githubからコピーしてくる)
  8. git push -u origin main を叩いたらgithubを確認

 コマンドメモ

git init
.gitディレクトリを作成(隠れファイル)

git clone
"リポジトリ→ローカルにコピーを作成"

git add
"ワークツリー→リポジトリとステージに追加(コミットする変更準備)"

git commit
”ステージに保存されているファイルを変更した事を保存する”

git commit -m "<メッセージ>" 
(1行目に変更内容の要約)
(2行目に空行)
(3行目に変更した理由)
 

git status
”現在の変更状況を確認する”

git diff
”ワークツリーとステージの変更差分を確認する”

git diff --staged
"ステージとコミットとの間の変更内容を表示する"
☆開発するときはステージに追加やコミットする前にdiffで何の変更をしたかを確認してから追加やコミットする癖をつける事。

git log
"変更履歴を確認する"
git log --oneline
'1行で表示する'
git log -n <コミット数>
"表示するコミット数を制限する"

git rm --cached <ファイル名>
"リポジトリにあるファイルだけ削除したいとき"

git mv <旧ファイル><新ファイル>
"ファイルの移動を記録する"

git remote add origin (URL)
"リモートリポジトリ(github)を新規追加する"
→URLはgithubリポジトリ作成時に発行されるものを入れる

git push -u origin main
"リモートリポジトリへ送信(プッシュする)"
"uは初回だけでいい"
"git branchでブランチ名確認(mainかmaster)"

git config --global alias.ci commit
"commitをciに変換する"

 バージョン管理したくないファイルをGit管理から外す

"自動生成されるファイルやパスが記載されているファイルは
gitignoreファイルに記述すること"

 ワークツリーのファイルを元の状態に戻したいとき

git checkout -- <ファイル名>
git checkout -- <ディレクトリ名>
git checkout -- .
"全変更を取り消す"

 ステージした変更を元に戻したい(取消す)とき

git reset HEAD <ファイル名>
git reset HEAD <ディレクトリ名>
git reset HEAD .
"全変更を取り消す"

☆指定した変更をステージから取り消すだけなので、ワークツリーのファイルには影響は与えない

react-hook-formとFirebaseでログイン画面とログイン機能

バージョン

  • react:18.0
  • next.js:13.5.6
  • typescript:5.0

前準備

  1. VSコードから使用するディレクトリに移動
  2. コマンド:「npx create-next-app@latest」 で作成
  3. プロジェクトネームを作成し、import alias? のみNoで、他はYesにして進む
  4. 作成したプロジェクトに移動
  5. コマンド:「code.」 で立ち上げ
  6. コマンド:「npm run dev」 でローカル環境が起動

ソースファイルの前準備

  • app/layout の lang を ja に変更しておく
  • app/globals.css の @tailwind 以外は削除しておく

Firebaseのセットアップ(初期化)

  1. https://console.firebase.google.com/u/0/?hl=ja  にログイン

  2. プロジェクトの追加をクリック
  3. アナリティクスは無効で次へ
    アナリティクス:ユーザーがどれくらい訪れたか?等が分かる機能
  4. 続行
  5. をクリックして次へ
  6. ネーム入力、Hostingは一旦空で次へ
    Firebase Hosting はデプロイで使う機能
  7. 何も変更せず、コンソールに進むをクリック
  8. プロジェクトの設定をクリック

  9. 「npm install firebase」をコピーしてVSCodeに戻りコマンドを叩く
  10. 次に Firebase を初期化し、使用するプロダクトの SDK の利用を開始します。の下記ソースコードをコピーしておく
  11. src\app 直下に「firebase.ts」ファイルを作成
  12. コピーしたソースを張り付ける
    ※apiKey や authDomain は 見られたらいけないので、git管理するならenvファイルや .gitignore を使うこと
  13. firebase.ts ファイルに書き加えて、初期化完了
    import { initializeApp } from "firebase/app";
    import { getAuth } from "firebase/auth";
    import { getFirestore } from "firebase/firestore";

    const firebaseConfig = {
      apiKey: "AIzaSyALIAt79-kG5Z0CzpBLc_KSVexcHOK-HGU",
      authDomain: "chatapplication-with-cha-ac9a9.firebaseapp.com",
      projectId: "chatapplication-with-cha-ac9a9",
      storageBucket: "chatapplication-with-cha-ac9a9.appspot.com",
      messagingSenderId: "745628687411",
      appId: "1:745628687411:web:1b2274a27ea9f17c4dd746",
    };

    const app = initializeApp(firebaseConfig);
    export const db = getFirestore(app);
    export const auth = getAuth(app);

新規登録ページの作成

CSS記法はTaillwind

import React from "react";

const Register = () => {
  return (
    <>
      <div className="h-screen flex flex-col items-center justify-center">
        <form className="bg-white p-8 rounded-lg shadow-md w-96">
          <h1 className="mb-4 text-2xl text-gray-700 font-medium font-">
            新規登録
          </h1>
          <div className="mb-4">
            <label className="block text-sm font-medium">メールアドレス</label>
            <input
              type="text"
              className="mt-1 border-2 rounded-md w-full p-2"
            ></input>
          </div>
          <div className="mb-4">
            <label className="block text-sm font-medium">パスワード</label>
            <input
              type="password"
              className="mt-1 border-2 rouded-mt w-full p-2"
            ></input>
          </div>
          <div className="justify-end flex pb-3">
            <button
              type="submit"
              className="bg-blue-500 hover:bg-blue-700 text-white font-bold px-4 py-2 rounded-md"
            >
              新規登録
            </button>
          </div>
          <div>
            <span>既にアカウントをお持ちの方:</span>
            <button className="text-blue-500 hover:text-blue-800 font-bold">
              ログインページへ
            </button>
          </div>
        </form>
      </div>
    </>
  );
};

export default Register;

 

新規登録機能

打ち込んだメールアドレスのバリデーションチェック

"use client";

import React from "react";
import { useForm, SubmitHandler } from "react-hook-form";

type Inputs = {
  email: string;
  password: string;
};

const Register = () => {
  const {
    // react側が用意しているプロパティ
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Inputs>();

  const onSubmit: SubmitHandler<Inputs> = async (data) => {
    console.log(data);
  };

  return (
    <>
      <div className="h-screen flex flex-col items-center justify-center">
        <form
          onSubmit={handleSubmit(onSubmit)}
          className="bg-white p-8 rounded-lg shadow-md w-96"
        >
          <h1 className="mb-4 text-2xl text-gray-700 font-medium font-">
            新規登録
          </h1>
          <div className="mb-4">
            <label className="block text-sm font-medium">メールアドレス</label>
            <input
              // requiredの値がエラーとして表示される
              {...register("email", { required: "メールアドレスは必須です" })}
              type="text"
              className="mt-1 border-2 rounded-md w-full p-2"
            />
            {/* emailのバリデーションエラー */}
            {errors.email && (
              <span className="text-red-500 text-sm">
                {errors.email?.message}
              </span>
            )}
          </div>
  ~省略~

 

正規表現のバリデーションチェック

<div className="mb-4">
            <label className="block text-sm font-medium">メールアドレス</label>
            <input
              // requiredの値がエラーとして表示される
              {...register("email", {
                required: "メールアドレスは必須です",
                // 正規表現
                pattern: {
                  value:
                    /^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/,
                  message: "正しい形式で入力してください",
                },
              })}
              type="text"
              className="mt-1 border-2 rounded-md w-full p-2"
            />
            {/* emailのバリデーションエラー */}
            {errors.email && (
              <span className="text-red-500 text-sm">
                {errors.email?.message}
              </span>
            )}
          </div>
          <div className="mb-4">
            <label className="block text-sm font-medium">パスワード</label>
            <input
              {...register("password", {
                required: "パスワードは必須です",
                // 文字数制御
                minLength: {
                  value: 6,
                  message: "6文字以上で入力してください。",
                },
              })}
              type="password"
              className="mt-1 border-2 rouded-mt w-full p-2"
            />
          </div>
          {errors.password && (
            <span className="text-red-500 text-sm">
              {errors.password?.message}
            </span>
          )}

 

新規登録を押すとデータが取得される。このデータをfirebaseに登録して新規登録を行う。

Firebaseにユーザー登録

  1. ユーザー管理の為firebaseからをクリック

  2. メール&パスワードを有効にして保存
  3. ウェブサイトで Firebase Authentication を使ってみるの新しいユーザーを登録するを参考に書く

import { auth } from "@/app/firebase";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { useForm, SubmitHandler } from "react-hook-form";

type Inputs = {
  email: string;
  password: string;
};

const Register = () => {
 
  const onSubmit: SubmitHandler<Inputs> = async (data) => {
    await createUserWithEmailAndPassword(auth, data.email, data.password)
      .then((userCredential) => {
        const user = userCredential.user;
      })
      .catch((error) => {
        alert(error);
      });
  };

 

新規登録を押すとユーザーが登録される

useRouterを使いログインページに遷移

  • pushに飛ばしたいパスを指定
  • 今回だと新規登録を押したらログインページに飛ぶ
import { useRouter } from "next/navigation";
const router = useRouter();
router.push("auth/login")

 

ログインページ作成

  • 新規登録ページをコピペして部分的に変更
    • ログインの場合は signInWithEmailAndPassword() を使用する
    • ログインしたらルートディレクトリに飛ばす
    • ログイン失敗のエラー表示
    • 新規登録へ の部分はnextのLinkコンポーネントを使用
"use client";

import { auth } from "@/app/firebase";
import { error } from "console";
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
} from "firebase/auth";
import { useRouter } from "next/navigation";
import React from "react";
import { useForm, SubmitHandler } from "react-hook-form";

type Inputs = {
  email: string;
  password: string;
};

const Register = () => {
  const router = useRouter();

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<Inputs>();

  const onSubmit: SubmitHandler<Inputs> = async (data) => {
    await signInWithEmailAndPassword(auth, data.email, data.password)
      .then((userCredential) => {
        const user = userCredential.user;
        router.push("/");
      })
      .catch((error) => {
        if (error.code === "auth/invalid-credential") {
          alert("存在しないユーザーです。");
        } else {
          alert(error.message);
        }
      });
  };

  return (
    <>
      <div className="h-screen flex flex-col items-center justify-center">
        <form
          onSubmit={handleSubmit(onSubmit)}
          className="bg-white p-8 rounded-lg shadow-md w-96"
        >
          <h1 className="mb-4 text-2xl text-gray-700 font-medium font-">
            ログイン
          </h1>
          <div className="mb-4">
            <label className="block text-sm font-medium">メールアドレス</label>
            <input
              // requiredの値がエラーとして表示される
              {...register("email", {
                required: "メールアドレスは必須です",
                // 正規表現
                pattern: {
                  value:
                    /^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/,
                  message: "正しい形式で入力してください",
                },
              })}
              type="text"
              className="mt-1 border-2 rounded-md w-full p-2"
            />
            {/* emailのバリデーションエラー */}
            {errors.email && (
              <span className="text-red-500 text-sm">
                {errors.email?.message}
              </span>
            )}
          </div>
          <div className="mb-4">
            <label className="block text-sm font-medium">パスワード</label>
            <input
              {...register("password", {
                required: "パスワードは必須です",
                // 文字数制御
                minLength: {
                  value: 6,
                  message: "6文字以上で入力してください。",
                },
              })}
              type="password"
              className="mt-1 border-2 rouded-mt w-full p-2"
            />
          </div>
          {errors.password && (
            <span className="text-red-500 text-sm">
              {errors.password?.message}
            </span>
          )}
          <div className="justify-end flex pb-3">
            <button
              type="submit"
              className="bg-blue-500 hover:bg-blue-700 text-white font-bold px-4 py-2 rounded-md"
            >
              ログイン
            </button>
          </div>
      <div>
            <span>アカウントをお持ちでない方:</span>
            <Link
              href={"/auth/register"}
              className="text-blue-500 hover:text-blue-800 font-bold"
            >
              新規登録へ
            </Link>
          </div>
        </form>
      </div>
    </>
  );
};

export default Register;

 

ログイン画面

PHP用チートシート

ポップアップで論理削除

Modelsに削除用SQL文を

public function findDel($id = 0) {
    $sql = "UPDATE players SET del_flg = '1' ";
  $sql .= " WHERE id = :id";
    $sth = $this->dbh->prepare($sql);
    $sth->bindParam(":id", $id, PDO::PARAM_INT);
    $sth->execute();
    $result = $sth->fetchAll(PDO::FETCH_ASSOC);
    return $result;
}

Controllersにメソッドを作成

public function delete() {
        if(empty($this->request["get"]["id"])) {
            echo "指定のパラメータが不正です。このページは表示できません。";
            exit;
        }

        $delete = $this->Player->findDel($this->request["get"]["id"]);
        $params = [
            "delete" => $delete
        ];
        return $params;
    }

Viewsに表示画面を

削除ボタンをクリック

→ポップアップ表示で「はい」をクリック

→delete.phpに遷移

 クリックしたボタンのIDを送る

 

<?php
$player = new PlayerController();
$params = $player->index();
 
<form action="/PlayerController.php" method="GET">
      <td><button formaction="./delete.php" type="submit"
       onclick="return confirm_delete();">削除</button></td>
        <input type="hidden" name="id" value="<?= $player['id'] ?>">
        </form>
        <script>
          function confirm_delete() {
              var select = confirm("削除してもよろしいですか?");
                  return select;
                  }
        </script>

遷移先でメソッド呼び出し

<?php
$params = $player->delete();
// 下記へ自由にHTMLを記載

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PHP:ポーカーの役判定アルゴリズム

PHP ポーカー でググっても既に学習済みの人じゃないと分からないような難しいコードしか出てこなかったので、このメモが同じ段階で躓いている初心者の人の為になれば幸いです。

準備

まずはロイヤルストレートフラッシュの手持ちからスタート。

ここのマークと数字を書き換えても、ちゃんと役が判定出来るアルゴリズムを作る。

$cards = [

["suite" => "club" , "number" => 4]  // 1枚目

["suite" => "club" , "number" => 3] // 2枚目

["suite" => "club" , "number" => 2] // 3枚目

["suite" => "club" , "number" => 5] // 4枚目

["suite" => "club" , "number" => 1] // 5枚目

]

 

このままでは扱いずらいので、数字とマークを分けておき数字はソートしておく(ストレート等を判定する為)

$hand_num = array_column($cards,"number");

$hand_suit = array_column($cards,"number");

sort($hand_num);

出力結果→

Array (

[0] => 1

[1] => 2

[2] => 3

[3] => 4

[4] => 5 ) です。

 

下準備が出来たので、ここから役を判定するアルゴリズムを考えていきます。

フラッシュ

条件:手札5枚のマークが全て同じマーク

1枚目と2枚目が同じマークかつ・・・4枚目と5枚目が同じマークなら。

  if ($hand_suit[0] == $hand_suit[1] &&
        $hand_suit[1] == $hand_suit[2] &&
        $hand_suit[2] == $hand_suit[3] &&
        $hand_suit[3] == $hand_suit[4] ) {
        $bool_flush = true;
    }

ストレート

条件:1~13の数字内で連番5回続く

もっとスマートに判定する方法があるだろうけど、真っ先に思いついたのが

1~5 2~6 3~7・・・というように全試行していく方法。

if ($str15 ||$str26 ||$str37 ||$str48 ||$str59 ||$str610||$str711||$str812||$str913||$str113) {
        $bool_straight = true;
    }

ストレートフラッシュとロイヤルストレートフラッシュ

条件:ストレートとフラッシュ両方を満たした場合かつ、1.10.11.12.13の連番だった場合

この2つに関してはストレートとフラッシュを組み合わせるだけ。

 

// ストレートフラッシュ

  if ($bool_flush && $bool_straight) {
        $bool_str_flush = true;
    }

// ロイヤルストレートフラッシュ
    if ($bool_str_flush == true && $str113 != true) {  // $str113 = 1.10.11.12.13の連番 
        $bool_royal = true;  
    }

 

フォーカードとスリーカード

条件:同じ数字が3枚、4枚ある場合

例えば手持ちの数字が [5.5.5.5.9]の場合、

  • 1枚目と2枚目のカードが同じ
  • 2枚目と3枚目のカードが同じ
  • 3枚目と4枚目のカードが同じ

この条件を満たせばフォーカードになる。

しかし、[1.5.5.5.5]の場合だとフォーカードなのに判定することが出来なくなるのでボツ。

カードの前後を比較することで判定するのを辞めて、

手札の中の数字とその数字が何枚あるか?を集計して判定する。

 for ($i=1; $i <= 13; $i++) {   
        $count_num[$i] = 0; // 配列の初期化 

    }
    for ($i=0; $i <= 4; $i++) { 
        $count_num[$hand_num[$i]]++; 
    }

出力結果→

1が1枚、5が4枚とカウント出来ているので、下記のコードで判定が可能になる。

(補足:ストレートも最適化可能)

 

for ($i=1; $i <= 13; $i++) { 
        $count_num[$hand_num[$i]]++;

if ($count_num[$i] == 4) {
            $bool_four = true;

if ($count_num[$i] == 3) {
            $bool_three = true;
        }

}

フルハウスとツーペアとワンペア

フルハウス = スリーカード+ワンペア

ツーペア = ワンペアが2つ

なのでワンペアのカウントが出来れば、さっき用意したスリーカードの判定を組み合わせてフルハウスが判定可能になり、ツーペアとワンペアも判定可能になる。

if ($count_num[$i] == 2) {
            $bool_one_pair++;  // ワンペアがあれば+1カウント
        }

if ($bool_three == true && $bool_one_pair == 1) {
            return "フルハウスです";
        }

if ($bool_one_pair == 2) {
            return "ツーペアです";
        }

if ($bool_one_pair == 1) {
        }

 

チェック

ちゃんと判定出来ていました

全ての役判定結果

追記:JOKERが1枚あるとき

まずジョーカーが手札にあった場合カウントする。

// ジョーカーをカウント
        $joker = false;
        if ($hand_num[0] == 0) {
            $joker = true;
        }

例えば、手札の数字に0(=joker)があるときにワンペアが成立してしまうとスリーカードが成立することになるので、ジョーカーが1枚あるときは一部の役に昇格が起きるので、追加しないといけない事が増える。

  • 手札が(0,1,10,11,12)(0,1,11,12,13)(0,1,10,12,13)(0,1,10,11,13)(0,10,11,12,13)だったらロイヤルストレートフラッシュ
  • 0,2,4,5,6 → ストレート
  • 同じマークが4枚+joker → フラッシュ
  • フォーカード+joker → ファイブカード
  • スリーカード+joker → フォーカード
  • ツーペア+joker → フルハウス
  • ワンペア+joker → スリーカード
  • ノーペア+joker → ワンペア

フラッシュ

club・diamond・heart・joker・spadeのいずれかでフラッシュが成立し、アルファベットでソートしたときに下記どちらかを満たしていれば、フラッシュが判定できる。

・1枚目から4枚目はclub・diamond・heartかつ5枚目はjoker

・1枚目はjokerかつ2枚目から5枚目はspade

ストレート

全通りの組み合わせを配列に格納し(面倒)、手持ちがどれかに当てはまっていればジョーカー入りのストレートと判定。

ロイヤルストレートフラッシュとストレートフラッシュ

フラッシュとストレートを組み合わせるだけ。


それ以外の役

特に難しい要素はなく、この通りに当てはめて書くだけ。

  • フォーカード+joker → ファイブカード
  • スリーカード+joker → フォーカード
  • ツーペア+joker → フルハウス
  • ワンペア+joker → スリーカード
  • ノーペア+joker → ワンペア

 

出力結果

無事判定出来てました

 

【CSS : jQuery】メモシート

疑似要素beforeのcolor変更方法

【HTML】
<lispan>class="back_hover1">
<a href="#">educure
<i class="fas fa-arrow-right before_colorChange1"></i></a></li>

 

CSS
.fa-arrow-right:before {
      content: "\f061";
      margin-left: 0.5rem;

      color: #2dbba1; //エメラルドグリーン

  }
  .fa-arrow-right2:before {
    content: "\f061";
    margin-left: 0.5rem;
    transition: 0.2s;
    color: #ffffff; //白色
}

 

// hover →アイコンcolor変更(疑似要素なので、新しいクラスで上書き)
  $(function(){
    $(".back_hover1").hover(function() {
        $('.before_colorChange1').toggleClass('fa-arrow-right2');
});  

.back_hover1 ← カーソルが重なると

.before_colorChange1 ←このクラスの疑似要素(エメラルドグリーン)を

fa-arrow-right2 ← この疑似要素(白色)に上書き

 

ハンバーガーメニューのCSS

 
.humburger-menu {
  /*スクロールするようにする*/
  overflow: scroll;
  /*ハンバーガーをその場に固定*/
  position: fixed;
  /*上端との距離*/
  top: 0;
  /*高さ画面いっぱい*/
  height: 100%;
  /*滑らかスクロール*/
  -webkit-overflow-scrolling: touch;
}

 ハンバーガーメニューを開け閉じするJavaScript

 
function slideIn(){
  // 見やすくするためにするために変数を作成
  var menu = $('.humburger-menu'), // 開け閉じする要素
    menuBtn = $('.hamburger_button'), // メニューボタン
    body = $(document.body),
    menuWidth = menu.outerWidth();

  // メニューボタンをクリックした時の動き
  menuBtn.on('click', function(){
    // body に open クラスをつけたりはずしたりする( open クラスは空)
    body.toggleClass('open');
    if(body.hasClass('open')){
      // open クラスが body についていたらメニューをスライドインする
      body.animate({'right' : menuWidth }, 200);
      menu.animate({'right' : 0 }, 200);
    } else {
      // open クラスが body についていなかったらスライドアウトする
      menu.animate({'right' : -menuWidth }, 200);
      body.animate({'right' : 0 }, 200);
    }
  });
};

 

スクロールバー表示・非表示

$(function(){
  var state = false;
  var pos;
  $("#nav_bar").click(function(){
    if (state == false) {
      pos = $(window).scrollTop();
      $("body").addClass("fixed").css({"top": -pos});
        state = true;
      } else {
      $("body").removeClass("fixed").css({"top": 0});
        window.scrollTo(0, pos);
        state = false;
  }
});
});
//css
body.fixed {
  position: fixed;
  width: 100%;
  height: 100%;
}

画像調整(アスペクト比

// CSS
background-size: cover;
  background-position: center center;
  padding-top: 56.25%;
  width: 100%;
// HTML
style="background-image: url(画像URL)"

16:9  → 9÷16=0.5625 =padding-top:56.25%

アスペクト比 パーセント変換後
4:3 75%
16:9 56.25%
3:2 66.66%
8:5(黄金比 62.5%