Example #1
0
func SubscribeGame(c common.WSContext) error {
	base64DecodedId, err := base64.URLEncoding.DecodeString(c.Match()[1])
	if err != nil {
		return err
	}
	s := c.Pack().New(c.Match()[0])
	s.Call = func(i interface{}, op string) error {
		game := i.(*Game)
		members, err := game.Members(c.DB())
		if err != nil {
			return err
		}
		member := members.Get(c.Principal())
		isMember := member != nil
		if !game.Private || isMember {
			state, err := game.ToState(c.DB(), members, member)
			if err != nil {
				return err
			}
			return s.Send(state, op)
		} else if op == gosubs.FetchType {
			return s.Send(GameState{}, op)
		}
		return nil
	}
	return s.Subscribe(&Game{Id: base64DecodedId})
}
Example #2
0
func DeleteMember(c common.WSContext) error {
	return c.Transact(func(c common.WSContext) error {
		decodedId, err := kol.DecodeId(c.Match()[1])
		if err != nil {
			return err
		}
		game := &Game{Id: decodedId}
		if err := c.DB().Get(game); err != nil {
			return fmt.Errorf("Game not found: %v", err)
		}
		if game.State != common.GameStateCreated {
			return fmt.Errorf("%+v already started", game)
		}
		member := Member{}
		if _, err := c.DB().Query().Where(kol.And{kol.Equals{"GameId", decodedId}, kol.Equals{"UserId", kol.Id(c.Principal())}}).First(&member); err != nil {
			return err
		}
		if err := c.DB().Del(&member); err != nil {
			return err
		}
		left, err := game.Members(c.DB())
		if err != nil {
			return err
		}
		if len(left) == 0 {
			if err := c.DB().Del(game); err != nil {
				return err
			}
		}
		return nil
	})
}
Example #3
0
func subscribeOthers(c common.WSContext, filter kol.QFilter, preLimiter func(source Games) (result Games), postLimiter func(source GameStates) (result GameStates)) error {
	if c.Principal() == "" {
		return websocket.JSON.Send(c.Conn(), gosubs.Message{
			Type: gosubs.FetchType,
			Object: &gosubs.Object{
				URI: c.Match()[0],
			},
		})
	}
	s := c.Pack().New(c.Match()[0])
	s.Query = s.DB().Query().Where(filter)
	s.Call = func(i interface{}, op string) error {
		games := i.([]*Game)
		if preLimiter != nil {
			games = ([]*Game)(preLimiter(Games(games)))
		}
		states := GameStates{}
		isMember := false
		me := &user.User{Id: kol.Id(c.Principal())}
		if err := c.DB().Get(me); err != nil {
			return err
		}
		for _, game := range games {
			if !game.Disallows(me) {
				members, err := game.Members(c.DB())
				if err != nil {
					return err
				}
				if disallows, err := members.Disallows(c.DB(), me); err != nil {
					return err
				} else if !disallows {
					isMember = members.Contains(c.Principal())
					if !isMember {
						state, err := game.ToState(c.DB(), members, nil)
						if err != nil {
							return err
						}
						states = append(states, state)
					}
				}
			}
		}
		if op == gosubs.FetchType || len(states) > 0 {
			if postLimiter != nil {
				states = postLimiter(states)
			}
			return s.Send(states, op)
		}
		return nil
	}
	return s.Subscribe(&Game{})
}
Example #4
0
func SubscribeMessages(c common.WSContext) (err error) {
	base64DecodedId, err := base64.URLEncoding.DecodeString(c.Match()[1])
	if err != nil {
		return err
	}
	game := &Game{Id: base64DecodedId}
	if err = c.DB().Get(game); err != nil {
		return
	}
	member, err := game.Member(c.DB(), c.Principal())
	if err != nil && err != kol.NotFound {
		return
	}
	memberId := ""
	if member != nil {
		memberId = member.Id.String()
	}
	s := c.Pack().New(c.Match()[0])
	s.Query = s.DB().Query().Where(kol.Equals{"GameId", base64DecodedId})
	s.Call = func(i interface{}, op string) (err error) {
		messages := i.([]*Message)
		result := Messages{}
		for _, message := range messages {
			if message.Public {
				game := &Game{Id: message.GameId}
				if err = c.DB().Get(game); err != nil {
					return
				}
				var members Members
				if members, err = game.Members(c.DB()); err != nil {
					return
				}
				message.RecipientIds = map[string]bool{}
				for _, memb := range members {
					message.RecipientIds[memb.Id.String()] = true
				}
			}
			if message.Public || message.RecipientIds[memberId] {
				result = append(result, *message)
			}
		}
		if op == gosubs.FetchType || len(result) > 0 {
			sort.Sort(result)
			return s.Send(result, op)
		}
		return
	}
	return s.Subscribe(&Message{})
}
Example #5
0
func SubscribeGamePhase(c common.WSContext) error {
	base64DecodedId, err := base64.URLEncoding.DecodeString(c.Match()[1])
	if err != nil {
		return err
	}
	game := &Game{Id: base64DecodedId}
	if err = c.DB().Get(game); err != nil {
		return err
	}
	phaseOrdinal, err := strconv.Atoi(c.Match()[2])
	if err != nil {
		return err
	}
	members, err := game.Members(c.DB())
	if err != nil {
		return err
	}
	member := members.Get(c.Principal())
	isMember := member != nil
	if !game.Private || isMember {
		state, err := game.ToStateWithPhaseOrdinal(c.DB(), members, member, phaseOrdinal)
		if err != nil {
			return err
		}
		return websocket.JSON.Send(c.Conn(), gosubs.Message{
			Type: gosubs.FetchType,
			Object: &gosubs.Object{
				URI:  c.Match()[0],
				Data: state,
			},
		})
	}
	return nil
}
Example #6
0
func SubscribeMessages(c common.WSContext) (err error) {
	base64DecodedId, err := base64.URLEncoding.DecodeString(c.Match()[1])
	if err != nil {
		return err
	}
	game := &Game{Id: base64DecodedId}
	if err = c.DB().Get(game); err != nil {
		return
	}
	variant, found := common.VariantMap[game.Variant]
	if !found {
		err = fmt.Errorf("Unknown variant for %+v", game)
		return
	}
	member, err := game.Member(c.DB(), c.Principal())
	if err != nil && err != kol.NotFound {
		return
	}
	memberId := ""
	if member != nil {
		memberId = member.Id.String()
	}
	s := c.Pack().New(c.Match()[0])
	s.Query = s.DB().Query().Where(kol.Equals{"GameId", base64DecodedId})
	s.Call = func(i interface{}, op string) (err error) {
		messages := i.([]*Message)
		result := Messages{}
		for _, message := range messages {
			if len(message.RecipientIds) == len(variant.Nations) || message.RecipientIds[memberId] {
				result = append(result, *message)
			}
		}
		if op == gosubs.FetchType || len(result) > 0 {
			sort.Sort(result)
			return s.Send(result, op)
		}
		return
	}
	return s.Subscribe(&Message{})
}
Example #7
0
func SubscribeMine(c common.WSContext) error {
	if c.Principal() == "" {
		return websocket.JSON.Send(c.Conn(), gosubs.Message{
			Type: gosubs.FetchType,
			Object: &gosubs.Object{
				URI: c.Match()[0],
			},
		})
	}
	s := c.Pack().New(c.Match()[0])
	s.Query = s.DB().Query().Where(kol.Equals{"UserId", kol.Id(c.Principal())})
	s.Call = func(i interface{}, op string) (err error) {
		members := i.([]*Member)
		var ep time.Duration
		ep, err = epoch.Get(c.DB())
		if err != nil {
			return
		}
		states := GameStates{}
		for _, member := range members {
			if op == gosubs.DeleteType {
				states = append(states, GameState{
					Game:    &Game{Id: member.GameId},
					Members: []MemberState{MemberState{Member: member}},
				})
			} else {
				game := &Game{Id: member.GameId}
				if err = s.DB().Get(game); err != nil {
					return
				}
				var gameMembers Members
				if gameMembers, err = game.Members(c.DB()); err != nil {
					return
				}
				var state GameState
				if state, err = game.ToState(c.DB(), gameMembers, member); err != nil {
					return
				}
				states = append(states, state)
			}
		}
		if op == gosubs.FetchType || len(states) > 0 {
			states = states.SortAndLimit(func(a, b GameState) bool {
				urgencyA := time.Hour * 24 * 365
				urgencyB := time.Hour * 24 * 365
				switch a.State {
				case common.GameStateStarted:
					_, phase, err := a.Game.Phase(c.DB(), 0)
					if err == nil {
						urgencyA = phase.Deadline - ep
					}
				case common.GameStateCreated:
					urgencyA -= 1
				}
				switch b.State {
				case common.GameStateStarted:
					_, phase, err := b.Game.Phase(c.DB(), 0)
					if err == nil {
						urgencyB = phase.Deadline - ep
					}
				case common.GameStateCreated:
					urgencyB -= 1
				}
				if urgencyA != urgencyB {
					return urgencyA < urgencyB
				}
				return a.CreatedAt.Before(b.CreatedAt)
			}, 1024*16)
			return s.Send(states, op)
		}
		return nil
	}
	return s.Subscribe(&Member{})
}