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

AI tests #131

Merged
merged 64 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
97a324a
First version of an AI school
Dec 23, 2023
7d40f56
#130
Dec 23, 2023
a271a7a
Remove fragment
Dec 23, 2023
de512b9
Remove captures
Dec 23, 2023
ea13d49
Fix Data
Dec 24, 2023
dc9e25c
Introducing Ruby
Dec 25, 2023
9c4c733
Include normalize
Dec 25, 2023
c1186f2
Remove game normalization
Dec 25, 2023
190c6e4
Debugging new Futuro model
Dec 28, 2023
7da9a2b
Update to use performMoveAfterStatistics
Dec 28, 2023
9cb37e9
Should have fixed some bugs
Dec 28, 2023
e27966d
Add tests: Futuro 80% against Ruby
Dec 28, 2023
013996c
Fix linter
Dec 28, 2023
c557623
Include tradebot
Dec 29, 2023
fdd467f
Reformat
Dec 29, 2023
9bb3101
Bugfix
Dec 29, 2023
9e5477f
To test
Dec 29, 2023
6d243c0
Fix linting
Dec 29, 2023
12e6877
Fix some bugs in Agent usage and smells
Dec 29, 2023
831cf43
Hopefully fix some bugs and make improvements
Dec 29, 2023
b41eb35
Try to fix bugs
Dec 29, 2023
5600a90
Fix futuro bug with 8
Dec 29, 2023
7e1ecb7
Fix linting and make some annotations
Dec 29, 2023
586e80b
#133 implement hadOneOrThirteen and previouslyPlayedCards
Dec 30, 2023
4cdfdbd
#133 implement NarrTradedCards
Dec 30, 2023
1687f60
#133 Fix test
Dec 30, 2023
3c881ac
Fix build
Dec 30, 2023
f181bec
#133 Add rest and remove simulationData
Dec 30, 2023
461809e
Update ts
Dec 31, 2023
074fe82
Works in waitinggames: Missing -> createGame
Dec 31, 2023
603dcec
Somewhat working version of game with AI
Dec 31, 2023
5fea47c
Fix linter
Dec 31, 2023
dbfc1df
Speed up
Dec 31, 2023
4b70b93
Add discardbot, implements #137
Dec 31, 2023
de7961c
Improve waitingroom
Dec 31, 2023
0c5d406
Add AI names
Dec 31, 2023
2afadbf
Use bot picture for bots in game and in overview
Jan 1, 2024
917e06b
Improve database checks
Jan 2, 2024
1bf3cfa
Add tests for #137, Added improvements and tests for tradebot #136, F…
Jan 2, 2024
dd9c60f
Fix linting
Jan 2, 2024
0b3a1bc
Include different bots in and simulation
Jan 2, 2024
98ba0ce
Implements bots in game and unify gameorder/teamsorder
Jan 2, 2024
c566e9f
Try to fix tests
Jan 2, 2024
9f26c9f
Fix minor bug
Jan 2, 2024
31a4bca
Remove some logs
Jan 2, 2024
4005348
Fix some flaws
Jan 2, 2024
1ccbe8a
Fix reordering for rematch
Jan 2, 2024
91e5bdc
Readd game and change the settings of futuro
Jan 2, 2024
c9d9ba2
Make Futuro faster
Jan 2, 2024
d93bc0c
Add some options for substitution
Jan 3, 2024
1a80b98
Patch up front end
Jan 3, 2024
96977e4
Add UI to substitution modal
Jan 3, 2024
560fc72
Add locale changes
Jan 3, 2024
a66a921
Fix tests and names
Jan 3, 2024
12e3e57
Remove some logs
Jan 3, 2024
2be9160
Fix tests
Jan 3, 2024
d9e92a5
Remove todo from tests
Jan 3, 2024
373bd3e
Remove some sonarcloud bugs
Jan 4, 2024
2e22b3e
Test without parallel tests
Jan 4, 2024
afd2894
Fix some more flaws
Jan 4, 2024
87b39a4
Add Graph for bot results
Jan 4, 2024
e312d28
Try to fix linting
Jan 4, 2024
a7acffb
Refactor type name and add warning to lint
Jan 4, 2024
100aef4
Apply to database
Jan 5, 2024
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
1 change: 1 addition & 0 deletions client/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
'no-duplicate-imports': 'error',

/* Maybe remove in future */
'no-shadow': ['warn'],
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/ban-ts-comment': 0,
'@typescript-eslint/no-extra-semi': 0,
Expand Down
1 change: 1 addition & 0 deletions client/src/components/GamesTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
:clickable="false"
:nameFirst="false"
:username="player"
:bot="slotProps.data.bots[slotProps.data.players.indexOf(player)] != null"
/>
</div>
</template>
Expand Down
58 changes: 58 additions & 0 deletions client/src/components/PlatformStats/BotStats.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<Chart
ref="botWinshareChart"
type="pie"
:data="botWinshareChartData"
:height="300"
:options="chartOptions"
/>
</template>

<script setup lang="ts">
import type { BotDataset } from '@/../../server/src/sharedTypes/typesPlatformStatistic'

import { ref, watch } from 'vue'
import Chart from 'primevue/chart'
import { getGraphColors } from '@/services/graphColors'
import { i18n } from '@/services/i18n'

const botWinshareChart = ref<any | null>(null)
const props = defineProps<{ data?: BotDataset }>()
watch(
() => props.data,
() => {
updateUserAgentChart()
},
{ deep: true }
)

function updateUserAgentChart() {
if (props.data === undefined) {
return
}

botWinshareChartData.value.labels = [i18n.global.t('Stats.BotWinshare.lost'), i18n.global.t('Stats.BotWinshare.won')]
botWinshareChartData.value.datasets = [
{
data: [props.data.total - props.data.won, props.data.won],
backgroundColor: getGraphColors({ alpha: 0.8 }),
},
]
botWinshareChart.value?.refresh()
}

const botWinshareChartData = ref({
labels: [] as any[],
datasets: [] as any[],
})

const chartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
reverse: true,
},
},
}
</script>
5 changes: 5 additions & 0 deletions client/src/components/PlatformStats/PlatformStats.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
<div class="chart-container">
<UserAgentStats :data="data?.userAgentDataset" />
</div>
<h1>{{ $t('Stats.headerBotWinshare') }}</h1>
<div class="chart-container">
<BotStats :data="data?.botDataset" />
</div>
</template>

<script setup lang="ts">
Expand All @@ -37,6 +41,7 @@ import LocaleStats from './LocaleStats.vue'
import StatsByHour from './StatsByHour.vue'
import StatsByDay from './StatsByDay.vue'
import UserAgentStats from './UserAgentStats.vue'
import BotStats from './BotStats.vue'

import type { PlatformStats } from '@/../../server/src/sharedTypes/typesPlatformStatistic'
import { ref } from 'vue'
Expand Down
11 changes: 10 additions & 1 deletion client/src/components/PlayerWithPicture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@
{{ username }}
</div>
<ProfilePicture
v-if="pictureVisible === true"
v-if="pictureVisible === true && !bot"
:username="username !== '' ? username : $t('Chat.deletedPlayer')"
:showCrown="showCrown"
:online="online"
class="autocompleteImage"
/>
<div
v-if="pictureVisible === true && bot"
class="autocompleteImage"
style="line-height: 30px; padding-left: 4px"
>
🤖
</div>
</div>
</template>

Expand All @@ -34,6 +41,7 @@ const props = withDefaults(
hideIfEmpty?: boolean
showCrown?: boolean
online?: boolean
bot?: boolean
}>(),
{
nameFirst: true,
Expand All @@ -43,6 +51,7 @@ const props = withDefaults(
hideIfEmpty: true,
showCrown: true,
online: undefined,
bot: false,
}
)

Expand Down
7 changes: 4 additions & 3 deletions client/src/components/RunningGamesWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
<template #body="slotProps">
<div class="playerContainer">
<PlayerWithPicture
v-for="player in slotProps.data.teams[teamIndex]?.filter((p: string | null) => p != null)"
:key="'Team-' + teamIndex + '-Player-' + player"
v-for="(_, playerIndex) in slotProps.data.teams[teamIndex]"
:key="`Team-${teamIndex}-Player-${playerIndex}`"
class="player"
:clickable="false"
:nameFirst="false"
:username="player"
:username="slotProps.data.teams[teamIndex][playerIndex] ?? ''"
:bot="slotProps.data.bots[teamIndex][playerIndex] ?? false"
/>
</div>
</template>
Expand Down
90 changes: 69 additions & 21 deletions client/src/components/WaitingGame.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,64 @@
class="playerSlot"
>
<div
v-if="game.players[playerIndex(Number(teamIndex), index)] != null"
v-if="game.players[playerIndex(Number(teamIndex), index)] != null || game.bots[playerIndex(Number(teamIndex), index)] != null"
class="playerContainer"
>
<div
v-if="active && game.players.slice(0, game.nPlayers).every((p) => p != null)"
v-if="
active &&
game.players
.slice(0, game.nPlayers)
.filter((_, i) => game.bots[i] == null)
.every((p) => p != null)
"
class="readyIcon"
>
<i
v-if="game.ready[playerIndex(Number(teamIndex), index)]"
v-if="
(game.players[playerIndex(Number(teamIndex), index)] != null && game.ready[playerIndex(Number(teamIndex), index)]) ||
game.bots[playerIndex(Number(teamIndex), index)] != null
"
class="pi pi-check"
style="color: green"
/>
<i
v-if="!game.ready[playerIndex(Number(teamIndex), index)]"
v-if="game.players[playerIndex(Number(teamIndex), index)] != null && !game.ready[playerIndex(Number(teamIndex), index)]"
class="pi pi-spin pi-spinner"
style="color: red"
/>
</div>
<BallsImage
v-if="activeAndNotNull(playerIndex(Number(teamIndex), index))"
:class="['playerBall', game.players[playerIndex(Number(teamIndex), index)] === username ? 'clickable' : '']"
:class="[
'playerBall',
game.players[playerIndex(Number(teamIndex), index)] === username || (game.bots[playerIndex(Number(teamIndex), index)] != null && game.admin === username)
? 'clickable'
: '',
]"
:color="game.balls[playerIndex(Number(teamIndex), index)]"
@click="toggle($event, playerIndex(Number(teamIndex), index))"
/>
<PlayerWithPicture
:username="game.players[playerIndex(Number(teamIndex), index)]"
:username="game.players[playerIndex(Number(teamIndex), index)] ?? $t('Waiting.bot')"
:hideIfEmpty="true"
:nameFirst="false"
:clickable="active"
:bot="game.bots[playerIndex(Number(teamIndex), index)] != null"
/>
<div
v-if="game.adminID === game.playerIDs[playerIndex(Number(teamIndex), index)]"
style="margin-left: 5px"
>
{{ `(${$t('Waiting.adminBadge')})` }}
</div>
</div>
<div v-else>
<Button
v-if="active && game.admin === username"
severity="secondary"
:label="`+ ${$t('Waiting.bot')}`"
@click="() => emit('add-bot', { gameID: game.id, botID: 3, playerIndex: playerIndex(Number(teamIndex), index) })"
/>
</div>
<div class="playerControls">
Expand All @@ -102,20 +131,20 @@
icon="pi pi-angle-up"
class="p-button-rounded p-button-secondary p-button-sm p-button-text buttonUpDown"
:disabled="playerIndex(Number(teamIndex), index) <= 0"
@click="movePlayer(game.id, game.players[playerIndex(Number(teamIndex), index)], -1)"
@click="movePlayerOrBot(game.id, playerIndex(Number(teamIndex), index), -1)"
/>
<Button
icon="pi pi-angle-down"
class="p-button-rounded p-button-secondary p-button-sm p-button-text buttonUpDown"
:disabled="playerIndex(Number(teamIndex), index) >= game.nPlayers - 1"
@click="movePlayer(game.id, game.players[playerIndex(Number(teamIndex), index)], 1)"
@click="movePlayerOrBot(game.id, playerIndex(Number(teamIndex), index), 1)"
/>
</div>
<Button
v-if="activeAndSelfOrAdmin(playerIndex(Number(teamIndex), index))"
icon="pi pi-times"
class="p-button-rounded p-button-danger p-button-text"
@click="removePlayer(game.players[playerIndex(Number(teamIndex), index)])"
@click="removePlayerOrBot(playerIndex(Number(teamIndex), index))"
/>
</div>
</div>
Expand Down Expand Up @@ -144,7 +173,7 @@
label="Bereit zum Starten?"
icon="pi pi-caret-right"
class="p-button-success"
:disabled="game.players.slice(0, game.nPlayers).some((p) => p === null) || game.ready.find((_, index) => game.players[index] === username)"
:disabled="game.players.slice(0, game.nPlayers).some((p, i) => p === null && game.bots[i] == null) || game.ready.find((_, index) => game.players[index] === username)"
@click="setPlayerReady()"
/>
</div>
Expand All @@ -171,10 +200,13 @@
const props = withDefaults(defineProps<{ game: WaitingGame; active?: boolean }>(), { active: false })

const emit = defineEmits<{
'add-bot': [data: { gameID: number; botID: number; playerIndex: number }]
'move-player': [data: { gameID: number; username: string; steps: number }]
'move-bot': [data: { gameID: number; playerIndex: number; steps: number }]
'remove-player': [username: string]
'remove-bot': [data: { gameID: number; playerIndex: number }]
'ready-player': [gameID: number]
'color-player': [username: string, gameID: number, color: string]
'color-player': [username: string, gameID: number, color: string, botIndex: number | null]
}>()

const opRef = ref<OverlayPanel | null>(null)
Expand All @@ -188,42 +220,58 @@
}

const activeAndNotNull = (index: number) => {
return props.game.players[index] != null && props.active
return (props.game.players[index] != null || props.game.bots[index] != null) && props.active
}

const activeAndSelf = (index: number) => {
return props.game.players[index] != null && props.active && props.game.players[index] === username.value
}

const activeAndSelfOrAdmin = (index: number) => {
return props.game.players[index] != null && props.active && (props.game.players[index] === username.value || props.game.admin === username.value)
return (
props.active &&
((props.game.players[index] != null && (props.game.players[index] === username.value || props.game.admin === username.value)) ||
(props.game.bots[index] != null && props.game.admin === username.value))
)
}

const movePlayer = (gameID: number, username: string, steps: number) => {
emit('move-player', {
gameID: gameID,
username: username,
steps: steps,
})
const movePlayerOrBot = (gameID: number, index: number, steps: number) => {
if (props.game.players[index] != null) {
emit('move-player', {
gameID,
username: props.game.players[index],
steps: steps,
})
}
if (props.game.bots[index] != null) {
emit('move-bot', { gameID, playerIndex: index, steps: steps })
}
}

const removePlayer = (username: string) => {

Check warning on line 251 in client/src/components/WaitingGame.vue

View workflow job for this annotation

GitHub Actions / build

'username' is already declared in the upper scope on line 196 column 10
emit('remove-player', username)
}

const removePlayerOrBot = (index: number) => {
if (props.game.players[index] != null) emit('remove-player', props.game.players[index])
if (props.game.bots[index] != null) emit('remove-bot', { gameID: props.game.id, playerIndex: index })
}

const setPlayerReady = () => {
emit('ready-player', props.game.id)
}

let playerIndexForColorChange: number | null = null
const toggle = (event: Event, index: number) => {
if (activeAndSelf(index)) {
playerIndexForColorChange = index
if (activeAndSelf(index) || (props.game.bots[index] != null && props.game.admin === username.value)) {
opRef.value?.toggle(event)
}
}

const switchColor = (color: string) => {
opRef.value?.hide()
emit('color-player', username.value ?? '', props.game.id, color)
emit('color-player', username.value ?? '', props.game.id, color, playerIndexForColorChange)
}
</script>

Expand Down
22 changes: 19 additions & 3 deletions client/src/components/WaitingOverview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,11 @@
class="activeGame"
:game="waitingStore.ownGame"
:active="true"
@add-bot="addBot"
@move-player="movePlayer"
@move-bot="moveBot"
@remove-player="removePlayer"
@remove-bot="removeBot"
@ready-player="setPlayerReady"
@color-player="setPlayerColor"
/>
Expand Down Expand Up @@ -271,28 +274,41 @@ function joinGame(game: WaitingGameType) {
socket.emitWithAck(5000, 'waiting:joinGame', game.id)
}

function addBot(data: { gameID: number; botID: number; playerIndex: number }) {
socket.emitWithAck(5000, 'waiting:addBot', data.gameID, data.botID, data.playerIndex)
}

function movePlayer(data: { gameID: number; username: string; steps: number }) {
socket.emitWithAck(5000, 'waiting:movePlayer', data)
}

function moveBot(data: { gameID: number; playerIndex: number; steps: number }) {
socket.emitWithAck(5000, 'waiting:moveBot', data)
}

function removePlayer(usernameToRemove: string) {
const confirmText = i18n.global.t(usernameToRemove === username.value ? 'Waiting.removePlayerConfirmSelf' : 'Waiting.removePlayerConfirmOther')
if (confirm(confirmText)) {
socket.emitWithAck(5000, 'waiting:removePlayer', usernameToRemove)
}
}

function removeBot(data: { gameID: number; playerIndex: number }) {
socket.emitWithAck(5000, 'waiting:removeBot', data.gameID, data.playerIndex)
}

function setPlayerReady(gameID: number) {
socket.emitWithAck(5000, 'waiting:readyPlayer', {
gameID: gameID,
})
}

function setPlayerColor(usernameToChange: string, gameID: number, color: string) {
function setPlayerColor(usernameToChange: string, gameID: number, color: string, botIndex: number | null) {
socket.emitWithAck(5000, 'waiting:switchColor', {
gameID: gameID,
gameID,
username: usernameToChange,
color: color,
color,
botIndex,
})
}
</script>
Expand Down
Loading
Loading