Skip to content

Commit

Permalink
Merge pull request #462 from hanshino:feature/minigame
Browse files Browse the repository at this point in the history
Refactor docker-compose.yml file
  • Loading branch information
hanshino authored Jan 19, 2024
2 parents 8b4da51 + 73ea089 commit 0dfa165
Show file tree
Hide file tree
Showing 9 changed files with 371 additions and 67 deletions.
2 changes: 1 addition & 1 deletion app/bottender.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {
},
redis: {
port: process.env.REDIS_PORT,
host: "redis",
host: process.env.REDIS_HOST,
password: process.env.REDIS_PASSWORD,
db: 0,
},
Expand Down
5 changes: 4 additions & 1 deletion app/locales/zh_tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@
"add_start_analyze_success": "成功分析開始時間...",
"add_end_now": "未指定結束時間,設定為現在之後一小時...",
"add_end_analyze_success": "成功分析結束時間...",
"admin_now": "正在舉辦的遊戲:\n{{ id }}\n{{ name }}"
"admin_now": "正在舉辦的遊戲:\n{{ id }}\n{{ name }}",
"sic_bo_rolled": "骰出了 {{ dice1 }}、{{ dice2 }}、{{ dice3 }},總和為 {{ sum }}",
"sic_bo_win": "你選擇的是 {{ option }},獲得 {{ chips }} * {{ payout }} = {{ total }} 顆女神石",
"sic_bo_lose": "你選擇的是 {{ option }},失去 {{ chips }} 顆女神石"
},
"trade": {
"no_mention": "請標記要交易的對象",
Expand Down
1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"devDependencies": {
"@types/express": "^4.17.21",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.2",
Expand Down
7 changes: 7 additions & 0 deletions app/server.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
const path = require("path");
if (process.env.NODE_ENV !== "production") {
require("dotenv").config({
path: path.resolve(__dirname, "../.env"),
});
}

const express = require("express");
const rateLimit = require("express-rate-limit");
const { bottender } = require("bottender");
Expand Down
3 changes: 3 additions & 0 deletions app/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const LotteryController = require("./controller/application/LotteryController");
const BullshitController = require("./controller/application/BullshitController");
const SubscribeController = require("./controller/application/SubscribeController");
const ScratchCardController = require("./controller/application/ScratchCardController");
const NumberController = require("./controller/application/NumberController");
const { transfer } = require("./middleware/dcWebhook");
const redis = require("./util/redis");
const traffic = require("./util/traffic");
Expand Down Expand Up @@ -97,6 +98,7 @@ async function HandlePostback(context, { next }) {
() => action === "exchangeScratchCard",
withProps(ScratchCardController.exchange, { payload })
),
route(() => action === "sicBoGuess", withProps(NumberController.postbackDecide, { payload })),
route("*", next),
]);
} catch (e) {
Expand Down Expand Up @@ -134,6 +136,7 @@ async function OrderBased(context, { next }) {
...BullshitController.router,
...SubscribeController.router,
...ScratchCardController.router,
...NumberController.router,
text(/^[/#.](使用說明|help)$/, welcome),
text(/^[/#.]抽(\*(?<times>\d+))?(\s*(?<tag>[\s\S]+))?$/, gacha.play),
text(/^[/#.]消耗抽(\*(?<times>\d+))?(\s*(?<tag>[\s\S]+))?$/, (context, props) =>
Expand Down
142 changes: 142 additions & 0 deletions app/src/controller/application/NumberController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
const { text } = require("bottender/router");
const { sample, get } = require("lodash");
const NumberTemplate = require("../../templates/application/Number");
const i18n = require("../../util/i18n");

exports.router = [
text(/^[.#/](猜大小) (?<chips>\d{1,7})$/, privateSicBoHolding),
text(/^[.#/](猜) (?<option>\S+) (?<chips>\d{1,7})$/, userDecide),
];

const optionMapping = {
big: ["大"],
small: ["小"],
double: ["兩顆"],
triple: ["三顆"],
};

exports.postbackDecide = async (context, { payload }) => {
const { option, chips } = payload;
await userDecide(context, { match: { groups: { option: optionMapping[option][0], chips } } });
};

/**
* Searches for an option in the optionMapping object and returns the corresponding key.
* @param {string} option - The option to search for.
* @returns {string} - The corresponding key for the option, or null if not found.
*/
function searchOption(option) {
return Object.keys(optionMapping).find(key => optionMapping[key].includes(option));
}

/**
* Handles the user's decision in a game.
* @param {Object} context - The context object.
* @param {Object} props - The props object containing the user's decision.
* @param {string} props.option - The user's selected option.
* @param {string} props.chips - The amount of chips the user has bet.
* @returns {Promise<void>} - A promise that resolves when the function is done.
*/
async function userDecide(context, props) {
const { option, chips } = props.match.groups;
const quoteToken = get(context, "event.message.quoteToken");

const key = searchOption(option);
if (!key) {
await context.replyText("請選擇正確的選項,例如:大、小、雙、三", { quoteToken });
return;
}

if (!chips) {
await context.replyText("請先下注", { quoteToken });
return;
}

const dice = rollDice(3);
const sum = dice.reduce((acc, cur) => acc + cur, 0);
const isSmall = sum >= 3 && sum <= 10;
const isBig = sum >= 11 && sum <= 18;
const isDouble = dice[0] === dice[1] || dice[0] === dice[2] || dice[1] === dice[2];
const isTriple = dice[0] === dice[1] && dice[0] === dice[2];

let result = false;
switch (key) {
case "big":
result = isBig;
break;
case "small":
result = isSmall;
break;
case "double":
result = isDouble;
break;
case "triple":
result = isTriple;
break;
}

let payout = 1;
if (result) {
switch (key) {
case "big":
case "small":
payout += 1;
break;
case "double":
payout += 8;
break;
case "triple":
payout += 180;
break;
}
}

const messages = [
"[公測] 不管輸贏都不會扣除籌碼,也不會贏得籌碼,僅供測試",
i18n.__("message.gamble.sic_bo_rolled", {
dice1: dice[0],
dice2: dice[1],
dice3: dice[2],
sum,
}),
];

const total = parseInt(chips) * payout;
if (result) {
messages.push(i18n.__("message.gamble.sic_bo_win", { option, chips, payout, total }));
} else {
messages.push(i18n.__("message.gamble.sic_bo_lose", { option, chips }));
}

const replyOption = {};
if (quoteToken) {
replyOption.quoteToken = quoteToken;
}
await context.replyText(messages.join("\n"), replyOption);
}

/**
* Handles the private Sic Bo holding logic.
*
* @param {import("bottender").LineContext} context - The context object.
* @param {import("bottender").Props} props - The props object.
* @returns {Promise<void>} - A promise that resolves when the logic is handled.
*/
async function privateSicBoHolding(context, props) {
const { chips } = props.match.groups;
await context.replyFlex("猜大小", NumberTemplate.generatePanel({ chips }));
}

/**
* Rolls a dice a specified number of times.
* @param {number} times - The number of times to roll the dice.
* @returns {number[]} - An array containing the results of each dice roll.
*/
function rollDice(times) {
const dice = [1, 2, 3, 4, 5, 6];
const result = [];
for (let i = 0; i < times; i++) {
result.push(sample(dice));
}
return result;
}
Loading

0 comments on commit 0dfa165

Please sign in to comment.