It works!
This commit is contained in:
parent
1040f980a0
commit
089e6021f9
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/">Start</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</div>
|
||||
<router-view/>
|
||||
|
|
7
src/models/Answer.ts
Normal file
7
src/models/Answer.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export class Answer {
|
||||
public constructor(public text: string[], public uuid: string = "", public index: number = -1) {
|
||||
this.text = text;
|
||||
this.index! = index;
|
||||
this.uuid! = uuid;
|
||||
}
|
||||
}
|
17
src/models/Message.ts
Normal file
17
src/models/Message.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
export enum MessageType {
|
||||
JOIN = "JOIN",
|
||||
START = "START",
|
||||
ANSWER = "ANSWER",
|
||||
PICK = "PICK",
|
||||
ROOM = "ROOM",
|
||||
}
|
||||
|
||||
export class Message {
|
||||
public msgtype: MessageType;
|
||||
public data: any;
|
||||
|
||||
public constructor(msgtype: MessageType, data: any) {
|
||||
this.msgtype = msgtype;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
13
src/models/Room.ts
Normal file
13
src/models/Room.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { Player } from "./Player";
|
||||
|
||||
export class Room {
|
||||
public code: string;
|
||||
public czar: number = 0;
|
||||
public players: Player[] = [];
|
||||
public started: boolean = false;
|
||||
// tslint:disable-next-line:variable-name
|
||||
public played_cards: number[] = [];
|
||||
public constructor(code: string) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import Vue from "vue";
|
||||
import Router from "vue-router";
|
||||
import JoinRoom from "./views/JoinRoom.vue";
|
||||
import Game from "./views/Game.vue";
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
|
@ -13,6 +14,11 @@ export default new Router({
|
|||
name: "home",
|
||||
component: JoinRoom,
|
||||
},
|
||||
{
|
||||
path: "/game/:code",
|
||||
name: "game",
|
||||
component: Game,
|
||||
},
|
||||
{
|
||||
path: "/about",
|
||||
name: "about",
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import axios from "axios";
|
||||
import { Message, MessageType } from "../models/Message";
|
||||
import { Answer } from "../models/Answer";
|
||||
|
||||
const webProt = "http://";
|
||||
const baseURL = "localhost:8000";
|
||||
|
||||
const axios_api = axios.create({
|
||||
baseURL,
|
||||
export const axios_api = axios.create({
|
||||
baseURL: webProt + baseURL,
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
|
@ -11,21 +14,62 @@ const axios_api = axios.create({
|
|||
});
|
||||
|
||||
export class Game {
|
||||
public uuid!: string;
|
||||
public owner!: boolean;
|
||||
public you!: number;
|
||||
private pub: WebSocket;
|
||||
private sub: WebSocket;
|
||||
private uuid: string;
|
||||
|
||||
constructor(code: string, name: string) {
|
||||
this.pub = new WebSocket(`://localhost:8000/ws/room/${code}/pub`);
|
||||
this.sub = new WebSocket(`://localhost:8000/ws/room/${code}/sub`);
|
||||
constructor(code: string, name: string, message_callback: (message: Message) => void) {
|
||||
this.pub = new WebSocket(`ws://${baseURL}/ws/room/${code}/pub`);
|
||||
this.sub = new WebSocket(`ws://${baseURL}/ws/room/${code}/sub`);
|
||||
|
||||
this.pub.addEventListener("open", (event) => {
|
||||
// JOIN
|
||||
console.info("pub-ws connected");
|
||||
const join = new Message(MessageType.JOIN, name);
|
||||
this.pub.send(JSON.stringify(join));
|
||||
});
|
||||
|
||||
this.pub.addEventListener("message", (event) => {
|
||||
const data: Player = JSON.parse(event.data);
|
||||
const msg: Message = JSON.parse(event.data);
|
||||
if (msg.msgtype === MessageType.JOIN) {
|
||||
this.uuid = msg.data.uuid;
|
||||
this.owner = msg.data.owner;
|
||||
this.you = msg.data.you;
|
||||
} else {
|
||||
message_callback(msg);
|
||||
}
|
||||
});
|
||||
|
||||
this.sub.addEventListener("open", (event) => {
|
||||
console.info("sub-ws connected");
|
||||
});
|
||||
|
||||
this.sub.addEventListener("message", (event) => {
|
||||
if (event.data === "1") {
|
||||
console.info("Hyperadvanced one way websocket connection established");
|
||||
return;
|
||||
}
|
||||
console.log(event.data);
|
||||
const msg: Message = JSON.parse(event.data);
|
||||
message_callback(msg);
|
||||
});
|
||||
}
|
||||
|
||||
public start_game() {
|
||||
const msg = new Message(MessageType.START, this.uuid);
|
||||
this.pub.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
public send_answer(text: string[]) {
|
||||
const answers = new Answer(text, this.uuid);
|
||||
const msg = new Message(MessageType.ANSWER, JSON.stringify(answers));
|
||||
this.pub.send(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
public pick_answer(answer: Answer) {
|
||||
answer.uuid = this.uuid;
|
||||
const msg = new Message(MessageType.PICK, JSON.stringify(answer));
|
||||
this.pub.send(JSON.stringify(msg));
|
||||
}
|
||||
}
|
||||
|
|
109
src/views/Game.vue
Normal file
109
src/views/Game.vue
Normal file
|
@ -0,0 +1,109 @@
|
|||
<template>
|
||||
<div id="game">
|
||||
<h1>
|
||||
Room:
|
||||
<a>{{ this.$route.params.code }}</a>
|
||||
</h1>
|
||||
<h2>Your name is: {{ this.name }}</h2>
|
||||
<ul>
|
||||
<li v-for="player in this.room.players">{{ player.name }}: {{player.points}}</li>
|
||||
</ul>
|
||||
|
||||
<button v-if="this.game.owner && !this.room.started" @click="this.start_game">Stort</button>
|
||||
|
||||
<span v-show="this.card" v-html="this.card.text" />
|
||||
|
||||
<ul v-show="this.card && !this.czar()">
|
||||
<li v-for="blank in this.card.pick">
|
||||
Card {{blank}}:
|
||||
<input type="text" v-model="inputs[blank - 1]" :disabled="input_blocked" />
|
||||
</li>
|
||||
<li>
|
||||
<button @click="this.send_answers" v-show="!input_blocked && room.started">Submit Answers</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li v-for="ans in this.answers">
|
||||
<span v-for="t in ans.text">{{ t }}, </span>
|
||||
<button @click="pick(ans)" v-show="czar()">Pick</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { Game, axios_api } from "../util/api";
|
||||
import { Message, MessageType } from "../models/Message";
|
||||
import { Room } from "../models/Room";
|
||||
import { Card } from "../models/Card";
|
||||
import { Answer } from "../models/Answer";
|
||||
|
||||
@Component({
|
||||
name: "Game",
|
||||
})
|
||||
export default class GameVueView extends Vue {
|
||||
private game: Game = {};
|
||||
private room: Room = {};
|
||||
private card: Card = {};
|
||||
private inputs: string[] = [];
|
||||
private input_blocked: boolean = false;
|
||||
private answers: Answer[] = [];
|
||||
private name: string;
|
||||
/**
|
||||
* Lifecycle hooks
|
||||
*/
|
||||
private async mounted() {
|
||||
this.name = this.$route.query.name || prompt("What is your nickname?");
|
||||
if (name && this.$route.params.code.length > 3) {
|
||||
this.name = name as string;
|
||||
const room = await axios_api.get(`/room/${this.$route.params.code}`);
|
||||
|
||||
if (room.status === 200 && !room.data.started) {
|
||||
this.game = new Game(this.$route.params.code, name, this.on_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private start_game() {
|
||||
this.game.start_game();
|
||||
}
|
||||
|
||||
private send_answers() {
|
||||
this.input_blocked = true;
|
||||
this.game.send_answer(this.inputs);
|
||||
}
|
||||
|
||||
private czar(): boolean {
|
||||
return this.game.you === this.room.czar;
|
||||
}
|
||||
|
||||
private pick(ans: Answer) {
|
||||
this.game.pick_answer(ans);
|
||||
}
|
||||
|
||||
private on_message(message: Message) {
|
||||
switch (message.msgtype) {
|
||||
case MessageType.JOIN:
|
||||
break;
|
||||
case MessageType.START:
|
||||
this.answers = [];
|
||||
this.inputs = [];
|
||||
this.input_blocked = false;
|
||||
this.card = message.data.card as Card;
|
||||
break;
|
||||
case MessageType.ROOM:
|
||||
this.room = message.data as Room;
|
||||
break;
|
||||
case MessageType.ANSWER:
|
||||
this.answers = message.data as Answer[];
|
||||
break;
|
||||
case MessageType.PICK:
|
||||
alert(message.data.text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
|
@ -1,15 +1,25 @@
|
|||
<template>
|
||||
<div id="joinroom">
|
||||
<label class="code-label" for="code">Room Code:</label>
|
||||
<input id="code" type="text" v-model="code" placeholder="Enter code here" minlength="4" />
|
||||
<label class="name-label" for>Name:</label>
|
||||
<input id="name" type="text" placeholder="Enter a username" maxlength="25" />
|
||||
<input
|
||||
required
|
||||
id="name"
|
||||
v-model="name"
|
||||
type="text"
|
||||
placeholder="Enter a username"
|
||||
maxlength="25"
|
||||
minlength="1"
|
||||
/>
|
||||
<label class="code-label" for="code">Room Code:</label>
|
||||
<input id="code" type="text" v-model="code" placeholder="Optional room code" minlength="4" />
|
||||
|
||||
<button id="join">Join!</button>
|
||||
<button @click="checkRoom" id="join">Join!</button>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { axios_api } from "../util/api";
|
||||
import {Room} from "../models/Room";
|
||||
|
||||
@Component({
|
||||
name: "JoinRoom",
|
||||
|
@ -17,6 +27,29 @@ import { Component, Vue } from "vue-property-decorator";
|
|||
export default class JoinRoom extends Vue {
|
||||
private code: string = "";
|
||||
private name: string = "";
|
||||
|
||||
private checkRoom() {
|
||||
if (this.name.length < 1 || this.name.length > 25) {
|
||||
return;
|
||||
}
|
||||
if (this.code.length >= 4) {
|
||||
this.code = this.code.trim();
|
||||
axios_api
|
||||
.get(`/room/${this.code}`)
|
||||
.then((data) => {
|
||||
this.$router.push(`/game/${this.code}?name=${this.name}`);
|
||||
})
|
||||
.catch((response) => {
|
||||
console.log("Error?" + response);
|
||||
alert("Sadly, this room does not exist...");
|
||||
});
|
||||
} else if (this.code.length === 0) {
|
||||
axios_api.post("/room").then((data) => {
|
||||
const room: Room = data.data;
|
||||
this.$router.push(`/game/${room.code}?name=${this.name}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
@ -27,20 +60,20 @@ export default class JoinRoom extends Vue {
|
|||
}
|
||||
|
||||
.code-label {
|
||||
grid-row: 1;
|
||||
grid-row: 2;
|
||||
grid-column: 2;
|
||||
min-width: 100px;
|
||||
}
|
||||
#code {
|
||||
grid-row: 1;
|
||||
grid-row: 2;
|
||||
grid-column: 3;
|
||||
}
|
||||
.name-label {
|
||||
grid-row: 2;
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
}
|
||||
#name {
|
||||
grid-row: 2;
|
||||
grid-row: 1;
|
||||
grid-column: 3;
|
||||
}
|
||||
|
||||
|
|
17
tslint.json
17
tslint.json
|
@ -9,11 +9,20 @@
|
|||
]
|
||||
},
|
||||
"rules": {
|
||||
"quotemark": [true, "double"],
|
||||
"indent": [true, "spaces", 4],
|
||||
"quotemark": [
|
||||
true,
|
||||
"double"
|
||||
],
|
||||
"indent": [
|
||||
true,
|
||||
"spaces",
|
||||
4
|
||||
],
|
||||
"no-console": false,
|
||||
"interface-name": false,
|
||||
"ordered-imports": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"no-consecutive-blank-lines": false
|
||||
"no-consecutive-blank-lines": false,
|
||||
"variable-name": false
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue