iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Software Development

徵坦補! 新手可! Open-Match 配對框架系列 第 7

Day7 配對條件範例 (角色,人數上限)

今天我們要自己假訂一個配對情境,來做一個比官方稍微複雜一點點的 Demo,並且透過這個模擬情境的實踐,來熟悉 Open-Match 在實作上須滿足的接口與函式用法。

情境

隨機產生兩個地區、兩種職業與不同等級條件的配對請求,並且將兩個不同職業才能配對的邏輯,加入我們的配對邏輯中

部署範例

  • 移除官方 demo (若無部署可以跳過)

    kubectl delete namespaces open-match-demo
    
  • 下載本次範例用 yaml

    open-match/open-match-role-location-demo.yml at example-a.2 · WeiWeiWesley/open-match

    主要基於官方 yaml 替換掉 demo 與 mmf 的 images 為本次範例所需要的情境

    - name: om-demo
            image: "weiweiwesley/open-match:example-a.2"
    
    ...
    
    - name: om-function
            image: "weiweiwesley/mmf_role_location:diff_role.2"
    
    ...
    
  • 部署

    
    kubectl create namespace open-match-demo
    
    kubectl apply -n open-match-demo -f open-match-role-location-demo.yml
    

    https://i.imgur.com/HConrwO.png

主要異動

Client

以時間亂數產生不同的配對請求,分別將不同型態的條件放到 StringArgsDoubleArgs 內。實務上這些資料,更可能是由撈取使用者資料庫獲得。

var ticketId string
	{

		ticket := &pb.Ticket{}

		//隨機產生不同條件
		//兩個地區
		//兩種職業
		//等級 0~30
		switch time.Now().Unix() % 4 {
		case 0:
			ticket.SearchFields = &pb.SearchFields{
				StringArgs: map[string]string{
					"location": "Asia/Taiwan",
					"role":     "knight",
				},
				DoubleArgs: map[string]float64{
					"level": float64(rand.Int31n(30)),
				},
			}
		case 1:
			ticket.SearchFields = &pb.SearchFields{
				StringArgs: map[string]string{
					"location": "Asia/Taiwan",
					"role":     "archer",
				},
				DoubleArgs: map[string]float64{
					"level": float64(rand.Int31n(30)),
				},
			}
		case 2:
			ticket.SearchFields = &pb.SearchFields{
				StringArgs: map[string]string{
					"location": "Asia/Japan",
					"role":     "knight",
				},
				DoubleArgs: map[string]float64{
					"level": float64(rand.Int31n(30)),
				},
			}
		case 3:
			ticket.SearchFields = &pb.SearchFields{
				StringArgs: map[string]string{
					"location": "Asia/Japan",
					"role":     "archer",
				},
				DoubleArgs: map[string]float64{
					"level": float64(rand.Int31n(30)),
				},
			}
		}

		req := &pb.CreateTicketRequest{Ticket: ticket}

		s.Status = fmt.Sprintf("Create ticket role: %s location: %s", ticket.SearchFields.StringArgs["role"], ticket.SearchFields.StringArgs["location"])
		update(s)
		time.Sleep(time.Second)

		resp, err := fe.CreateTicket(ctx, req)
		if err != nil {
			panic(err)
		}
		ticketId = resp.Id
	}

MMF

Match Function 是我們實作配對邏輯的部份,這邊可以看到我們能針對 ticket.SearchFields 的內容,對請求是否進行同場配對做篩選 ,previousRole 在記錄下玩家角色後,會拒絕配對相同角色的玩家。

func makeMatches(poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
	tickets := map[string]*pb.Ticket{}
	for _, pool := range poolTickets {
		for _, ticket := range pool {
			tickets[ticket.GetId()] = ticket
		}
	}

	var matches []*pb.Match

	t := time.Now().Format("2006-01-02T15:04:05.00")

	thisMatch := make([]*pb.Ticket, 0, 2)
	matchNum := 0

	previousRole := ""
	for _, ticket := range tickets {
		log.Println("pairing:", ticket.Id, ticket.SearchFields.StringArgs["role"])

		//若同職業則會跳過此次配對
		if previousRole != ticket.SearchFields.StringArgs["role"] {
			thisMatch = append(thisMatch, ticket)
			previousRole = ticket.SearchFields.StringArgs["role"]
		}

		if len(thisMatch) >= 2 {
			matches = append(matches, &pb.Match{
				MatchId:       fmt.Sprintf("profile-%s-time-%s-num-%d", matchName, t, matchNum),
				MatchProfile:  matchName,
				MatchFunction: matchName,
				Tickets:       thisMatch,
			})

			log.Println("pairing success", thisMatch[0].SearchFields.StringArgs["role"], thisMatch[1].SearchFields.StringArgs["role"])

			previousRole = ""
			thisMatch = make([]*pb.Ticket, 0, 2)
			matchNum++
		}
	}

	return matches, nil
}

快速抽換配對條件

基於 Open-Match 框架已經將 MMF 獨立為一個服務實體啟動,我們可以利用 kubernetes rolling update 的特性,動態的抽換線上的 MMF。我們可以試著將本篇範例的 MMF,再度更換為官方demo 的映像黨,並重新 apply 上便可以再度恢復成任意兩人即可配對成功。

更換 MMF

- name: om-function
        image: "gcr.io/open-match-public-images/openmatch-mmf-go-soloduel:1.2.0"

Just apply again

kubectl apply -n open-match-demo -f open-match-role-location-demo.yml

本日心得

單純利用 tickets 的資料進行條件篩選,這在 client or MMF 實作上都是非常簡易的,我們可以依照遊戲的各種特性,以及玩家遊玩過程與實體所產生的資料來產生不同的配對條件。本次範例中僅用兩種不同角色即可配對,而那些沒有配對到的玩家,會等到出現不同角色時才配對,這可能會發生一個尷尬的情況:如果大家都是選擇相同角色時,所有人都會卡在配對等待中的狀態。為了避免等待時間過長,之後一點的篇幅會再用一個範例來教大家如何釋放 tickets。

此外由於本次範例是想沿用官方 demo 介面,直接從官方demo fork 出來異動,會有一些 golang 相依上的一些問題,這與 Open-Match 本身的使用上沒有直接相關,所以為了讓範例順利已將 images 放在 dockerHub 上。


上一篇
Day6 Director & Match Function
下一篇
Day8 Swagger UI & Open Match APIs
系列文
徵坦補! 新手可! Open-Match 配對框架30

尚未有邦友留言

立即登入留言