✌️
This commit is contained in:
		
							parent
							
								
									f838b482bf
								
							
						
					
					
						commit
						98f09ad16c
					
				
					 3 changed files with 253 additions and 55 deletions
				
			
		| 
						 | 
				
			
			@ -33,6 +33,8 @@ export interface IGame {
 | 
			
		|||
		can_put_everywhere: boolean;
 | 
			
		||||
		looped_board: boolean;
 | 
			
		||||
	};
 | 
			
		||||
	form1: any;
 | 
			
		||||
	form2: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,21 @@ export default function(request: websocket.request, connection: websocket.connec
 | 
			
		|||
				updateSettings(msg.settings);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case 'init-form':
 | 
			
		||||
				if (msg.body == null) return;
 | 
			
		||||
				initForm(msg.body);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case 'update-form':
 | 
			
		||||
				if (msg.id == null || msg.value === undefined) return;
 | 
			
		||||
				updateForm(msg.id, msg.value);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case 'message':
 | 
			
		||||
				if (msg.body == null) return;
 | 
			
		||||
				message(msg.body);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case 'set':
 | 
			
		||||
				if (msg.pos == null) return;
 | 
			
		||||
				set(msg.pos);
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +70,67 @@ export default function(request: websocket.request, connection: websocket.connec
 | 
			
		|||
		publishOthelloGameStream(gameId, 'update-settings', settings);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function initForm(form) {
 | 
			
		||||
		const game = await Game.findOne({ _id: gameId });
 | 
			
		||||
 | 
			
		||||
		if (game.is_started) return;
 | 
			
		||||
		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
 | 
			
		||||
 | 
			
		||||
		const set = game.user1_id.equals(user._id) ? {
 | 
			
		||||
			form1: form
 | 
			
		||||
		} : {
 | 
			
		||||
			form2: form
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		await Game.update({ _id: gameId }, {
 | 
			
		||||
			$set: set
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		publishOthelloGameStream(gameId, 'init-form', {
 | 
			
		||||
			user_id: user._id,
 | 
			
		||||
			form
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function updateForm(id, value) {
 | 
			
		||||
		const game = await Game.findOne({ _id: gameId });
 | 
			
		||||
 | 
			
		||||
		if (game.is_started) return;
 | 
			
		||||
		if (!game.user1_id.equals(user._id) && !game.user2_id.equals(user._id)) return;
 | 
			
		||||
 | 
			
		||||
		const form = game.user1_id.equals(user._id) ? game.form2 : game.form1;
 | 
			
		||||
 | 
			
		||||
		const item = form.find(i => i.id == id);
 | 
			
		||||
 | 
			
		||||
		if (item == null) return;
 | 
			
		||||
 | 
			
		||||
		item.value = value;
 | 
			
		||||
 | 
			
		||||
		const set = game.user1_id.equals(user._id) ? {
 | 
			
		||||
			form2: form
 | 
			
		||||
		} : {
 | 
			
		||||
			form1: form
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		await Game.update({ _id: gameId }, {
 | 
			
		||||
			$set: set
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		publishOthelloGameStream(gameId, 'update-form', {
 | 
			
		||||
			user_id: user._id,
 | 
			
		||||
			id,
 | 
			
		||||
			value
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function message(message) {
 | 
			
		||||
		message.id = Math.random();
 | 
			
		||||
		publishOthelloGameStream(gameId, 'message', {
 | 
			
		||||
			user_id: user._id,
 | 
			
		||||
			message
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function accept(accept: boolean) {
 | 
			
		||||
		const game = await Game.findOne({ _id: gameId });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,9 +2,12 @@
 | 
			
		|||
<div class="root">
 | 
			
		||||
	<header><b>{{ game.user1.name }}</b> vs <b>{{ game.user2.name }}</b></header>
 | 
			
		||||
 | 
			
		||||
	<div>
 | 
			
		||||
		<p>ゲームの設定</p>
 | 
			
		||||
 | 
			
		||||
	<el-select class="map" v-model="mapName" placeholder="マップを選択" @change="onMapChange">
 | 
			
		||||
		<el-card class="map">
 | 
			
		||||
			<div slot="header">
 | 
			
		||||
				<el-select :class="$style.mapSelect" v-model="mapName" placeholder="マップを選択" @change="onMapChange">
 | 
			
		||||
					<el-option label="ランダム" :value="null"/>
 | 
			
		||||
					<el-option-group v-for="c in mapCategories" :key="c" :label="c">
 | 
			
		||||
						<el-option v-for="m in maps" v-if="m.category == c" :key="m.name" :label="m.name" :value="m.name">
 | 
			
		||||
| 
						 | 
				
			
			@ -13,8 +16,8 @@
 | 
			
		|||
						</el-option>
 | 
			
		||||
					</el-option-group>
 | 
			
		||||
				</el-select>
 | 
			
		||||
 | 
			
		||||
	<div class="board" v-if="game.settings.map != null" :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }">
 | 
			
		||||
			</div>
 | 
			
		||||
			<div :class="$style.board" v-if="game.settings.map != null" :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }">
 | 
			
		||||
				<div v-for="(x, i) in game.settings.map.join('')"
 | 
			
		||||
					:class="{ none: x == ' ' }"
 | 
			
		||||
					@click="onPixelClick(i, x)"
 | 
			
		||||
| 
						 | 
				
			
			@ -23,16 +26,53 @@
 | 
			
		|||
					<template v-if="x == 'w'">%fa:circle R%</template>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</el-card>
 | 
			
		||||
 | 
			
		||||
	<div class="rules">
 | 
			
		||||
		<mk-switch v-model="game.settings.is_llotheo" @change="updateSettings" text="石の少ない方が勝ち(ロセオ)"/>
 | 
			
		||||
		<mk-switch v-model="game.settings.looped_board" @change="updateSettings" text="ループマップ"/>
 | 
			
		||||
		<mk-switch v-model="game.settings.can_put_everywhere" @change="updateSettings" text="どこでも置けるモード"/>
 | 
			
		||||
		<div>
 | 
			
		||||
		<el-card class="bw">
 | 
			
		||||
			<div slot="header">
 | 
			
		||||
				<span>先手/後手</span>
 | 
			
		||||
			</div>
 | 
			
		||||
			<el-radio v-model="game.settings.bw" label="random" @change="updateSettings">ランダム</el-radio>
 | 
			
		||||
			<el-radio v-model="game.settings.bw" :label="1" @change="updateSettings">{{ game.user1.name }}が黒</el-radio>
 | 
			
		||||
			<el-radio v-model="game.settings.bw" :label="2" @change="updateSettings">{{ game.user2.name }}が黒</el-radio>
 | 
			
		||||
		</el-card>
 | 
			
		||||
 | 
			
		||||
		<el-card class="rules">
 | 
			
		||||
			<div slot="header">
 | 
			
		||||
				<span>ルール</span>
 | 
			
		||||
			</div>
 | 
			
		||||
			<mk-switch v-model="game.settings.is_llotheo" @change="updateSettings" text="石の少ない方が勝ち(ロセオ)"/>
 | 
			
		||||
			<mk-switch v-model="game.settings.looped_board" @change="updateSettings" text="ループマップ"/>
 | 
			
		||||
			<mk-switch v-model="game.settings.can_put_everywhere" @change="updateSettings" text="どこでも置けるモード"/>
 | 
			
		||||
		</el-card>
 | 
			
		||||
 | 
			
		||||
		<el-card class="bot-form" v-if="form">
 | 
			
		||||
			<div slot="header">
 | 
			
		||||
				<span>Botの設定</span>
 | 
			
		||||
			</div>
 | 
			
		||||
			<el-alert v-for="message in messages"
 | 
			
		||||
				:title="message.text"
 | 
			
		||||
				:type="message.type"
 | 
			
		||||
				:key="message.id"
 | 
			
		||||
			/>
 | 
			
		||||
			<template v-for="item in form">
 | 
			
		||||
				<mk-switch v-if="item.type == 'button'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm($event, item)">{{ item.desc || '' }}</mk-switch>
 | 
			
		||||
 | 
			
		||||
				<el-card v-if="item.type == 'radio'" :key="item.id">
 | 
			
		||||
					<div slot="header">
 | 
			
		||||
						<span>{{ item.label }}</span>
 | 
			
		||||
					</div>
 | 
			
		||||
					<el-radio v-for="(r, i) in item.items" :key="item.id + ':' + i" v-model="item.value" :label="r.value" @change="onChangeForm($event, item)">{{ r.label }}</el-radio>
 | 
			
		||||
				</el-card>
 | 
			
		||||
 | 
			
		||||
				<el-card v-if="item.type == 'textbox'" :key="item.id">
 | 
			
		||||
					<div slot="header">
 | 
			
		||||
						<span>{{ item.label }}</span>
 | 
			
		||||
					</div>
 | 
			
		||||
					<el-input v-model="item.value" @change="onChangeForm($event, item)"/>
 | 
			
		||||
				</el-card>
 | 
			
		||||
			</template>
 | 
			
		||||
		</el-card>
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
	<footer>
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +104,9 @@ export default Vue.extend({
 | 
			
		|||
			o: null,
 | 
			
		||||
			isLlotheo: false,
 | 
			
		||||
			mapName: maps.eighteight.name,
 | 
			
		||||
			maps: maps
 | 
			
		||||
			maps: maps,
 | 
			
		||||
			form: null,
 | 
			
		||||
			messages: []
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,11 +130,56 @@ export default Vue.extend({
 | 
			
		|||
	created() {
 | 
			
		||||
		this.connection.on('change-accepts', this.onChangeAccepts);
 | 
			
		||||
		this.connection.on('update-settings', this.onUpdateSettings);
 | 
			
		||||
		this.connection.on('init-form', this.onInitForm);
 | 
			
		||||
		this.connection.on('message', this.onMessage);
 | 
			
		||||
 | 
			
		||||
		if (this.game.user1_id != (this as any).os.i.id && this.game.settings.form1) this.form = this.game.settings.form1;
 | 
			
		||||
		if (this.game.user2_id != (this as any).os.i.id && this.game.settings.form2) this.form = this.game.settings.form2;
 | 
			
		||||
 | 
			
		||||
		// for debugging
 | 
			
		||||
		if ((this as any).os.i.username == 'test1') {
 | 
			
		||||
			setTimeout(() => {
 | 
			
		||||
				this.connection.send({
 | 
			
		||||
					type: 'init-form',
 | 
			
		||||
					body: [{
 | 
			
		||||
						id: 'button1',
 | 
			
		||||
						type: 'button',
 | 
			
		||||
						label: 'Enable hoge',
 | 
			
		||||
						value: false
 | 
			
		||||
					}, {
 | 
			
		||||
						id: 'radio1',
 | 
			
		||||
						type: 'radio',
 | 
			
		||||
						label: '強さ',
 | 
			
		||||
						value: 2,
 | 
			
		||||
						items: [{
 | 
			
		||||
							label: '弱',
 | 
			
		||||
							value: 1
 | 
			
		||||
						}, {
 | 
			
		||||
							label: '中',
 | 
			
		||||
							value: 2
 | 
			
		||||
						}, {
 | 
			
		||||
							label: '強',
 | 
			
		||||
							value: 3
 | 
			
		||||
						}]
 | 
			
		||||
					}]
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				this.connection.send({
 | 
			
		||||
					type: 'message',
 | 
			
		||||
					body: {
 | 
			
		||||
						text: 'Hey',
 | 
			
		||||
						type: 'info'
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			}, 2000);
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	beforeDestroy() {
 | 
			
		||||
		this.connection.off('change-accepts', this.onChangeAccepts);
 | 
			
		||||
		this.connection.off('update-settings', this.onUpdateSettings);
 | 
			
		||||
		this.connection.off('init-form', this.onInitForm);
 | 
			
		||||
		this.connection.off('message', this.onMessage);
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	methods: {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +222,24 @@ export default Vue.extend({
 | 
			
		|||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		onInitForm(x) {
 | 
			
		||||
			if (x.user_id == (this as any).os.i.id) return;
 | 
			
		||||
			this.form = x.form;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		onMessage(x) {
 | 
			
		||||
			if (x.user_id == (this as any).os.i.id) return;
 | 
			
		||||
			this.messages.unshift(x.message);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		onChangeForm(v, item) {
 | 
			
		||||
			this.connection.send({
 | 
			
		||||
				type: 'update-form',
 | 
			
		||||
				id: item.id,
 | 
			
		||||
				value: v
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		onMapChange(v) {
 | 
			
		||||
			if (v == null) {
 | 
			
		||||
				this.game.settings.map = null;
 | 
			
		||||
| 
						 | 
				
			
			@ -168,20 +273,43 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
.root
 | 
			
		||||
	text-align center
 | 
			
		||||
	background #f9f9f9
 | 
			
		||||
 | 
			
		||||
	> header
 | 
			
		||||
		padding 8px
 | 
			
		||||
		border-bottom dashed 1px #c4cdd4
 | 
			
		||||
 | 
			
		||||
	> .map
 | 
			
		||||
		width 300px
 | 
			
		||||
	> div
 | 
			
		||||
		padding 0 16px
 | 
			
		||||
 | 
			
		||||
	> .board
 | 
			
		||||
		> .map
 | 
			
		||||
		> .bw
 | 
			
		||||
		> .rules
 | 
			
		||||
		> .bot-form
 | 
			
		||||
			max-width 400px
 | 
			
		||||
			margin 0 auto 16px auto
 | 
			
		||||
 | 
			
		||||
	> footer
 | 
			
		||||
		position sticky
 | 
			
		||||
		bottom 0
 | 
			
		||||
		padding 16px
 | 
			
		||||
		background rgba(255, 255, 255, 0.9)
 | 
			
		||||
		border-top solid 1px #c4cdd4
 | 
			
		||||
 | 
			
		||||
		> .status
 | 
			
		||||
			margin 0 0 16px 0
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" module>
 | 
			
		||||
.mapSelect
 | 
			
		||||
	width 100%
 | 
			
		||||
 | 
			
		||||
.board
 | 
			
		||||
	display grid
 | 
			
		||||
	grid-gap 4px
 | 
			
		||||
	width 300px
 | 
			
		||||
	height 300px
 | 
			
		||||
		margin 16px auto
 | 
			
		||||
	margin 0 auto
 | 
			
		||||
 | 
			
		||||
	> div
 | 
			
		||||
		background transparent
 | 
			
		||||
| 
						 | 
				
			
			@ -199,17 +327,9 @@ export default Vue.extend({
 | 
			
		|||
		&.none
 | 
			
		||||
			border-color transparent
 | 
			
		||||
 | 
			
		||||
	> .rules
 | 
			
		||||
		max-width 300px
 | 
			
		||||
		margin 0 auto 32px auto
 | 
			
		||||
 | 
			
		||||
	> footer
 | 
			
		||||
		position sticky
 | 
			
		||||
		bottom 0
 | 
			
		||||
		padding 16px
 | 
			
		||||
		background rgba(255, 255, 255, 0.9)
 | 
			
		||||
		border-top solid 1px #c4cdd4
 | 
			
		||||
 | 
			
		||||
		> .status
 | 
			
		||||
			margin 0 0 16px 0
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
.el-alert__content
 | 
			
		||||
	position initial !important
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue