HTML
JavaScript
初心者
vue.js
Splatoon

【Vue.js】スプラトゥーン2 おすすめブキ診断をパワーアップさせた【Part2】

前回の記事

スプラトゥーン2 おすすめブキ診断を作ってみた(Vue.js)

前回の記事で、Vue.jsの勉強を兼ねてスプラトゥーン2のおすすめブキ診断を作成したのですが、思ったよりもフィードバックをいただくことができたので、いくつか改修をしてみました。

パワーアップ後のサイト

スプラトゥーン2 ブキ診断 Octo Expansion
(特にタコは関係ありません)

sp2buki.png

改善点

  • タイトルロゴの画像化(イカモドキフォント)
  • 背景色/ボタン色をインクっぽく調整
  • ボタンデザインの調整
  • 質問数の追加
  • ブキ(H3リールガンD、クアッドホッパーブラック)の追加
  • 質問切替時のアニメーション追加
  • 変数宣言の厳格化
  • 比較演算子の厳格化
  • clickAnswer関数の引数をboolean型に変更
  • オブジェクトのキー名を英字に変更
  • ブキの出現頻度を確認する機能を追加※

ブキの出現頻度を確認する機能について

このアプリは上手に設問とポイントを設定しないと、オススメされるブキが特定のブキに偏ってしまうという問題があります。コメントでご指摘いただきましたが、以前のバージョンではどの選択肢を選んでも、デュアルスイーパーカスタムが選択されないという残念仕様になっておりました…。

ということで今回は偏りをなくすために、テストを実施することにしました。「はい」「いいえ」の2択で8問設問があるので、2^8=256通りの全回答パターンを作成し、どのブキがオススメされるかテストすることで、ブキの偏りがないように調整してみました。

dist.png

マニュコラが34回と一番多いですが、強いので良いんじゃないでしょうか(?)

コードは「はい」を"0"、「いいえ」を"1"として、while文でループを回し、
"0""1"→"00""01""10""11"→"000""001""010""011""100""101""110""111"
といった形で回答パターンを作成していきました。
純粋にtrue,falseで配列を作れば良いと思うのですが、多次元配列の操作が思い通りにいかなかったので、力技になっています…。

ソースコード

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>スプラトゥーン2 ブキ診断</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="css/main.css" type="text/css" media="all">
  </head>
  <body>
    <div id="app">
        <img src="img/title.png">
        <p id ="counter" v-if="count">
          {{ counter }} / {{ all }}
        </p>
        <transition appear name="message" mode="out-in">
          <h2 id="message" :key="message">
            {{ message }}
          </h2>
        </transition>
        <div id="choice" v-if="choice">
            <a href="#" class="square_btn yes" v-on:click="clickAnswer(true)">はい</a>
            <a href="#" class="square_btn no" v-on:click="clickAnswer(false)">いいえ</a>
        </div>
        <div id ="retry" v-if="retry_btn">
            <a href="#" class="square_btn yes" v-on:click="retry">リトライする</a>
        </div>
    </div>
    <div id ="about">
      works by <a href="https://qiita.com/Sinhalite">@Sinhalite</a>
    </div>
    <script src="js/main.js" ></script>
  </body>
</html>
main.js
const quetions = [
  "エイムには自信がある",
  "キルよりも塗りのほうが好きだ",
  "かくれんぼが得意だ",
  "ガンガン前に突っ込むのが好きだ",
  "機動力が高い武器が好きだ",
  "トリッキーな武器を使いこなしたい",
  "射程は長めのブキのほうが好きだ",
  "空を飛びたいという願望がある",
];
let counter;
let weapons;

init();
testRecommendation();

function init(){
  counter = 0;
  weapons ={
    spColla:{name:"スプラシューターコラボ",point:0},
    nZap85:{name:"N-ZAP85",point:0},
    maneuColla:{name:"スプラマニューバーコラボ",point:0},
    duaCus:{name:"デュアルスイーパーカスタム",point:0},
    jetCus:{name:"ジェットスイーパーカスタム",point:0},
    spCharger:{name:"スプラチャージャー",point:0},
    hotCus:{name:"ホットブラスターカスタム",point:0},
    spRoller:{name:"スプラローラー",point:0},
    pablo:{name:"パブロ",point:0},
    bucketDeco:{name:"バケットスロッシャーデコ",point:0},
    barrel:{name:"バレルスピナー",point:0},
    paraShelter:{name:"パラシェルター",point:0},
    h3d:{name:"H3リールガンD",point:0},
    quadHopperB:{name:"クアッドホッパーブラック",point:0}
  }
}

const app = new Vue({
  el: '#app',
  data: {
    choice: true,
    retry_btn: false,
    count:true,
    message: quetions[0],
    counter:counter+1,
    all:quetions.length
  },
  methods: {
    clickAnswer: function (answer) {
      addPoint(answer,counter);
      counter += 1;
      if(counter > quetions.length-1){
        let maxCount = 0;
        let maxWeapon = "";
        for(let weapon in weapons) {
          if(maxCount < weapons[weapon].point){
            maxCount = weapons[weapon].point;
            maxWeapon = weapons[weapon].name;
          }
        }
        this.choice = false;
        this.count = false;
        this.message = "あなたには「" + maxWeapon + "」がオススメです!";
        this.retry_btn = true;
      }else{
        this.counter = counter+1;
        this.message = quetions[counter];
      }
    },
    retry: function () {
      init();
      this.counter = counter+1;
      this.choice = true;
      this.count = true;
      this.retry_btn = false;
      this.message = quetions[counter];
    }
  }
});

function addPoint(answer,counter) {
  switch(counter){
    case 0:
      if(answer === true){
        weapons.nZap85.point += 1;
        weapons.jetCus.point += 1;
        weapons.duaCus.point += 1;
        weapons.maneuColla.point += 1;
        weapons.spCharger.point += 1;
        weapons.h3d.point += 2;
        weapons.quadHopperB.point += 1;
      }else{
        weapons.hotCus.point += 1;
        weapons.spRoller.point += 1;
        weapons.pablo.point += 1;
        weapons.bucketDeco.point += 1;
        weapons.barrel.point += 1;
        weapons.paraShelter.point += 1;
      }
      break;
    case 1:
      if(answer === true){
        weapons.nZap85.point += 1;
        weapons.duaCus.point += 1;
        weapons.barrel.point += 1;
        weapons.bucketDeco.point += 1;
      }else{
        weapons.spColla.point += 1;
        weapons.jetCus.point += 1;
        weapons.hotCus.point += 1;
        weapons.spRoller.point += 1;
        weapons.paraShelter.point += 1;
        weapons.maneuColla.point += 1;
        weapons.spCharger.point += 1;
        weapons.quadHopperB.point += 1;
      }
      break;
    case 2:
      if(answer === true){
        weapons.spRoller.point += 1;
        weapons.pablo.point += 1;
      }else{
        weapons.barrel.point += 1;
        weapons.spCharger.point += 1;
        weapons.h3d.point += 1;
      }
      break;
    case 3:
      if(answer === true){
        weapons.spRoller.point += 1;
        weapons.pablo.point += 1;
        weapons.bucketDeco.point += 1;
        weapons.hotCus.point += 1;
        weapons.spColla.point += 1;
        weapons.paraShelter.point += 1;
        weapons.maneuColla.point += 1;
        weapons.quadHopperB.point += 1;
      }else{
        weapons.nZap85.point += 1;
        weapons.duaCus.point += 1;
        weapons.jetCus.point += 1;
        weapons.barrel.point += 1;
        weapons.spCharger.point += 1;
        weapons.h3d.point += 1;
      }
      break;
    case 4:
      if(answer === true){
        weapons.spRoller.point += 1;
        weapons.pablo.point += 1;
        weapons.nZap85.point += 1;
        weapons.duaCus.point += 1;
        weapons.spColla.point += 1;
        weapons.maneuColla.point += 1;
        weapons.quadHopperB.point += 1;
      }else{
        weapons.hotCus.point += 1;
        weapons.bucketDeco.point += 1;
        weapons.jetCus.point += 1;
        weapons.barrel.point += 1;
        weapons.spCharger.point += 1;
      }
      break;
    case 5:
      if(answer === true){
        weapons.paraShelter.point += 2;
        weapons.quadHopperB.point += 2;
        weapons.h3d.point += 1;
        weapons.pablo.point += 1;
      }else{
      }
      break;
    case 6:
      if(answer === true){
        weapons.jetCus.point += 1;
        weapons.duaCus.point += 1;
        weapons.barrel.point += 1;
        weapons.spCharger.point += 1;
        weapons.h3d.point += 1;
        weapons.bucketDeco.point += 1;
      }else{
        weapons.spRoller.point += 1;
        weapons.nZap85.point += 1;
        weapons.spColla.point += 1;
        weapons.maneuColla.point += 1;
        weapons.hotCus.point += 1;
        weapons.paraShelter.point += 1;
        weapons.pablo.point += 1;
      }
      break;
    case 7:
      if(answer === true){
        weapons.spColla.point += 1;
        weapons.maneuColla.point += 1;
        weapons.hotCus.point += 1;
      }else{
      }
      break;
  }
}

function testRecommendation(){
  let distribution ={
    spColla:{name:"スプラシューターコラボ",point:0},
    nZap85:{name:"N-ZAP85",point:0},
    maneuColla:{name:"スプラマニューバーコラボ",point:0},
    duaCus:{name:"デュアルスイーパーカスタム",point:0},
    jetCus:{name:"ジェットスイーパーカスタム",point:0},
    spCharger:{name:"スプラチャージャー",point:0},
    hotCus:{name:"ホットブラスターカスタム",point:0},
    spRoller:{name:"スプラローラー",point:0},
    pablo:{name:"パブロ",point:0},
    bucketDeco:{name:"バケットスロッシャーデコ",point:0},
    barrel:{name:"バレルスピナー",point:0},
    paraShelter:{name:"パラシェルター",point:0},
    h3d:{name:"H3リールガンD",point:0},
    quadHopperB:{name:"クアッドホッパーブラック",point:0}
  }
  let answerPattern =["0","1"];
  let tempAnswerPattern =[];
  let loopCounter = 0;

  while(loopCounter < quetions.length - 1){
    for(let answer of answerPattern){
      tempAnswerPattern.push(answer + "0");
      tempAnswerPattern.push(answer + "1");
    }
    answerPattern = tempAnswerPattern;
    tempAnswerPattern = [];
    loopCounter += 1;
  }

  for(let answer of answerPattern){
    let answerList = answer.split("");
    for(let singleAnswer of answerList){
      if(singleAnswer === "0"){
        singleAnswer = true;
      }else{
        singleAnswer = false;
      }
      addPoint(singleAnswer,counter);
      counter += 1;
    }

    let maxCount = 0;
    let maxWeapon = "";
    for(let weapon in weapons) {
      if(maxCount < weapons[weapon].point){
        maxCount = weapons[weapon].point;
        maxWeapon = weapon;
      }
    }
    distribution[maxWeapon].point += 1;
    init();
  }
      console.log(distribution);
}

おわりに

テストコードとメイン処理のコードで一部重複してる記述もあり、イマイチかなと思いつつも、とりあえず公開してみました。
もっと良い書き方などあれば、ご教授いただけると幸いです:bow_tone2: