Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Disassoc tournament game #875

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions api/proto/game_service/game_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,29 @@ message StreakInfoResponse {

message RematchStreakRequest { string original_request_id = 1; }

message DisassociateTournamentGameRequest {
string tournament_id = 1;
string game_id = 2;
}

message AssociateTournamentGameRequest {
string tournament_id = 1;
string game_id = 2;
string division = 3;
int32 round = 4;
}

message Empty {

}

service GameMetadataService {
rpc GetMetadata(GameInfoRequest) returns(GameInfoResponse);
rpc GetGCG(GCGRequest) returns(GCGResponse);
rpc GetGameHistory(GameHistoryRequest) returns(GameHistoryResponse);
rpc GetRecentGames(RecentGamesRequest) returns(GameInfoResponses);
rpc GetRematchStreak(RematchStreakRequest) returns(StreakInfoResponse);

rpc AssociateTournamentGame(AssociateTournamentGameRequest) returns(Empty);
rpc DisassociateTournamentGame(DisassociateTournamentGameRequest) returns (Empty);
}
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,30 @@ export namespace CheckinRequest {
}
}

export class DisassociateClubGameRequest extends jspb.Message {
getTournamentId(): string;
setTournamentId(value: string): void;

getGameId(): string;
setGameId(value: string): void;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): DisassociateClubGameRequest.AsObject;
static toObject(includeInstance: boolean, msg: DisassociateClubGameRequest): DisassociateClubGameRequest.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: DisassociateClubGameRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): DisassociateClubGameRequest;
static deserializeBinaryFromReader(message: DisassociateClubGameRequest, reader: jspb.BinaryReader): DisassociateClubGameRequest;
}

export namespace DisassociateClubGameRequest {
export type AsObject = {
tournamentId: string,
gameId: string,
}
}

export class NewClubSessionRequest extends jspb.Message {
hasDate(): boolean;
clearDate(): void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ goog.object.extend(proto, google_protobuf_timestamp_pb);
goog.exportSymbol('proto.tournament_service.CheckinRequest', null, global);
goog.exportSymbol('proto.tournament_service.ClubSessionResponse', null, global);
goog.exportSymbol('proto.tournament_service.ClubSessionsResponse', null, global);
goog.exportSymbol('proto.tournament_service.DisassociateClubGameRequest', null, global);
goog.exportSymbol('proto.tournament_service.FinishTournamentRequest', null, global);
goog.exportSymbol('proto.tournament_service.GetTournamentMetadataRequest', null, global);
goog.exportSymbol('proto.tournament_service.GetTournamentRequest', null, global);
Expand Down Expand Up @@ -508,6 +509,27 @@ if (goog.DEBUG && !COMPILED) {
*/
proto.tournament_service.CheckinRequest.displayName = 'proto.tournament_service.CheckinRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.tournament_service.DisassociateClubGameRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.tournament_service.DisassociateClubGameRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.tournament_service.DisassociateClubGameRequest.displayName = 'proto.tournament_service.DisassociateClubGameRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
Expand Down Expand Up @@ -5148,6 +5170,166 @@ proto.tournament_service.CheckinRequest.prototype.setId = function(value) {



if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.tournament_service.DisassociateClubGameRequest.prototype.toObject = function(opt_includeInstance) {
return proto.tournament_service.DisassociateClubGameRequest.toObject(opt_includeInstance, this);
};


/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.tournament_service.DisassociateClubGameRequest} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.tournament_service.DisassociateClubGameRequest.toObject = function(includeInstance, msg) {
var f, obj = {
tournamentId: jspb.Message.getFieldWithDefault(msg, 1, ""),
gameId: jspb.Message.getFieldWithDefault(msg, 2, "")
};

if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}


/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.tournament_service.DisassociateClubGameRequest}
*/
proto.tournament_service.DisassociateClubGameRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.tournament_service.DisassociateClubGameRequest;
return proto.tournament_service.DisassociateClubGameRequest.deserializeBinaryFromReader(msg, reader);
};


/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.tournament_service.DisassociateClubGameRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.tournament_service.DisassociateClubGameRequest}
*/
proto.tournament_service.DisassociateClubGameRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setTournamentId(value);
break;
case 2:
var value = /** @type {string} */ (reader.readString());
msg.setGameId(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};


/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.tournament_service.DisassociateClubGameRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.tournament_service.DisassociateClubGameRequest.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};


/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.tournament_service.DisassociateClubGameRequest} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.tournament_service.DisassociateClubGameRequest.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getTournamentId();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
f = message.getGameId();
if (f.length > 0) {
writer.writeString(
2,
f
);
}
};


/**
* optional string tournament_id = 1;
* @return {string}
*/
proto.tournament_service.DisassociateClubGameRequest.prototype.getTournamentId = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};


/**
* @param {string} value
* @return {!proto.tournament_service.DisassociateClubGameRequest} returns this
*/
proto.tournament_service.DisassociateClubGameRequest.prototype.setTournamentId = function(value) {
return jspb.Message.setProto3StringField(this, 1, value);
};


/**
* optional string game_id = 2;
* @return {string}
*/
proto.tournament_service.DisassociateClubGameRequest.prototype.getGameId = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
};


/**
* @param {string} value
* @return {!proto.tournament_service.DisassociateClubGameRequest} returns this
*/
proto.tournament_service.DisassociateClubGameRequest.prototype.setGameId = function(value) {
return jspb.Message.setProto3StringField(this, 2, value);
};





if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
Expand Down
1 change: 1 addition & 0 deletions liwords-ui/src/tournament/actions_panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ export const ActionsPanel = React.memo((props: Props) => {
? undefined
: fetchNext
}
isDirector={isDirector}
/>
</>
);
Expand Down
29 changes: 29 additions & 0 deletions liwords-ui/src/tournament/recent_games.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { Link } from 'react-router-dom';
import moment from 'moment';
import { Button, Table, Tag } from 'antd';
import { RecentGame } from './recent_game';
import { DeleteOutlined } from '@ant-design/icons';

type Props = {
games: Array<RecentGame>;
fetchPrev?: () => void;
fetchNext?: () => void;
isDirector: boolean;
};

type playerLinkProps = {
Expand Down Expand Up @@ -82,6 +84,24 @@ export const RecentTourneyGames = React.memo((props: Props) => {
case 'STANDARD':
endReason = 'Complete';
}
const delbtn = props.isDirector ? (
<Button
size="small"
type="text"
danger
onClick={() => {
if (window.confirm('Are you sure you want to remove this game?')) {
fetch(`/api/tournament/game/${item.game_id}`, {
method: 'DELETE',
}).then(() => {
window.location.reload();
});
}
}}
>
<DeleteOutlined />
</Button>
) : null;

return {
game_id: item.game_id, // used by rowKey
Expand All @@ -90,6 +110,7 @@ export const RecentTourneyGames = React.memo((props: Props) => {
scores,
endReason,
when,
delbtn,
};
})
.filter((item) => item !== null);
Expand Down Expand Up @@ -122,6 +143,14 @@ export const RecentTourneyGames = React.memo((props: Props) => {
key: 'when',
},
];
if (props.isDirector) {
columns.push({
className: 'delbtn',
dataIndex: 'delbtn',
key: 'delbtn',
title: '',
});
}
// TODO: use the normal Ant table pagination when the backend can give us a total
return (
<>
Expand Down
12 changes: 12 additions & 0 deletions pkg/tournament/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,18 @@ func (ts *TournamentService) GetRecentClubSessions(ctx context.Context, req *pb.
return ts.tournamentStore.GetRecentClubSessions(ctx, req.Id, int(req.Count), int(req.Offset))
}

func (ts *TournamentService) DisassociateClubGame(ctx context.Context, req *pb.DisassociateClubGameRequest) (*pb.TournamentResponse, error) {
err := authenticateDirector(ctx, ts, req.TournamentId, false)
if err != nil {
return nil, err
}
err = DisassociateClubGame(ctx, ts.tournamentStore, req.TournamentId, req.GameId)
if err != nil {
return nil, twirp.NewError(twirp.InvalidArgument, err.Error())
}
return &pb.TournamentResponse{}, nil
}

func sessionUser(ctx context.Context, ts *TournamentService) (*entity.User, error) {
sess, err := apiserver.GetSession(ctx)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions pkg/tournament/tournament.go
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,14 @@ func UncheckIn(ctx context.Context, ts TournamentStore, tid string) error {
return errors.New("not implemented")
}

func DisassociateClubGame(ctx context.Context, ts TournamentStore, tid, gid string) error {
t, err := ts.Get(ctx, tid)
if err != nil {
return errors.New("tournament does not exist")
}

}

/*
func CheckIn(ctx context.Context, ts TournamentStore, tid string, playerid string) error {
t, err := ts.Get(ctx, tid)
Expand Down
Loading