wad-lab 1.0.9 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +13 -5
- package/package.json +1 -1
- package/templates/servlet-session-tracking/WEB-INF/LoginServlet.java +46 -0
- package/templates/servlet-session-tracking/WEB-INF/LogoutServlet.java +39 -0
- package/templates/servlet-session-tracking/WEB-INF/ProfileServlet.java +83 -0
- package/templates/servlet-session-tracking/WEB-INF/classes/LoginServlet.class +0 -0
- package/templates/servlet-session-tracking/WEB-INF/classes/LogoutServlet.class +0 -0
- package/templates/servlet-session-tracking/WEB-INF/classes/ProfileServlet.class +0 -0
- package/templates/servlet-session-tracking/WEB-INF/web.xml +38 -0
- package/templates/servlet-session-tracking/index.html +36 -0
- package/templates/springboot-hospital-api/.mvn/wrapper/maven-wrapper.properties +3 -0
- package/templates/springboot-hospital-api/mvnw +295 -0
- package/templates/springboot-hospital-api/mvnw.cmd +189 -0
- package/templates/springboot-hospital-api/pom.xml +41 -0
- package/templates/springboot-hospital-api/src/main/java/com/example/hospital/HospitalApplication.java +12 -0
- package/templates/springboot-hospital-api/src/main/java/com/example/hospital/controller/HospitalController.java +50 -0
- package/templates/springboot-hospital-api/src/main/java/com/example/hospital/model/Appointment.java +95 -0
- package/templates/springboot-hospital-api/src/main/java/com/example/hospital/repository/AppointmentRepository.java +15 -0
- package/templates/springboot-hospital-api/src/main/java/com/example/hospital/service/HospitalService.java +54 -0
- package/templates/springboot-hospital-api/src/main/resources/application.properties +3 -0
- package/templates/springboot-hospital-api/src/test/java/com/example/hospital/HospitalApplicationTests.java +12 -0
- package/templates/springboot-library-api/.mvn/wrapper/maven-wrapper.properties +3 -0
- package/templates/springboot-library-api/mvnw +295 -0
- package/templates/springboot-library-api/mvnw.cmd +189 -0
- package/templates/springboot-library-api/pom.xml +42 -0
- package/templates/springboot-library-api/src/main/java/com/example/library/LibraryApplication.java +12 -0
- package/templates/springboot-library-api/src/main/java/com/example/library/controller/LibraryController.java +51 -0
- package/templates/springboot-library-api/src/main/java/com/example/library/model/Book.java +76 -0
- package/templates/springboot-library-api/src/main/java/com/example/library/model/CategoryAnalytics.java +41 -0
- package/templates/springboot-library-api/src/main/java/com/example/library/repository/BookRepository.java +13 -0
- package/templates/springboot-library-api/src/main/java/com/example/library/service/LibraryService.java +60 -0
- package/templates/springboot-library-api/src/main/resources/application.properties +3 -0
- package/templates/vue-game-rps/index.html +12 -0
- package/templates/vue-game-rps/package.json +19 -0
- package/templates/vue-game-rps/src/App.vue +125 -0
- package/templates/vue-game-rps/src/main.js +5 -0
- package/templates/vue-game-rps/src/stores/rpsStore.js +43 -0
- package/templates/vue-game-rps/vite.config.js +6 -0
- package/templates/vue-game-tictactoe/index.html +12 -0
- package/templates/vue-game-tictactoe/package.json +19 -0
- package/templates/vue-game-tictactoe/src/App.vue +105 -0
- package/templates/vue-game-tictactoe/src/main.js +5 -0
- package/templates/vue-game-tictactoe/src/stores/tictactoeStore.js +61 -0
- package/templates/vue-game-tictactoe/vite.config.js +6 -0
- package/templates/vue-game-whackamole/index.html +12 -0
- package/templates/vue-game-whackamole/package.json +19 -0
- package/templates/vue-game-whackamole/src/App.vue +104 -0
- package/templates/vue-game-whackamole/src/main.js +7 -0
- package/templates/vue-game-whackamole/src/stores/moleStore.js +71 -0
- package/templates/vue-game-whackamole/vite.config.js +6 -0
- package/templates/vue-hospital-portal/index.html +12 -0
- package/templates/vue-hospital-portal/package.json +20 -0
- package/templates/vue-hospital-portal/src/App.vue +107 -0
- package/templates/vue-hospital-portal/src/main.js +9 -0
- package/templates/vue-hospital-portal/src/router/index.js +17 -0
- package/templates/vue-hospital-portal/src/stores/hospitalStore.js +91 -0
- package/templates/vue-hospital-portal/src/views/HospitalBillingView.vue +271 -0
- package/templates/vue-hospital-portal/src/views/OPDRegistrationView.vue +453 -0
- package/templates/vue-hospital-portal/src/views/PatientListView.vue +315 -0
- package/templates/vue-hospital-portal/vite.config.js +6 -0
- package/templates/vue-library-system/index.html +12 -0
- package/templates/vue-library-system/package.json +20 -0
- package/templates/vue-library-system/src/App.vue +91 -0
- package/templates/vue-library-system/src/main.js +9 -0
- package/templates/vue-library-system/src/router/index.js +29 -0
- package/templates/vue-library-system/src/stores/libraryStore.js +87 -0
- package/templates/vue-library-system/src/views/BookCatalogView.vue +432 -0
- package/templates/vue-library-system/src/views/LoanManagerView.vue +296 -0
- package/templates/vue-library-system/src/views/MembershipView.vue +269 -0
- package/templates/vue-library-system/vite.config.js +6 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package com.example.library.model;
|
|
2
|
+
|
|
3
|
+
public class CategoryAnalytics {
|
|
4
|
+
|
|
5
|
+
private String category;
|
|
6
|
+
private int totalCopies;
|
|
7
|
+
private double averagePrice;
|
|
8
|
+
|
|
9
|
+
public CategoryAnalytics() {
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public CategoryAnalytics(String category, int totalCopies, double averagePrice) {
|
|
13
|
+
this.category = category;
|
|
14
|
+
this.totalCopies = totalCopies;
|
|
15
|
+
this.averagePrice = averagePrice;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public String getCategory() {
|
|
19
|
+
return category;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public void setCategory(String category) {
|
|
23
|
+
this.category = category;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public int getTotalCopies() {
|
|
27
|
+
return totalCopies;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public void setTotalCopies(int totalCopies) {
|
|
31
|
+
this.totalCopies = totalCopies;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public double getAveragePrice() {
|
|
35
|
+
return averagePrice;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public void setAveragePrice(double averagePrice) {
|
|
39
|
+
this.averagePrice = averagePrice;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.example.library.repository;
|
|
2
|
+
|
|
3
|
+
import com.example.library.model.Book;
|
|
4
|
+
import org.springframework.data.mongodb.repository.MongoRepository;
|
|
5
|
+
import org.springframework.stereotype.Repository;
|
|
6
|
+
|
|
7
|
+
import java.util.List;
|
|
8
|
+
|
|
9
|
+
@Repository
|
|
10
|
+
public interface BookRepository extends MongoRepository<Book, String> {
|
|
11
|
+
List<Book> findByCategory(String category);
|
|
12
|
+
List<Book> findByAuthor(String author);
|
|
13
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package com.example.library.service;
|
|
2
|
+
|
|
3
|
+
import com.example.library.model.Book;
|
|
4
|
+
import com.example.library.model.CategoryAnalytics;
|
|
5
|
+
import com.example.library.repository.BookRepository;
|
|
6
|
+
import org.springframework.data.mongodb.core.MongoTemplate;
|
|
7
|
+
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
|
8
|
+
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
|
9
|
+
import org.springframework.stereotype.Service;
|
|
10
|
+
|
|
11
|
+
import java.util.List;
|
|
12
|
+
import java.util.Optional;
|
|
13
|
+
|
|
14
|
+
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
|
|
15
|
+
|
|
16
|
+
@Service
|
|
17
|
+
public class LibraryService {
|
|
18
|
+
|
|
19
|
+
private final BookRepository bookRepository;
|
|
20
|
+
private final MongoTemplate mongoTemplate;
|
|
21
|
+
|
|
22
|
+
public LibraryService(BookRepository bookRepository, MongoTemplate mongoTemplate) {
|
|
23
|
+
this.bookRepository = bookRepository;
|
|
24
|
+
this.mongoTemplate = mongoTemplate;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public List<Book> getAllBooks() {
|
|
28
|
+
return bookRepository.findAll();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public Optional<Book> getBookById(String id) {
|
|
32
|
+
return bookRepository.findById(id);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public Book addBook(Book book) {
|
|
36
|
+
return bookRepository.save(book);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public void deleteBook(String id) {
|
|
40
|
+
bookRepository.deleteById(id);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public List<CategoryAnalytics> getCategoryAnalytics() {
|
|
44
|
+
Aggregation aggregation = newAggregation(
|
|
45
|
+
group("category")
|
|
46
|
+
.sum("totalCopies").as("totalCopies")
|
|
47
|
+
.avg("price").as("averagePrice"),
|
|
48
|
+
project("totalCopies", "averagePrice")
|
|
49
|
+
.and("_id").as("category")
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
AggregationResults<CategoryAnalytics> results = mongoTemplate.aggregate(
|
|
53
|
+
aggregation,
|
|
54
|
+
"books",
|
|
55
|
+
CategoryAnalytics.class
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return results.getMappedResults();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Vue Rock Paper Scissors</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.js"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-game-rps",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"pinia": "^4.1.0",
|
|
13
|
+
"vue": "^3.5.44"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
17
|
+
"vite": "^8.3.4"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="container">
|
|
3
|
+
<h1>Vue Rock Paper Scissors</h1>
|
|
4
|
+
|
|
5
|
+
<div class="scoreboard">
|
|
6
|
+
<div class="score-card">
|
|
7
|
+
<span class="label">Player:</span>
|
|
8
|
+
<span class="value">{{ store.playerScore }}</span>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="score-card">
|
|
11
|
+
<span class="label">Computer:</span>
|
|
12
|
+
<span class="value">{{ store.computerScore }}</span>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="score-card">
|
|
15
|
+
<span class="label">Ties:</span>
|
|
16
|
+
<span class="value">{{ store.ties }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="choices">
|
|
21
|
+
<button @click="store.playRound('Rock')">✊ Rock</button>
|
|
22
|
+
<button @click="store.playRound('Paper')">✋ Paper</button>
|
|
23
|
+
<button @click="store.playRound('Scissors')">✌ Scissors</button>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="results">
|
|
27
|
+
<div v-if="store.playerChoice && store.computerChoice" class="matchup">
|
|
28
|
+
<p>Player: <strong>{{ store.playerChoice }}</strong></p>
|
|
29
|
+
<p>Computer: <strong>{{ store.computerChoice }}</strong></p>
|
|
30
|
+
</div>
|
|
31
|
+
<p class="message">{{ store.resultMessage }}</p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<button class="reset-btn" @click="store.resetGame">Reset Game</button>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script setup>
|
|
39
|
+
import { useRpsStore } from './stores/rpsStore'
|
|
40
|
+
|
|
41
|
+
const store = useRpsStore()
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<style scoped>
|
|
45
|
+
.container {
|
|
46
|
+
max-width: 500px;
|
|
47
|
+
margin: 40px auto;
|
|
48
|
+
padding: 20px;
|
|
49
|
+
text-align: center;
|
|
50
|
+
font-family: Arial, sans-serif;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.scoreboard {
|
|
54
|
+
display: flex;
|
|
55
|
+
justify-content: space-around;
|
|
56
|
+
margin: 20px 0;
|
|
57
|
+
padding: 12px;
|
|
58
|
+
background: #f0f0f0;
|
|
59
|
+
border-radius: 6px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.score-card {
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
gap: 4px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.label {
|
|
69
|
+
font-weight: bold;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.value {
|
|
73
|
+
font-size: 1.4rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.choices {
|
|
77
|
+
display: flex;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
gap: 12px;
|
|
80
|
+
margin: 20px 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
button {
|
|
84
|
+
padding: 10px 16px;
|
|
85
|
+
font-size: 1rem;
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
border: 1px solid #ccc;
|
|
88
|
+
border-radius: 4px;
|
|
89
|
+
background: #fff;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
button:hover {
|
|
93
|
+
background: #e9e9e9;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.results {
|
|
97
|
+
margin: 20px 0;
|
|
98
|
+
padding: 15px;
|
|
99
|
+
border: 1px solid #ddd;
|
|
100
|
+
border-radius: 6px;
|
|
101
|
+
background: #fafafa;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.matchup {
|
|
105
|
+
display: flex;
|
|
106
|
+
justify-content: space-around;
|
|
107
|
+
margin-bottom: 10px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.message {
|
|
111
|
+
font-size: 1.2rem;
|
|
112
|
+
font-weight: bold;
|
|
113
|
+
margin: 5px 0 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.reset-btn {
|
|
117
|
+
background: #e74c3c;
|
|
118
|
+
color: #fff;
|
|
119
|
+
border: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.reset-btn:hover {
|
|
123
|
+
background: #c0392b;
|
|
124
|
+
}
|
|
125
|
+
</style>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
|
|
3
|
+
export const useRpsStore = defineStore('rps', {
|
|
4
|
+
state: () => ({
|
|
5
|
+
choices: ['Rock', 'Paper', 'Scissors'],
|
|
6
|
+
playerScore: 0,
|
|
7
|
+
computerScore: 0,
|
|
8
|
+
ties: 0,
|
|
9
|
+
playerChoice: null,
|
|
10
|
+
computerChoice: null,
|
|
11
|
+
resultMessage: 'Make your choice to play!'
|
|
12
|
+
}),
|
|
13
|
+
actions: {
|
|
14
|
+
playRound(choice) {
|
|
15
|
+
this.playerChoice = choice
|
|
16
|
+
const randomIndex = Math.floor(Math.random() * this.choices.length)
|
|
17
|
+
this.computerChoice = this.choices[randomIndex]
|
|
18
|
+
|
|
19
|
+
if (this.playerChoice === this.computerChoice) {
|
|
20
|
+
this.ties++
|
|
21
|
+
this.resultMessage = "It's a tie!"
|
|
22
|
+
} else if (
|
|
23
|
+
(this.playerChoice === 'Rock' && this.computerChoice === 'Scissors') ||
|
|
24
|
+
(this.playerChoice === 'Paper' && this.computerChoice === 'Rock') ||
|
|
25
|
+
(this.playerChoice === 'Scissors' && this.computerChoice === 'Paper')
|
|
26
|
+
) {
|
|
27
|
+
this.playerScore++
|
|
28
|
+
this.resultMessage = 'You win!'
|
|
29
|
+
} else {
|
|
30
|
+
this.computerScore++
|
|
31
|
+
this.resultMessage = 'Computer wins!'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
resetGame() {
|
|
35
|
+
this.playerScore = 0
|
|
36
|
+
this.computerScore = 0
|
|
37
|
+
this.ties = 0
|
|
38
|
+
this.playerChoice = null
|
|
39
|
+
this.computerChoice = null
|
|
40
|
+
this.resultMessage = 'Make your choice to play!'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Vue Tic Tac Toe</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.js"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-game-tictactoe",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"pinia": "^4.1.0",
|
|
13
|
+
"vue": "^3.5.44"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
17
|
+
"vite": "^8.3.4"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useTicTacToeStore } from './stores/tictactoeStore'
|
|
3
|
+
|
|
4
|
+
const store = useTicTacToeStore()
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div class="game-container">
|
|
9
|
+
<h1>Vue Tic Tac Toe</h1>
|
|
10
|
+
|
|
11
|
+
<div class="status">
|
|
12
|
+
<span v-if="store.winner">Player {{ store.winner }} Wins! 🎉</span>
|
|
13
|
+
<span v-else-if="store.isDraw">Game Draw! 🤝</span>
|
|
14
|
+
<span v-else>Player {{ store.currentPlayer }}'s Turn</span>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div class="board">
|
|
18
|
+
<button
|
|
19
|
+
v-for="(cell, index) in store.board"
|
|
20
|
+
:key="index"
|
|
21
|
+
type="button"
|
|
22
|
+
class="cell"
|
|
23
|
+
:disabled="cell !== '' || !!store.winner || store.isDraw"
|
|
24
|
+
@click="store.makeMove(index)"
|
|
25
|
+
>
|
|
26
|
+
{{ cell }}
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<button type="button" class="btn-reset" @click="store.resetBoard">Reset Game</button>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
body {
|
|
36
|
+
font-family: Arial, sans-serif;
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
align-items: center;
|
|
40
|
+
min-height: 100vh;
|
|
41
|
+
margin: 0;
|
|
42
|
+
background-color: #f5f5f5;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.game-container {
|
|
46
|
+
text-align: center;
|
|
47
|
+
background: #ffffff;
|
|
48
|
+
padding: 30px;
|
|
49
|
+
border: 1px solid #ccc;
|
|
50
|
+
border-radius: 8px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
h1 {
|
|
54
|
+
margin-top: 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.status {
|
|
58
|
+
margin: 15px 0;
|
|
59
|
+
font-size: 20px;
|
|
60
|
+
font-weight: bold;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.board {
|
|
64
|
+
display: grid;
|
|
65
|
+
grid-template-columns: repeat(3, 80px);
|
|
66
|
+
gap: 8px;
|
|
67
|
+
margin: 20px auto;
|
|
68
|
+
width: 256px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.cell {
|
|
72
|
+
width: 80px;
|
|
73
|
+
height: 80px;
|
|
74
|
+
background-color: #f9f9f9;
|
|
75
|
+
border: 2px solid #555;
|
|
76
|
+
font-size: 36px;
|
|
77
|
+
font-weight: bold;
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
display: flex;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
align-items: center;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.cell:hover:not(:disabled) {
|
|
85
|
+
background-color: #eee;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.cell:disabled {
|
|
89
|
+
cursor: not-allowed;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.btn-reset {
|
|
93
|
+
padding: 10px 20px;
|
|
94
|
+
font-size: 16px;
|
|
95
|
+
background-color: #333;
|
|
96
|
+
color: white;
|
|
97
|
+
border: none;
|
|
98
|
+
border-radius: 4px;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.btn-reset:hover {
|
|
103
|
+
background-color: #555;
|
|
104
|
+
}
|
|
105
|
+
</style>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
|
|
3
|
+
export const useTicTacToeStore = defineStore('tictactoe', {
|
|
4
|
+
state: () => ({
|
|
5
|
+
board: Array(9).fill(''),
|
|
6
|
+
currentPlayer: 'X',
|
|
7
|
+
winner: null,
|
|
8
|
+
isDraw: false,
|
|
9
|
+
winningConditions: [
|
|
10
|
+
[0, 1, 2],
|
|
11
|
+
[3, 4, 5],
|
|
12
|
+
[6, 7, 8],
|
|
13
|
+
[0, 3, 6],
|
|
14
|
+
[1, 4, 7],
|
|
15
|
+
[2, 5, 8],
|
|
16
|
+
[0, 4, 8],
|
|
17
|
+
[2, 4, 6]
|
|
18
|
+
]
|
|
19
|
+
}),
|
|
20
|
+
actions: {
|
|
21
|
+
checkWin() {
|
|
22
|
+
for (const [a, b, c] of this.winningConditions) {
|
|
23
|
+
if (this.board[a] && this.board[a] === this.board[b] && this.board[b] === this.board[c]) {
|
|
24
|
+
this.winner = this.currentPlayer
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false
|
|
29
|
+
},
|
|
30
|
+
checkDraw() {
|
|
31
|
+
if (!this.board.includes('')) {
|
|
32
|
+
this.isDraw = true
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
return false
|
|
36
|
+
},
|
|
37
|
+
makeMove(index) {
|
|
38
|
+
if (this.board[index] !== '' || this.winner || this.isDraw) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.board[index] = this.currentPlayer
|
|
43
|
+
|
|
44
|
+
if (this.checkWin()) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (this.checkDraw()) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.currentPlayer = this.currentPlayer === 'X' ? 'O' : 'X'
|
|
53
|
+
},
|
|
54
|
+
resetBoard() {
|
|
55
|
+
this.board = Array(9).fill('')
|
|
56
|
+
this.currentPlayer = 'X'
|
|
57
|
+
this.winner = null
|
|
58
|
+
this.isDraw = false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Vue Whack A Mole</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.js"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-game-whackamole",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"pinia": "^4.1.0",
|
|
13
|
+
"vue": "^3.5.44"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@vitejs/plugin-vue": "^5.2.1",
|
|
17
|
+
"vite": "^6.0.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="game-container">
|
|
3
|
+
<h1>Vue Whack A Mole</h1>
|
|
4
|
+
|
|
5
|
+
<div class="status-bar">
|
|
6
|
+
<span>Score: {{ store.score }}</span>
|
|
7
|
+
<span>Time Left: {{ store.timeLeft }}s</span>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<button class="start-btn" :disabled="store.isPlaying" @click="store.startGame()">
|
|
11
|
+
Start Game
|
|
12
|
+
</button>
|
|
13
|
+
|
|
14
|
+
<div class="grid">
|
|
15
|
+
<div
|
|
16
|
+
v-for="i in 9"
|
|
17
|
+
:key="i - 1"
|
|
18
|
+
class="hole"
|
|
19
|
+
@click="store.whackMole(i - 1)"
|
|
20
|
+
>
|
|
21
|
+
<span v-if="store.activeHoleIndex === i - 1" class="mole">🐹</span>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup>
|
|
28
|
+
import { useMoleStore } from './stores/moleStore'
|
|
29
|
+
|
|
30
|
+
const store = useMoleStore()
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
body {
|
|
35
|
+
margin: 0;
|
|
36
|
+
font-family: sans-serif;
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
align-items: center;
|
|
40
|
+
min-height: 100vh;
|
|
41
|
+
background-color: #f0f2f5;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.game-container {
|
|
45
|
+
text-align: center;
|
|
46
|
+
background: #ffffff;
|
|
47
|
+
padding: 24px;
|
|
48
|
+
border-radius: 12px;
|
|
49
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
50
|
+
width: 320px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
h1 {
|
|
54
|
+
margin-top: 0;
|
|
55
|
+
margin-bottom: 16px;
|
|
56
|
+
font-size: 24px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.status-bar {
|
|
60
|
+
display: flex;
|
|
61
|
+
justify-content: space-between;
|
|
62
|
+
margin-bottom: 16px;
|
|
63
|
+
font-size: 16px;
|
|
64
|
+
font-weight: bold;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.start-btn {
|
|
68
|
+
padding: 10px 20px;
|
|
69
|
+
font-size: 16px;
|
|
70
|
+
background-color: #42b883;
|
|
71
|
+
color: white;
|
|
72
|
+
border: none;
|
|
73
|
+
border-radius: 6px;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
margin-bottom: 20px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.start-btn:disabled {
|
|
79
|
+
background-color: #a8d5c2;
|
|
80
|
+
cursor: not-allowed;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.grid {
|
|
84
|
+
display: grid;
|
|
85
|
+
grid-template-columns: repeat(3, 1fr);
|
|
86
|
+
gap: 12px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.hole {
|
|
90
|
+
width: 80px;
|
|
91
|
+
height: 80px;
|
|
92
|
+
background-color: #795548;
|
|
93
|
+
border-radius: 50%;
|
|
94
|
+
display: flex;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
align-items: center;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
user-select: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.mole {
|
|
102
|
+
font-size: 40px;
|
|
103
|
+
}
|
|
104
|
+
</style>
|