Skip to content

Commit

Permalink
完成命運
Browse files Browse the repository at this point in the history
  • Loading branch information
maxzh1999tw committed Aug 30, 2022
1 parent 07ba8c7 commit b026098
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 4 deletions.
2 changes: 1 addition & 1 deletion app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from linebot import (LineBotApi, WebhookParser)
from google.cloud import firestore
from controller import *
from controllers import *

from services import GameService

Expand Down
115 changes: 115 additions & 0 deletions card/cardServices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from ast import Lambda
import random
from google.cloud import firestore
from google.cloud.firestore import Client
from card.cardViews import CardViewFactory

from models import GameLog, GameLogAction
from views import ViewFactory


class BaseCardService:
def __init__(self, db: Client, fieldName: str, cardDict: dict):
self._db = db
self._collection = self._db.collection("Game")
self.fieldName = fieldName
self.cardDict = cardDict

def draw(self, gameId: str) -> Lambda:
isNewDeck = False
doc = self._collection.document(gameId)
deck = doc.get().get(self.fieldName)
if len(deck) == 0:
deck = self.createNewDeck()
isNewDeck = True
card = random.choice(deck)
if isNewDeck:
deck.remove(card)
doc.update({
self.fieldName: deck
})
else:
doc.update({
self.fieldName: firestore.ArrayRemove([card])
})
return self.cardDict[card][1]

def createNewDeck(self) -> list:
return list(self.cardDict.keys())

def excuteCard(self, card, event, controller, gameId, params=None):
self.cardDict[card][0](event, controller, gameId, params)


class DestinyService(BaseCardService):
def __init__(self, db: Client):
cardDict = {
"擊落戰鬥機": (self.shootDownFighter, lambda argument : CardViewFactory.shootDownFighter(argument)),
"繳學費": (self.payTuition, lambda argument : CardViewFactory.payTuition(argument)),
"外星人俘虜": (None, lambda argument : CardViewFactory.capturedByAliens(argument)),
"牢底坐穿": (None, lambda argument : CardViewFactory.goToJail(argument)),
}
super().__init__(db, "DestinyCards", cardDict)

def shootDownFighter(self, event, controller, gameId: str, params):
userId = event.source.user_id
amount = 2000
controller.userService.addBalance(userId, amount)
controller.gameService.AddGameLog(gameId, GameLog(
f"{controller.getUserName(userId)} 擊落戰鬥機,得到了 ${amount}", GameLogAction.Earn, amount))
controller.recordAndReply(event, ViewFactory.OperateSuccess(
controller.getConsoleArgument(gameId, userId), f"操作成功~\n您領取了 ${amount}"))

def payTuition(self, event, controller, gameId: str, params):
userId = event.source.user_id
amount = 600
controller.userService.addBalance(userId, amount * -1)
controller.gameService.AddGameLog(gameId, GameLog(
f"{controller.getUserName(userId)} 繳學費,失去了 ${amount}", GameLogAction.Pay, amount))
controller.recordAndReply(event, ViewFactory.OperateSuccess(
controller.getConsoleArgument(gameId, userId), f"操作成功~\n您繳納了 ${amount}"))


class ChanceService(BaseCardService):
def __init__(self, db: Client):
cardDict = {
"股票當沖": (self.stockHit, None),
"豪華坐駕": (None, None),
"都更協調會": (None, None),
"有關係沒關係": (None, None),
}
super().__init__(db, "ChanceCards", cardDict)

def stockHit(self, event, controller, gameId: str, params):
userId = event.source.user_id
resultType = GameLogAction.Pay
if params["dice"] == 1:
resultType = GameLogAction.Earn
amount = 1000
elif params["dice"] == 2:
amount = 200
elif params["dice"] == 3:
amount = 300
elif params["dice"] == 4:
resultType = GameLogAction.Earn
amount = 400
elif params["dice"] == 5:
amount = 500
elif params["dice"] == 6:
amount = 600

controller.userService.addBalance(
userId, amount if resultType == GameLogAction.Earn else amount * -1)
text = "獲得" if resultType == GameLogAction.Earn else "失去"
controller.gameService.AddGameLog(gameId, GameLog(
f"{controller.getUserName(userId)} 玩股票當沖,{text}了 ${amount}", resultType, amount))

if params["times"] < 3:
pass
else:
if resultType == GameLogAction.Pay:
controller.recordAndReply(event, CardViewFactory.stockHitResultContinuable(
controller.getConsoleArgument(gameId, userId), f"當沖失敗...您失去了 ${amount}", params["times"] + 1))
else:
controller.recordAndReply(event, CardViewFactory.stockHitResultEnd(
controller.getConsoleArgument(gameId, userId), f"當沖賺錢!!您獲得了 ${amount}"))
178 changes: 178 additions & 0 deletions card/cardViews.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import json
import uuid
from linebot.models import *

from views import *


class CardViewFactory(ViewFactory):
def shootDownFighter(argument: ConsoleArgument):
message = CardViewFactory._cardTemplate(
argument,
"https://thumbs.dreamstime.com/b/bomber-plane-drops-bomb-sketch-engraving-vector-illustration-scratch-board-style-imitation-hand-drawn-image-bomber-plane-drops-159425073.jpg",
"命運",
"擊落戰鬥機",
"擊落戰鬥機,得 $2000")

footer = '''{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "button",
"style": "primary",
"action": {
"type": "postback",
"label": "領取獎勵",
"data": "@data"
}
}
]
}'''

id = str(uuid.uuid4())
footer = footer.replace("@data", PostbackData(PostbackType.Destiny,
id, {"name": "擊落戰鬥機"}).toFormatedJSON())
message["footer"] = json.loads(footer, strict=False)
return View(id, FlexSendMessage(alt_text="[命運] 擊落戰鬥機", contents=message))

def payTuition(argument: ConsoleArgument):
message = CardViewFactory._cardTemplate(
argument,
"https://thumbs.dreamstime.com/b/bomber-plane-drops-bomb-sketch-engraving-vector-illustration-scratch-board-style-imitation-hand-drawn-image-bomber-plane-drops-159425073.jpg",
"命運",
"繳學費",
"繳學費,失去 $800")

footer = '''{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "button",
"style": "primary",
"action": {
"type": "postback",
"label": "繳錢",
"data": "@data"
}
}
]
}'''

id = str(uuid.uuid4())
footer = footer.replace("@data", PostbackData(PostbackType.Destiny,
id, {"name": "繳學費"}).toFormatedJSON())
message["footer"] = json.loads(footer, strict=False)
return View(id, FlexSendMessage(alt_text="[命運] 繳學費", contents=message))

def capturedByAliens(argument: ConsoleArgument):
message = CardViewFactory._cardTemplate(
argument,
"https://thumbs.dreamstime.com/b/bomber-plane-drops-bomb-sketch-engraving-vector-illustration-scratch-board-style-imitation-hand-drawn-image-bomber-plane-drops-159425073.jpg",
"命運",
"外星人俘虜",
"被外星人俘虜,暫停行動一回合(可以收過路費)")

id = str(uuid.uuid4())
return View(id, FlexSendMessage(alt_text="[命運] 外星人俘虜", contents=message))

def goToJail(argument: ConsoleArgument):
message = CardViewFactory._cardTemplate(
argument,
"https://thumbs.dreamstime.com/b/bomber-plane-drops-bomb-sketch-engraving-vector-illustration-scratch-board-style-imitation-hand-drawn-image-bomber-plane-drops-159425073.jpg",
"命運",
"牢底坐穿",
"立刻去坐牢")

id = str(uuid.uuid4())
return View(id, FlexSendMessage(alt_text="[命運] 牢底坐穿", contents=message))

def stockHit(argument: ConsoleArgument):
pass

def stockHitResultContinuable(argument: ConsoleArgument, text: str, times: int):
pass

def stockHitResultEnd(argument: ConsoleArgument, text: str):
pass

def _cardTemplate(argument: ConsoleArgument, imgUrl: str, typeName: str, title: str, content: str):
template = '''{
"type": "bubble",
"hero": {
"type": "image",
"url": "@ImgUrl",
"size": "full",
"aspectRatio": "20:13",
"aspectMode": "cover"
},
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "@TypeName",
"size": "md",
"margin": "none",
"align": "center",
"gravity": "center"
}
],
"backgroundColor": "#b3f2e5",
"cornerRadius": "xl",
"paddingAll": "xs"
}
],
"cornerRadius": "lg",
"justifyContent": "center",
"flex": 1
},
{
"type": "text",
"text": "@Title",
"weight": "bold",
"size": "xl",
"flex": 4
}
],
"spacing": "md",
"alignItems": "center",
"justifyContent": "center"
},
{
"type": "box",
"layout": "vertical",
"margin": "lg",
"spacing": "sm",
"contents": [
{
"type": "text",
"text": "@Content",
"wrap": true
}
]
}
]
}
}'''
template = template.replace("@ImgUrl", imgUrl)
template = template.replace("@TypeName", typeName)
template = template.replace("@Title", title)
template = template.replace("@Content", content)
message = json.loads(template, strict=False)
message["header"] = ViewFactory._getGameHeader(argument)
return message
17 changes: 16 additions & 1 deletion controller.py → controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
from linebot import LineBotApi
from linebot.models import *
from google.cloud.firestore import Client
from card.cardServices import ChanceService, DestinyService
from models import *

from services import GameService, UserService
from view import ConsoleArgument, View, ViewFactory
from views import ConsoleArgument, View, ViewFactory


class BaseController:
def __init__(self, lineBotApi: LineBotApi, db: Client, gameService=None, userService=None):
self._db = db
self.lineBotApi = lineBotApi
self.gameService = GameService(
db) if gameService == None else gameService
Expand Down Expand Up @@ -76,6 +78,7 @@ def handleEvent(self, event, gameId: str):

try:
if isinstance(event, PostbackEvent):
print(event.postback.data)
data = PostbackData.parse(event.postback.data)
if data.type == PostbackType.LeaveConfirm:
self.recordAndReply(
Expand Down Expand Up @@ -111,6 +114,18 @@ def handleEvent(self, event, gameId: str):
self.recordAndReply(event, ViewFactory.askTransferAmount(self.getUserName(data.params)))
else:
self.recordAndReply(event, ViewFactory.buttonExpired())
elif data.type == PostbackType.Chance:
if data.params == None:
cardService = ChanceService(self._db)
viewFunc = cardService.draw(gameId)
self.recordAndReply(event, viewFunc(self.getConsoleArgument(gameId, userId)))
elif data.type == PostbackType.Destiny:
cardService = DestinyService(self._db)
if data.params == None:
cardViewFunc = cardService.draw(gameId)
self.recordAndReply(event, cardViewFunc(self.getConsoleArgument(gameId, userId)))
else:
cardService.excuteCard(data.params["name"], event, self, gameId)
return

userContext = self.userService.getContext(userId)
Expand Down
4 changes: 3 additions & 1 deletion services.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def createGame(self, *memberIds: str):
"UpdateTime": datetime.now(),
"Members": memberIds,
"GameLogs": [],
"DestinyCards": [],
"ChanceCards":[]
})
return gameId

Expand Down Expand Up @@ -126,4 +128,4 @@ def setContext(self, userId: str, context: UserContext):
def addBalance(self, userId: str, amount: int):
self._collection.document(userId).update({
"Balance": firestore.Increment(amount)
})
})
1 change: 0 additions & 1 deletion view.py → views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from datetime import datetime
import json
import string
import uuid
from linebot.models import *

Expand Down

0 comments on commit b026098

Please sign in to comment.