---
sidebar_position: 3
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Hướng dẫn Javascript (CORE)

Các dòng `code (lệnh)` được viết sẵn đầy đủ các chức năng cơ bản để hoạt động đồng bộ với `API Adman` trong các thẻ `<script></script>` phía dưới cùng.

## HTML/CSS Mẫu

<details>
<summary>HTML/CSS Mẫu</summary>
<Tabs>
<TabItem value="html" label="HTML">

```html
<div class="main-game">
  <div class="container">
    <!-- HEADER -->
    <div class="header d-flex flex-column align-items-center pt-4">
      <!-- MINIGAME NAME -->
      <h1 class="js-minigame-name">MINIGAME</h1>

      <!-- TIME END -->
      <h2 class="js-minigame-endtime">THỜI GIAN KẾT THÚC</h2>

      <!-- PLAYER STATUS -->
      <div class="users-status text-center color-white">
        <p>
          Số người đang online:
          <i class="js-users-status-online blink font-weight-700">999</i>
        </p>
        <p>
          Đã chơi:
          <i class="js-users-status-played blink font-weight-700">999</i>
        </p>
        <p>
          Đang chơi:
          <i class="js-users-status-playing blink font-weight-700">999</i>
        </p>
      </div>
    </div>

    <!-- MAIN CONTENT -->
    <div class="main-content pt-4">
      <!-- MINI GAME -->
      <div class="mini-game d-flex align-items-center justify-content-between">
        <!-- PLAYER -->
        <div class="player">
          <a
            href="javascript:window.scroll({top:10000,behavior:'smooth'});"
            class="font-weight-500 text-center"
          >
          </a>
          <div action="" class="form">
            <p class="form-title font-weight-900 text-center">
              Vui lòng nhập thông tin của bạn để bắt đầu quay
            </p>

            <div class="form-list" id="js-user-info">
              <!-- Ajax holder -->
            </div>

            <p id="js-game-status" class="font-weight-700 color-red my-3"></p>
            <p id="js-game-notify" class="font-weight-700 color-red my-3"></p>

            <a
              href="javascript:;"
              type="submit"
              id="js-spin-btn"
              style="display:block;"
              class="form-btn-submit font-weight-900 color-secondary bg-primary text-center text-uppercase"
              onclick="start_game()"
            >
              Click để bắt đầu
            </a>
            <!-- js-spin-btn -->
            <a
              href="javascript:;"
              type="submit"
              id="js-reset-btn"
              style="display:none;"
              class="form-btn-submit font-weight-900 color-secondary bg-primary text-center text-uppercase"
              onclick="Adman.MiniGame.reset()"
            >
              Chơi lại
            </a>
            <!-- js-reset-btn -->
            <div class="player-prize color-white">
              <p class="font-weight-700 mb-1">Danh sách kết quả của bạn</p>
              <ol id="js-reward-list">
                <!-- js-reward-list -->
                <!-- Ajax holder -->
                <i class="color-red"
                  >Quay ngay để nhận những phần quà hấp dẫn</i
                >
              </ol>
            </div>
          </div>
        </div>
        <!-- GAME -->
        <div class="game-spin">
          <div class="vqmm-ct-ct in-wheel spin-roll">
            <div class="vq-ct">
              <!-- CANVAS -->
              <canvas
                id="canvas"
                width="772"
                height="772"
                class="wheel-canvas d-flex w-100"
              >
                <p style="color: white" align="center">
                  Sorry, your browser doesn't support canvas. Please try
                  another.
                </p>
              </canvas>
            </div>
          </div>
        </div>
      </div>

      <!-- GAME PZIRE -->
      <div class="game-prize grid grid--1-cols grid--1-cols-mb pt-4">
        <!-- COL PRIZE INFO -->
        <div class="game-prize-info pt-4">
          <!-- HEADING -->
          <div class="heading-p text-center p-relative">
            <div class="wrapper">
              <div class="title">
                <h2 class="text-center">DANH SÁCH GIẢI THƯỞNG</h2>
              </div>
            </div>
          </div>
          <!-- CONTENT -->
          <div class="content-p">
            <!-- ROW P TOP-->
            <div class="row-p row-p-best grid" id="js-reward-list-top">
              <!-- AJAX HOLDER -->
            </div>
          </div>
        </div>
        <!-- COL PRIZE RECENT -->
        <div class="game-prize-recent pt-4">
          <!-- HEADING -->
          <h2 class="text-center">DANH SÁCH NGƯỜI CHƠI TRÚNG GIẢI GẦN ĐÂY</h2>
          <div id="js-recent-winners">
            <h4>Hãy là người chơi đầu tiên được ghi lên BẢNG VÀNG!</h4>
            <!-- AJAX HOLDER -->
          </div>
        </div>
      </div>
    </div>

    <!-- FOOTER -->
    <div class="footer pt-4">
      <!-- GAME POLICY -->
      <div class="game-policy color-white">
        <h2 class="">THỂ LỆ CHƯƠNG TRÌNH</h2>
        <ol class="list" id="js-game-policy">
          <li>Quý khách cần đăng nhập Thông tin chính xác để quay thưởng.</li>
          <li>Mỗi khách hàng được quay 5 lần và chỉ được chọn 1 phần quà.</li>
          <li>
            Mã giảm giá sử dụng trong vòng 15 ngày kể từ ngày nhận thưởng.
          </li>
          <li>Voucher được phát hành và áp dụng đến khi hết số lượng.</li>
        </ol>
      </div>
    </div>
  </div>
</div>
```

</TabItem>
<TabItem value="css" label="CSS">

```css
*,
*,
::after,
::before {
  padding: 0;
  margin: 0;
  -webkit-box-sizing: inherit;
  box-sizing: inherit;
}
html {
  font-size: 16px;
}
body {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  font-family: Inter, sans-serif;
  color: #000;
  min-width: 1220px;
  word-break: break-word;
  line-height: 1.3;
  font-weight: 400;
  background-size: cover;
  background-attachment: fixed;
}
.container {
  max-width: 1220px;
  width: 100%;
  padding: 0 10px;
  margin: 0 auto;
}
a {
  text-decoration: none;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
}
.font-weight-900 {
  font-weight: 900;
}
.font-weight-800 {
  font-weight: 800;
}
.font-weight-700 {
  font-weight: 700;
}
.font-weight-600 {
  font-weight: 600;
}
.font-weight-500 {
  font-weight: 500;
}
.font-weight-400 {
  font-weight: 400;
}
.font-weight-300 {
  font-weight: 300;
}
.grid {
  display: -ms-grid;
  display: grid;
  gap: 16px;
}
.grid--2-cols {
  -ms-grid-columns: (1fr) [2];
  grid-template-columns: repeat(2, 1fr);
}
.grid--3-cols {
  -ms-grid-columns: (1fr) [3];
  grid-template-columns: repeat(3, 1fr);
}
.grid--4-cols {
  -ms-grid-columns: (1fr) [4];
  grid-template-columns: repeat(4, 1fr);
}
.d-flex {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}
.align-items-center {
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
}
.align-items-start {
  -webkit-box-align: start;
  -ms-flex-align: start;
  align-items: flex-start;
}
.align-items-end {
  -webkit-box-align: end;
  -ms-flex-align: end;
  align-items: flex-end;
}
.align-items-baseline {
  -webkit-box-align: baseline;
  -ms-flex-align: baseline;
  align-items: baseline;
}
.justify-content-center {
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}
.justify-content-between {
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
}
.flex-column {
  -ms-flex-direction: column;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  flex-direction: column;
}
.flex-row {
  -ms-flex-direction: row;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  flex-direction: row;
}
.flex-1 {
  -webkit-box-flex: 1;
  -ms-flex: 1;
  flex: 1;
}
.flex-wrap {
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
}
.p-4 {
  padding: 24px !important;
}
.pt-4,
.py-4 {
  padding-top: 24px !important;
}
.pr-4,
.px-4 {
  padding-right: 24px !important;
}
.pb-4,
.py-4 {
  padding-bottom: 24px !important;
}
.pl-4,
.px-4 {
  padding-left: 24px !important;
}
text-center {
  text-align: center;
}
.blink {
  -webkit-animation: blink 1s steps(1, end) infinite;
  animation: blink 1s steps(1, end) infinite;
}
@-webkit-keyframes blink {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@keyframes blink {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
canvas {
  max-width: 600px;
}
.p-item {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-pack: distribute;
  justify-content: space-around;
}
.form {
  padding: 10px;
  border: 1px solid;
}
.form-input {
  margin: 8px 0;
  width: 100%;
}
.form-btn-submit {
  padding: 8px;
  background: red;
  color: #fff;
  margin: 8px 0;
  text-align: center;
}
```

</TabItem>
</Tabs>
</details>

## Khai báo ID Minigame, Link API Adman và các biến thường dùng

```jsx
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>const GAME_ID ='O4z25JLzP9';</script>
<script id="hura-am-main" src="https://static.gleecdn.com/am/v1/aman.bundle.js?id=EVjpMnXO"></script>
```

```jsx
const SPIN_HOLDER = $("#js-spin-btn");
const RESET_HOLDER = $("#js-reset-btn");
const REWARD_LIST_HOLDER = $("#js-reward-list");
const GAME_NOTIFY = $("#js-game-notify");
```

## Khởi tạo Minigame và các hàm xử lý chung

```jsx
$(function () {
  if (Adman) {
    // Cài đặt game
    Adman.MiniGame.setUp({
      id: GAME_ID,
      handleStatusUpdate, // Hàm xử lý hiển thị các thông tin về: Người đang chơi - Người trúng thưởng - Giải thưởng còn lại - Trạng thái game (đóng hay mở)
      handleNotification, // Hàm xử lý thông báo lỗi tới người dùng
      onSetupComplete, // Hàm xử lý khi quá trình cài đặt đã xong
      onReset, // Hàm xử lý khi Người dùng click vào Reset
      onPlayStart, // Hàm xử lý khi Người dùng click vào Play
      onPlayComplete, // Hàm xử lý khi Hiệu ứng chạy kết thúc (v.d. Khi vòng quay dừng lại)
      handleDisplayWinningPrize, // Hàm xử lý Hiển thị danh sách giải thưởng đã trúng (v.d. Game cho phép quay 5 lần, khách hàng trúng 5 giải, khách hàng khi đó sẽ cần Chọn 1 giải để nhận thưởng )
    });
  }
});
```

## Xử lý hiển thị giao diện

```jsx
// Hàm xử lý hiển thị các thông tin về: Người đang chơi - Người trúng thưởng - Giải thưởng còn lại - Trạng thái game (đóng hay mở)
function handleStatusUpdate(game_status) {
  console.log("handleStatusUpdate", game_status);
  // Hiển thị danh sách người trúng giải gần nhất
  if (recent_winners) buildRecentWinners(recent_winners);

  // Cập nhật số lượng giải thưởng còn lại liên tục
  if (rewards) updateRemainingRewards(rewards);

  // Hiển thị số lượng Người chơi online - đang chơi - đã chơi
  if (users) showUserStat(users);
}

function showUserStat(users) {
  console.log("user_status:", users);
  $(".js-users-status-online").html(users.online);
  $(".js-users-status-played").html(users.played);
  $(".js-users-status-playing").html(users.playing);
}

function updateRemainingRewards(remaining_rewards) {
  console.log("remaining_rewards", remaining_rewards);
  remaining_rewards.forEach((item) => {
    let remaining_reward = item.reserved > 0 ? item.remaining : item.total;
    $(".js-remaining-" + item.id).html(remaining_reward);
  });
}

// Hàm hiển thị danh sách người trúng giải gần nhất
function buildRecentWinners(recent_winners) {
  console.log("recent_winners", recent_winners);
  const showUnixTime = Adman.Util.showUnixTime;
  const row_list = recent_winners.map(function (item, index) {
    return `
      <tr>
        <td>${index + 1}</td>
        <td>${item.email}</td>
        <td>${item.prize}</td>
        <td>${showUnixTime(item.time)}</td>
      </tr>
    `;
  });

  const table_content = `
    <!-- TABLE LIST RECENT PRIZE -->
    <table class="text-14 text-12-mb w-100">
      <tr>
          <th>STT</th>
          <th>Khách hàng</th>
          <th>Giải thưởng</th>
          <th>Thời gian</th>
      </tr>
      ${row_list.join("")}
    </table>
  `;

  $("#js-recent-winners").html(table_content);
}
```

## Xử lý Hiển thị danh sách giải thưởng đã trúng

```jsx
// Hàm xử lý Hiển thị danh sách giải thưởng đã trúng (v.d. Game cho phép quay 5 lần, khách hàng trúng 5 giải, khách hàng khi đó sẽ cần Chọn 1 giải để nhận thưởng )
function handleDisplayWinningPrize(winning_rewards) {
  console.log(winning_rewards);
  const claimed_reward = winning_rewards.some(
    (_reward) => _reward.has_claimed == 1
  );

  function _rewardHtml(reward) {
    let chose_reward = "";
    if (claimed_reward)
      chose_reward = reward.has_claimed == 1 ? "Bạn đã chọn giải này" : "";
    else
      chose_reward =
        reward.title.indexOf("Chúc bạn may mắn lần sau") == 0
          ? ""
          : "Chọn giải này";

    return `
      <li class="item mb-1 ml-4">
        ${reward.title} 
        <i class="js-chose-reward color-red font-weight-700">
          <a href="javascript:;" data-id="${reward.id}" class="js-chose-reward-btn">${chose_reward}</a>
        </i>
      </li>
    `;
  }

  REWARD_LIST_HOLDER.html(
    winning_rewards.map((reward) => _rewardHtml(reward)).join("")
  );
  if (claimed_reward) $(".js-chose-reward-btn").css("pointer-events", "none");

  // Turn off any listener
  REWARD_LIST_HOLDER.off("click");

  // Hàm lắng nghe khi ấn "Nhận giải"
  REWARD_LIST_HOLDER.on("click", function (e) {
    let reward_id = $(e.target).data("id");

    if (reward_id) {
      if (confirm("Bạn chắc chắn muốn chọn giải thưởng này chứ?") == true) {
        Adman.MiniGame.claimReward(reward_id).then(function (res) {
          //console.log('Adman.MiniGame.claimReward', res);
          _checkRewardStatus(res, reward_id);
        });
      }
    }
  });
}
```

## Kiểm tra tình trạng giải thưởng

```jsx
// Hàm kiểm tra tình trạng giải thưởng
function _checkRewardStatus(data, reward_id) {
  let status = data.status;
  let message = data.msg;
  let error = "";

  if (status == "error") {
    if (message == "The reward is out of stock!") {
      error +=
        "- Số lượng giải thưởng đã hết. Vui lòng chọn giải thưởng khác.<br>";
    } else if (message == "Has claimed a reward before") {
      error += "- Có lỗi xảy ra. Bạn đã từng nhận 1 giải thưởng.<br>";
    } else if (
      message ==
      "Email hoặc số di động đã được dùng chọn giải trước đó rồi.<br>"
    ) {
      error += "- Có lỗi xảy ra. Email hoặc số di động đã được trao giải.<br>";
    } else {
      error += message;
    }

    GAME_NOTIFY.html(error);
    $(".js-reward-notify").html(error);
  } else {
    GAME_NOTIFY.html(
      "Giải thưởng bạn chọn đã được gửi vào Email. Vui lòng kiểm tra lại."
    );
    $(".js-reward-notify").html(
      "Giải thưởng bạn chọn đã được gửi vào Email. Vui lòng kiểm tra lại."
    );

    $("#js-reward-list a").each(function () {
      let id = $(this).attr("data-id");

      if (reward_id == id) {
        $(this).css("pointer-events", "none").html("Bạn đã chọn giải này");
      } else {
        $(this).remove();
      }
    });
  }
}
```

## Xử lý khi quá trình cài đặt đã xong

```jsx
// Kiểm tra lượt chơi
function checkSpinLeft(permission) {
  const gameInfo = Adman.MiniGame.getInfo();

  let spinMax = gameInfo.rules.max_retry_per_user;
  let spinUsed = $("#js-reward-list .item").length;
  let spinLeft = spinMax - spinUsed;

  if (permission > 0 && spinLeft > 0)
    $(".js-reward-notify").html(`Bạn còn ${spinLeft} lượt quay.`);

  if (spinLeft == 0) {
    SPIN_HOLDER.remove();
    RESET_HOLDER.remove();
    GAME_NOTIFY.html(`Bạn đã hết lượt quay.`);
  }
}

// Hàm kiểm tra người dùng đã đăng nhập chưa
function checkUserExist(game_info) {
  const user_info = Adman.User.getUserInfo();
  console.log(user_info);

  if (user_info.name || user_info.email || user_info.mobile) {
    checkUserInfo();
  } else {
    const email =
      game_info.rules.require_email_before_play == 1
        ? '<input type="email" placeholder="Email*" id="js-user-email" class="form-input" />'
        : "";
    const name =
      game_info.rules.require_name_before_play == 1
        ? '<input type="text" placeholder="Họ tên*" id="js-user-name" class="form-input" />'
        : "";
    const mobile =
      game_info.rules.require_mobile_before_play == 1
        ? '<input type="text" placeholder="Số điện thoại*" id="js-user-mobile" class="form-input" />'
        : "";

    $("#js-user-info").html(`${email} ${name} ${mobile}`);
  }
}

function checkUserInfo() {
  const user_info = Adman.User.getUserInfo();

  if (user_info && (user_info.name || user_info.email || user_info.mobile)) {
    let user_name = "";

    if (user_info.name && user_info.name != "") {
      user_name = user_info.name;
    } else if (user_info.email && user_info.email != "") {
      user_name = user_info.email;
    } else if (user_info.mobile && user_info.mobile != "") {
      user_name = user_info.mobile.substring(0, 7) + "***";
    }

    $("#js-user-info").html(
      `<p class="color-white pb-2">Xin chào, <i class="font-weight-700">${user_name}</i>.</p>`
    );
  }
}

// Hiển thị Danh sách giải thưởng
function renderRewardList(data, holder) {
  let dataReward = data;
  let product_tpl = "";

  dataReward.forEach(function (item, index) {
    product_tpl += `
      <!-- PRODUCT ITEM -->
      <div class="p-item" data-id="${item.id}">
        <h4 class="p-title">Giải thưởng ${index + 1}</h4>
        <a href="" class="p-img">
          <img src="${item.image}" alt="${item.title}" class="p-pic" />
        </a>
        <h3 class="p-name line-clamp-2 my-2">${item.title}</h3>
        <p class="p-price mb-2">${item.market_value.toLocaleString(3)} VNĐ </p>
        <p class="p-quantity-total">Số lượng <span class="font-weight-700">${
          item.total
        }</span></p>
        <p class="p-quantity-left bg-primary">Còn <span class="ml-1 font-weight-700 js-remaining-${
          item.id
        }">${item.remaining}</span></p>
      </div>
    `;

    $(holder).html(product_tpl);
  });
}

// Hàm xử lý khi quá trình cài đặt đã xong
function onSetupComplete(game_info) {
  console.log(game_info);

  // Kiểm tra lượt quay
  checkSpinLeft(0);

  // Kiểm tra thông tin người dùng, nếu chưa có thì hiển thị form cập nhật thông tin
  checkUserExist(game_info);

  // Tên Vòng quay
  $(".js-minigame-name").html(game_info.title);

  // Thời gian kết thúc
  $(".js-minigame-endtime").html(
    Adman.Util.showUnixTime(game_info.rules.end_time)
  );

  // Render list giải thưởng
  const data_reward = game_info.rewards;
  renderRewardList(data_reward, "#js-reward-list-top");

  // Hiển thị quy định chơi
  GAME_POLICY_HOLDER.html(game_info.description);
}
```

## Xử lý khi chơi Minigame

```jsx
// Hàm xử lý khi Người dùng click vào Reset
function onReset() {
  // Ẩn nút Reset và hiển thị nút Play
  SPIN_HOLDER.css("display", "none");
  RESET_HOLDER.css("display", "none");
  start_game();
}

// Hàm xử lý khi Người dùng click vào Play
function onPlayStart() {
  // Ẩn nút Play để không click vào lần 2
  SPIN_HOLDER.css("display", "none");
  GAME_NOTIFY.html("");
}

// Hàm xử lý khi Hiệu ứng chạy kết thúc (v.d. Khi vòng quay dừng lại)
function onPlayComplete() {
  // Ẩn nút Play và hiển thị nút Reset
  SPIN_HOLDER.css("display", "none");
  RESET_HOLDER.css("display", "block");

  setTimeout(function (params) {
    checkSpinLeft(1);
  }, 100);
}

// Hàm khởi động Vòng quay
function start_game() {
  if (check_field() == false) {
    return false;
  } else {
    let email = $("#js-user-email").val();
    let name = $("#js-user-name").val();
    let mobile = $("#js-user-mobile").val();

    Adman.User.setUserInfo({
      email: email,
      name: name,
      mobile: mobile,
    }).then(function (response) {
      Adman.MiniGame.play();
      checkUserInfo();
      GAME_NOTIFY.html("");
    });
  }
}
```

## Xử lý khác

```jsx
// Kiểm tra form điền thông tin trước khi gửi
function check_field() {
  let error = "";
  const number_regex1 = /^[0]\d{9}$/i;
  const number_regex2 = /^[0]\d{10}$/i;

  let check_name = $("#js-user-name").val();
  if (check_name != undefined) {
    if (check_name.length < 2) error += "- Tên quá ngắn <br>";
  }

  let check_email = $("#js-user-email").val();
  if (check_email != undefined) {
    if (check_email.length < 4) {
      error += "- Bạn chưa nhập email <br>";
    } else if (check_email.length > 4) {
      if (validateEmail(check_email) == false)
        error += "- Email không hợp lệ <br>";
    }
  }

  let check_tel = $("#js-user-mobile").val();
  if (check_tel != undefined) {
    if (
      number_regex1.test(check_tel) == false &&
      number_regex2.test(check_tel) == false
    )
      error += "- Số điện thoại chưa chính xác\n";
  }

  if (error != "") {
    GAME_NOTIFY.html(error);
    return false;
  }
}

// Kiểm tra Email
function validateEmail(sEmail) {
  var filter =
    /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
  if (filter.test(sEmail)) {
    return true;
  } else {
    return false;
  }
}
```
