App.vue 3.65 KB
Newer Older
Sebastian Speitel's avatar
Sebastian Speitel committed
1
2
<template>
  <div>
Sebastian Speitel's avatar
Sebastian Speitel committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    <div v-if="phase === 'setup'" class="card">
      <div class="card-body">
        <v-grid v-model:grid="myGrid" @clicked="edit(myGrid, $event)" />
      </div>
      <div class="card-footer btn-group">
        <button class="btn btn-danger" @click="myGrid.reset()">Reset</button>
        <button
          class="btn"
          :disabled="!valid"
          :class="{ 'btn-success': valid }"
          @click="phase = 'ready'"
        >
          Los!
        </button>
      </div>
    </div>
19
    <div v-if="phase === 'war'" class="card">
Sebastian Speitel's avatar
Sebastian Speitel committed
20
21
22
23
      <div class="card-body d-flex" style="justify-content: space-between">
        <v-grid v-model:grid="myGrid" />
        <v-grid v-model:grid="otherGrid" />
      </div>
Sebastian Speitel's avatar
Sebastian Speitel committed
24
    </div>
Sebastian Speitel's avatar
Sebastian Speitel committed
25
26
    <ul v-if="phase === 'setup'">
      <template v-for="l in Math.max(myGrid.width, myGrid.height)">
Sebastian Speitel's avatar
Sebastian Speitel committed
27
        <li
Sebastian Speitel's avatar
Sebastian Speitel committed
28
          v-if="required[l] || myGrid.shipCount(l)"
Sebastian Speitel's avatar
Sebastian Speitel committed
29
30
          :key="l"
          :style="`color:${
Sebastian Speitel's avatar
Sebastian Speitel committed
31
            (required[l] || 0) === myGrid.shipCount(l) ? 'green' : 'red'
Sebastian Speitel's avatar
Sebastian Speitel committed
32
33
          }`"
        >
Sebastian Speitel's avatar
Sebastian Speitel committed
34
          {{ l }}er: {{ myGrid.shipCount(l) }} von {{ required[l] || 0 }}
Sebastian Speitel's avatar
Sebastian Speitel committed
35
36
37
        </li>
      </template>
    </ul>
Sebastian Speitel's avatar
Sebastian Speitel committed
38

Sebastian Speitel's avatar
Sebastian Speitel committed
39
40
    <br />
    <textarea readonly v-text="json" />
Sebastian Speitel's avatar
Sebastian Speitel committed
41
42
43
44
  </div>
</template>

<script lang="ts">
Sebastian Speitel's avatar
Sebastian Speitel committed
45
import { reactive, ref, unref, computed, onMounted, watch } from "vue";
Sebastian Speitel's avatar
Sebastian Speitel committed
46
47
import { Cell, getCell, setCell, Grid } from "./gameLogic";
import VGrid from "./components/Grid.vue";
Sebastian Speitel's avatar
Sebastian Speitel committed
48
import * as config from "./config";
Sebastian Speitel's avatar
Sebastian Speitel committed
49

50
const required = config.SHIPS;
Sebastian Speitel's avatar
Sebastian Speitel committed
51

Sebastian Speitel's avatar
Sebastian Speitel committed
52
export default {
Sebastian Speitel's avatar
Sebastian Speitel committed
53
  components: { VGrid },
Sebastian Speitel's avatar
Sebastian Speitel committed
54
  setup() {
Sebastian Speitel's avatar
Sebastian Speitel committed
55
56
    const myGrid = reactive(new Grid(12, 6, Cell.UNKNOWN));
    const otherGrid = reactive(new Grid(12, 6));
Sebastian Speitel's avatar
Sebastian Speitel committed
57
58
    const phase = ref("setup");

Sebastian Speitel's avatar
Sebastian Speitel committed
59
60
    function edit(g: Grid, [x, y]: [x: number, y: number]) {
      const old = getCell(g, x, y);
61
      if (old === Cell.UNKNOWN) {
Sebastian Speitel's avatar
Sebastian Speitel committed
62
        setCell(g, x, y, Cell.SHIP);
Sebastian Speitel's avatar
Sebastian Speitel committed
63
64
65
66
        return;
      }

      if (old === Cell.SHIP) {
Sebastian Speitel's avatar
Sebastian Speitel committed
67
        setCell(g, x, y, Cell.UNKNOWN);
Sebastian Speitel's avatar
Sebastian Speitel committed
68
69
70
71
        return;
      }
    }

Sebastian Speitel's avatar
Sebastian Speitel committed
72
    const ships = computed(() => myGrid.ships);
Sebastian Speitel's avatar
Sebastian Speitel committed
73

Sebastian Speitel's avatar
Sebastian Speitel committed
74
    const valid = myGrid.valid(required);
Sebastian Speitel's avatar
Sebastian Speitel committed
75
76
77
78
79

    const json = computed(() => {
      return JSON.stringify([...ships.value.values()]);
    });

Sebastian Speitel's avatar
Sebastian Speitel committed
80
    setInterval(async () => {
Sebastian Speitel's avatar
Sebastian Speitel committed
81
      const resp = await fetch(config.BASE_URL + "/api/gamephase");
Sebastian Speitel's avatar
Sebastian Speitel committed
82
      const { phase: p } = await resp.json();
Sebastian Speitel's avatar
Sebastian Speitel committed
83
      if (phase.value === "ready" && p !== "war") {
Sebastian Speitel's avatar
Sebastian Speitel committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
        return;
      }
      phase.value = p;

      if (p !== "war") {
        return;
      }

      const state2Cell: { [s: string]: Cell } = {
        H: Cell.HIT,
        S: Cell.SHIP,
        W: Cell.UNKNOWN,
        F: Cell.WATER
      };

Sebastian Speitel's avatar
Sebastian Speitel committed
99
      fetch(config.BASE_URL + "/api/grid/my")
Sebastian Speitel's avatar
Sebastian Speitel committed
100
101
102
103
104
105
106
        .then(r => r.json())
        .then(json => {
          for (const { x, y, state } of json) {
            setCell(myGrid, x, y, state2Cell[state]);
          }
        });

Sebastian Speitel's avatar
Sebastian Speitel committed
107
      fetch(config.BASE_URL + "/api/grid/other")
Sebastian Speitel's avatar
Sebastian Speitel committed
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
        .then(r => r.json())
        .then(json => {
          for (const { x, y, state } of json) {
            setCell(otherGrid, x, y, state2Cell[state]);
          }
        });
    }, 1000);

    watch(phase, p => {
      p = unref(p);
      switch (p) {
        case "setup":
          myGrid.reset();
          break;
        case "ready":
Sebastian Speitel's avatar
Sebastian Speitel committed
123
          fetch(config.BASE_URL + "/api/ready", {
Sebastian Speitel's avatar
Sebastian Speitel committed
124
125
126
127
128
129
130
131
132
133
134
135
136
            method: "POST",
            headers: {
              "Content-Type": "application/json"
            },
            body: JSON.stringify(myGrid)
          });
          break;
        case "war":
          otherGrid.reset();
          break;
      }
    });

Sebastian Speitel's avatar
Sebastian Speitel committed
137
    return {
Sebastian Speitel's avatar
Sebastian Speitel committed
138
      phase,
Sebastian Speitel's avatar
Sebastian Speitel committed
139
140
      myGrid,
      otherGrid,
Sebastian Speitel's avatar
Sebastian Speitel committed
141
      getCell,
Sebastian Speitel's avatar
Sebastian Speitel committed
142
      edit,
Sebastian Speitel's avatar
Sebastian Speitel committed
143
144
145
146
147
148
149
      ships,
      required,
      valid,
      json
    };
  }
};
Sebastian Speitel's avatar
Sebastian Speitel committed
150
</script>