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

#15 Feature/15 create gungi game #25

Merged
merged 5 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 8 additions & 0 deletions server/src/domain/events/CreateEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Event } from './Event';

export default interface CreateEvent extends Event {
name: 'CreateEvent';
data: {
gungiId: string;
};
}
45 changes: 43 additions & 2 deletions server/src/frameworks/data-services/GungiRepository.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import IRepository from 'src/usecases/Repository';
import Gungi from 'src/domain/Gungi';
import { GungiData } from 'src/frameworks/data-services/GungiData';
import { GungiData, PlayerData } from 'src/frameworks/data-services/GungiData';
import GungiDao from './dao/GungiDao';
import GungiDataModel from './data-model/GungiDataModel';
import { Injectable } from '@nestjs/common';
import LEVEL from '../../domain/constant/LEVEL';
import { randomUUID } from 'crypto';
import SIDE from '../../domain/constant/SIDE';

export type InitRequest = {
level: LEVEL;
players: { id: string; nickname: string }[];
};

@Injectable()
export class GungiRepository implements IRepository<Gungi> {
export class GungiRepository implements IRepository<Gungi, InitRequest> {
zhihdd marked this conversation as resolved.
Show resolved Hide resolved
constructor(private _dao: GungiDao, private _dataModel: GungiDataModel) {}

async findById(id: string): Promise<Gungi | null> {
Expand All @@ -21,4 +29,37 @@ export class GungiRepository implements IRepository<Gungi> {
const data: GungiData = this._dataModel.toData(gungi);
await this._dao.save(data);
}

create(request: InitRequest): Gungi {
const players = request.players.map<PlayerData>((player, index) => {
return {
id: player.id,
name: player.nickname,
deadArea: {
gomas: [],
},
gomaOki: {
gomas: [],
},
side: index === 0 ? SIDE.WHITE : SIDE.BLACK,
};
});

const initData: GungiData = {
_id: randomUUID(),
level: request.level,
currentTurn: SIDE.WHITE,
turn: {
sente: null,
gote: null,
},
players,
gungiHan: {
han: [],
},
history: [],
};

return this._dataModel.toDomain(initData);
}
}
19 changes: 19 additions & 0 deletions server/src/gateway/controllers/Gungi.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Body, Controller, HttpStatus, Param, Post, Res } from '@nestjs/common';
import CreateUsecase, {
CreateGungiRequest,
} from '../../usecases/service-class/CreateUsecase';
import FurigomaUsecase, {
FurigomaRequest,
} from '../../usecases/service-class/FurigomaUsecase';
Expand All @@ -19,16 +22,32 @@ import ConfigurationUsecase, {
ConfigurationRequest,
} from '../../usecases/service-class/ConfigurationUsecase';
import ConfigurationPresenter from '../presenter/ConfigurationPresenter';
import CreatePresenter from '../presenter/CreatePresenter';

@Controller()
export default class GungiController {
constructor(
private _createUsecase: CreateUsecase,
private _furigomaUsecase: FurigomaUsecase,
private _surrenderUsecase: SurrenderUsecase,
private _arataUsecase: ArataUsecase,
private _configurationUsecase: ConfigurationUsecase,
) {}

@Post('/gungi/create')
async create(
@Body() body: { players: { id: string; nickname: string }[] },
@Res() res,
) {
const input: CreateGungiRequest = {
...body,
};
const presenter = new CreatePresenter();

const response = await this._createUsecase.present(input, presenter);
return res.status(HttpStatus.OK).send(response);
}

@Post('/gungi/:gungiId/furigoma')
async furigoma(
@Param('gungiId') gungiId: string,
Expand Down
17 changes: 17 additions & 0 deletions server/src/gateway/presenter/CreatePresenter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Presenter from '../../usecases/Presenter';
import { Event, findByEventName } from '../../domain/events/Event';

interface CreateGungiView {
url: string;
}

export default class CreatePresenter implements Presenter<CreateGungiView> {
present(events: Event[]): CreateGungiView {
const event = findByEventName(events, 'CreateEvent');
const data = event.data;
const gungiId = data.gungiId;
return {
url: `/gungi/${gungiId}`,
};
}
}
3 changes: 3 additions & 0 deletions server/src/usecases/GungiUsecase.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import FurigomaUsecase from './service-class/FurigomaUsecase';
import ImplEventBus from '../gateway/eventBus/ImplEventBus';
import ArataUsecase from './service-class/ArataUsecase';
import ConfigurationUsecase from './service-class/ConfigurationUsecase';
import CreateUsecase from './service-class/CreateUsecase';

@Module({
imports: [GungiRepositoryModule],
providers: [
CreateUsecase,
SurrenderUsecase,
FurigomaUsecase,
ArataUsecase,
Expand All @@ -19,6 +21,7 @@ import ConfigurationUsecase from './service-class/ConfigurationUsecase';
},
],
exports: [
CreateUsecase,
SurrenderUsecase,
FurigomaUsecase,
ConfigurationUsecase,
Expand Down
4 changes: 3 additions & 1 deletion server/src/usecases/Repository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export default interface IRepository<T> {
export default interface IRepository<T, InitRequest> {
zhihdd marked this conversation as resolved.
Show resolved Hide resolved
findById(id: string): Promise<T | null>;

save(item: T): Promise<void>;

create(request: InitRequest): T;
}
3 changes: 2 additions & 1 deletion server/src/usecases/service-class/ArataUsecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import SIDE from '../../domain/constant/SIDE';
import { Inject, Injectable } from '@nestjs/common';
import Coordinate from '../../domain/Coordinate';
import Usecase from '../Usecase';
import { InitRequest } from '../../frameworks/data-services/GungiRepository';

export interface ArataRequest {
gungiId: string;
Expand All @@ -26,7 +27,7 @@ export interface ArataRequest {
export default class ArataUsecase implements Usecase<ArataRequest> {
constructor(
@Inject('GungiRepository')
private _gungiRepository: IRepository<Gungi>,
private _gungiRepository: IRepository<Gungi, InitRequest>,
@Inject('EventBus')
private _eventBus: EventBus,
) {}
Expand Down
3 changes: 2 additions & 1 deletion server/src/usecases/service-class/ConfigurationUsecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Gungi from '../../domain/Gungi';
import Presenter from '../Presenter';
import { GameState } from '../../domain/constant/GameState';
import Usecase from '../Usecase';
import { InitRequest } from '../../frameworks/data-services/GungiRepository';

export interface ConfigurationRequest {
gungiId: string;
Expand All @@ -17,7 +18,7 @@ export default class ConfigurationUsecase
{
constructor(
@Inject('GungiRepository')
private _gungiRepository: IRepository<Gungi>,
private _gungiRepository: IRepository<Gungi, InitRequest>,
@Inject('EventBus')
private _eventBus: EventBus,
) {}
Expand Down
44 changes: 44 additions & 0 deletions server/src/usecases/service-class/CreateUsecase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Usecase from '../Usecase';
import Presenter from '../Presenter';
import CreateEvent from '../../domain/events/CreateEvent';
import { Inject, Injectable } from '@nestjs/common';
import IRepository from '../Repository';
import Gungi from '../../domain/Gungi';
import EventBus from '../EventBus';
import LEVEL from '../../domain/constant/LEVEL';
import { InitRequest } from '../../frameworks/data-services/GungiRepository';

export type CreateGungiRequest = {
players: { id: string; nickname: string }[];
};

@Injectable()
export default class CreateUsecase implements Usecase<CreateGungiRequest> {
constructor(
@Inject('GungiRepository')
private _gungiRepository: IRepository<Gungi, InitRequest>,
@Inject('EventBus')
private _eventBus: EventBus,
) {}

async present<View>(
request: CreateGungiRequest,
presenter: Presenter<View>,
): Promise<View> {
const initRequest: InitRequest = {
level: LEVEL.BEGINNER,
players: request.players,
};

const gungi = this._gungiRepository.create(initRequest);
await this._gungiRepository.save(gungi);

const event: CreateEvent = {
name: 'CreateEvent',
data: {
gungiId: gungi.id,
},
};
return presenter.present([event]);
}
}
3 changes: 2 additions & 1 deletion server/src/usecases/service-class/FurigomaUsecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Gungi from '../../domain/Gungi';
import { Event } from '../../domain/events/Event';
import Presenter from '../Presenter';
import Usecase from '../Usecase';
import { InitRequest } from '../../frameworks/data-services/GungiRepository';

export type FurigomaRequest = {
gungiId: string;
Expand All @@ -15,7 +16,7 @@ export type FurigomaRequest = {
export default class FurigomaUsecase implements Usecase<FurigomaRequest> {
constructor(
@Inject('GungiRepository')
private _gungiRepository: IRepository<Gungi>,
private _gungiRepository: IRepository<Gungi, InitRequest>,
@Inject('EventBus')
private _eventBus: EventBus,
) {}
Expand Down
3 changes: 2 additions & 1 deletion server/src/usecases/service-class/SurrenderUsecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import IRepository from '../Repository';
import Gungi from '../../domain/Gungi';
import Presenter from '../Presenter';
import Usecase from '../Usecase';
import { InitRequest } from '../../frameworks/data-services/GungiRepository';

export interface SurrenderRequest {
gungiId: string;
Expand All @@ -14,7 +15,7 @@ export interface SurrenderRequest {
export default class SurrenderUsecase implements Usecase<SurrenderRequest> {
constructor(
@Inject('GungiRepository')
private _gungiRepository: IRepository<Gungi>,
private _gungiRepository: IRepository<Gungi, InitRequest>,
@Inject('EventBus')
private _eventBus: EventBus,
) {}
Expand Down
29 changes: 29 additions & 0 deletions server/test/e2e/e2e.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,35 @@ describe('AppController (e2e)', () => {
await app.close();
});

it('/(POST) gungi/create', async () => {
const body = {
players: [
{
id: '6497f6f226b40d440b9a90cc',
nickname: '金城武',
},
{
id: '6498112b26b40d440b9a90ce',
nickname: '重智',
},
],
};

const response = await request(app.getHttpServer())
.post(`/gungi/create`)
.send(body)
.expect(200);

const responseData = response.body;
const url = responseData.url;
const regex = /\/gungi\/(?<gungiId>[^/]+)/;
const {
groups: { gungiId },
} = url.match(regex) || {};

expect(gungiId).toBeDefined();
});

it('/(POST) gungi/:gungiId/surrender', async () => {
const gungiId = randomUUID();
const gungiData: GungiData = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import GOMA from '../../../../src/domain/constant/GOMA';
import SIDE from '../../../../src/domain/constant/SIDE';
import { ERROR_MESSAGE } from '../../../../src/domain/constant/ERROR_MESSAGE';
import Coordinate from '../../../../src/domain/Coordinate';
import Gungi from '../../../../src/domain/Gungi';
import Player from '../../../../src/domain/Player';
import when_arata_at_han from './helper/whenArataTo';

describe('下面沒棋別亂疊', () => {
Expand Down