diff --git a/prisma/migrations/20230913142372_sqloptimization/migration.sql b/prisma/migrations/20230913142372_sqloptimization/migration.sql
new file mode 100644
index 0000000..869fe88
--- /dev/null
+++ b/prisma/migrations/20230913142372_sqloptimization/migration.sql
@@ -0,0 +1,21 @@
+-- AlterTable
+alter table banned_user
+ add constraint banned_user_user_id_fk
+ foreign key (user_id) references user (id)
+ on delete cascade;
+
+alter table game_sessions
+ modify user_id int not null;
+
+alter table game_sessions
+ add constraint game_sessions_user_id_fk
+ foreign key (user_id) references user (id)
+ on delete cascade;
+
+alter table riitag.game_sessions
+ modify game_id int unsigned not null;
+
+alter table game_sessions
+ add constraint game_sessions_game_game_pk_fk
+ foreign key (game_id) references game (game_pk);
+
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index cab8e37..cb4f7e8 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -23,14 +23,15 @@ model account {
}
model game {
- game_pk Int @id @default(autoincrement()) @db.UnsignedInt
- game_id String @db.VarChar(50)
- console String @db.VarChar(9)
- name String? @db.VarChar(255)
- playcount Int @default(1) @db.UnsignedInt
- first_played DateTime @default(now())
- last_played DateTime @default(now()) @updatedAt
- playlog playlog[]
+ game_pk Int @id @default(autoincrement()) @db.UnsignedInt
+ game_id String @db.VarChar(50)
+ console String @db.VarChar(9)
+ name String? @db.VarChar(255)
+ playcount Int @default(1) @db.UnsignedInt
+ first_played DateTime @default(now())
+ last_played DateTime @default(now()) @updatedAt
+ game_sessions game_sessions[]
+ playlog playlog[]
@@unique([game_id, console], map: "game_id_console")
@@index([console], map: "console")
@@ -67,35 +68,37 @@ model following {
}
model user {
- id Int @id @default(autoincrement())
- username String @unique @db.VarChar(50)
- role String @default("user") @db.VarChar(25)
- display_name String? @db.VarChar(255)
- image String? @db.VarChar(255)
- randkey String? @unique @db.VarChar(200)
- coins Int @default(0) @db.UnsignedInt
- cover_region String @default("EN") @db.VarChar(6)
- cover_type String @default("cover3D") @db.VarChar(10)
- comment String? @db.VarChar(50)
- overlay String @default("overlay1") @db.VarChar(20)
- background String @default("riiconnect241.png") @db.VarChar(120)
- flag String @default("rc24") @db.VarChar(20)
- coin String @default("mario") @db.VarChar(20)
- font String @default("default") @db.VarChar(50)
- show_avatar Boolean @default(false)
- show_mii Boolean @default(false)
- mii_type String @default("guest") @db.VarChar(10)
- mii_data String? @db.VarChar(8192)
- cmoc_entry_no String? @db.VarChar(12)
- created_at DateTime @default(now())
- updated_at DateTime @default(now()) @updatedAt
- badge String? @db.VarChar(50)
- isBanned Boolean @default(false)
- isPublic Boolean @default(true)
+ id Int @id @default(autoincrement())
+ username String @unique @db.VarChar(50)
+ role String @default("user") @db.VarChar(25)
+ display_name String? @db.VarChar(255)
+ image String? @db.VarChar(255)
+ randkey String? @unique @db.VarChar(200)
+ coins Int @default(0) @db.UnsignedInt
+ cover_region String @default("EN") @db.VarChar(6)
+ cover_type String @default("cover3D") @db.VarChar(10)
+ comment String? @db.VarChar(50)
+ overlay String @default("overlay1") @db.VarChar(20)
+ background String @default("riiconnect241.png") @db.VarChar(120)
+ flag String @default("rc24") @db.VarChar(20)
+ coin String @default("mario") @db.VarChar(20)
+ font String @default("default") @db.VarChar(50)
+ show_avatar Boolean @default(false)
+ show_mii Boolean @default(false)
+ mii_type String @default("guest") @db.VarChar(10)
+ mii_data String? @db.VarChar(8192)
+ cmoc_entry_no String? @db.VarChar(12)
+ created_at DateTime @default(now())
+ updated_at DateTime @default(now()) @updatedAt
+ badge String? @db.VarChar(50)
+ isBanned Boolean @default(false)
+ isPublic Boolean @default(true)
publicOverride Boolean?
- language String @default("en") @db.VarChar(11)
+ language String @default("en") @db.VarChar(11)
accounts account[]
+ banned_user banned_user?
following following[]
+ game_sessions game_sessions[]
playlog playlog[]
}
@@ -109,9 +112,14 @@ model events {
model game_sessions {
id Int @id @unique(map: "game_sessions_id_uindex") @default(autoincrement())
- user_id String @db.VarChar(64)
- game_id String @db.VarChar(50)
+ user_id Int
+ game_id Int @db.UnsignedInt
start_time DateTime @default(now()) @db.DateTime(0)
+ game game @relation(fields: [game_id], references: [game_pk], onUpdate: Restrict, map: "game_sessions_game_game_pk_fk")
+ user user @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: Restrict, map: "game_sessions_user_id_fk")
+
+ @@index([user_id], map: "game_sessions_user_id_fk")
+ @@index([game_id], map: "game_sessions_game_game_pk_fk")
}
model banned_user {
@@ -120,6 +128,7 @@ model banned_user {
ip_address String @db.VarChar(64)
reason String @db.VarChar(255)
action_time DateTime @default(now()) @db.DateTime(0)
+ user user @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: Restrict, map: "banned_user_user_id_fk")
}
model moderation_log {
diff --git a/src/components/user/PlayLog.jsx b/src/components/user/PlayLog.jsx
index 9cd46ba..c7f23bc 100644
--- a/src/components/user/PlayLog.jsx
+++ b/src/components/user/PlayLog.jsx
@@ -11,6 +11,10 @@ function PlayLog ({ playlog, current }) {
return duration.humanize()
}
+ function isPlaying (gameId) {
+ return current && current.some((session) => session.game.game_id === gameId)
+ }
+
const [hydrated, setHydrated] = React.useState(false)
React.useEffect(() => {
// This forces a rerender, so the date is rendered
@@ -43,7 +47,7 @@ function PlayLog ({ playlog, current }) {
{log.game.name === null ? log.game.game_id : log.game.name}
{log.play_time > 0 ? `${getTimeStamp(log.play_time)}` : 'Not Tracked'}
{log.play_count} times
- {current && current.game_id === log.game.game_id ? 'Now' : moment(log.played_on).from()}
+ {current.length > 0 && isPlaying(log.game.game_id) ? 'Now' : moment(log.played_on).from()}
))}
diff --git a/src/components/user/PlayingStatus.jsx b/src/components/user/PlayingStatus.jsx
index 8d3b3cf..b7f9bef 100644
--- a/src/components/user/PlayingStatus.jsx
+++ b/src/components/user/PlayingStatus.jsx
@@ -3,23 +3,25 @@ import PropTypes from 'prop-types'
import { Card } from 'react-bootstrap'
import moment from 'moment/moment'
-function PlayingStatus ({ session, game }) {
+function PlayingStatus ({ session, games: sessions }) {
return (
-
- Now Playing
-
-
- Game: {game.name}
- Started Playing: {moment(session.start_time).from()}
-
-
-
+ sessions.map((session, index) => (
+
+ Now Playing
+
+
+ Game: {session.game.name}
+ Started Playing: {moment(session.game.start_time).from()}
+
+
+
+ ))
)
}
PlayingStatus.propTypes = {
session: PropTypes.object.isRequired,
- game: PropTypes.object.isRequired
+ game: PropTypes.array.isRequired
}
export default PlayingStatus
diff --git a/src/pages/edit.jsx b/src/pages/edit.jsx
index 906dbc6..3ae0278 100644
--- a/src/pages/edit.jsx
+++ b/src/pages/edit.jsx
@@ -23,20 +23,32 @@ import LanguageContext from '@/components/shared/LanguageContext'
import AppNavbar from '@/components/shared/AppNavbar'
export const getServerSideProps = withSession(async ({ req }) => {
- const username = req.session?.username
+ // get the current user session
+ const sessionAccount = req.session?.username
- const loggedInUser = username != null
+ const session = sessionAccount != null
? await prisma.user.findUnique({
where: {
- username
+ username: sessionAccount
},
select: {
- language: true
+ language: true,
+ display_name: true,
+ cover_region: true,
+ cover_type: true,
+ comment: true,
+ overlay: true,
+ background: true,
+ flag: true,
+ coin: true,
+ font: true,
+ show_avatar: true,
+ show_mii: true
}
})
- : { role: 'guest' }
+ : null
- if (!username) {
+ if (!sessionAccount) {
return {
redirect: {
destination: '/',
@@ -45,26 +57,7 @@ export const getServerSideProps = withSession(async ({ req }) => {
}
}
- const tagInfo = await prisma.user.findUnique({
- where: {
- username
- },
- select: {
- display_name: true,
- cover_region: true,
- cover_type: true,
- comment: true,
- overlay: true,
- background: true,
- flag: true,
- coin: true,
- font: true,
- show_avatar: true,
- show_mii: true
- }
- })
-
- return { props: { tagInfo, language: loggedInUser?.language || 'en' } }
+ return { props: { tagInfo: session, language: session?.language || 'en' } }
})
function EditPage ({ tagInfo, language }) {
diff --git a/src/pages/game-leaderboard.jsx b/src/pages/game-leaderboard.jsx
index cca3cb0..505069d 100644
--- a/src/pages/game-leaderboard.jsx
+++ b/src/pages/game-leaderboard.jsx
@@ -12,14 +12,14 @@ const limit = TOTAL_GAMES_ON_LEADERBOARD
export async function getServerSideProps ({ query }) {
let { page, search } = query
- page = page === undefined ? 1 : Number.parseInt(page, 10)
- if (Number.isNaN(page) || page <= 0) {
- page = 1
- }
+
+ page = Number.parseInt(page, 10) || 1
+
+ if (Number.isNaN(page) || page <= 0) page = 1
// Add logic for the search handler
- let leaderboard
- let totalGames
+ let leaderboard, totalGames
+
if (search) {
// Call your search function here and pass the search parameter
[totalGames, leaderboard] = await getGameLeaderboardSearch(page, limit, search)
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 687f73c..589259b 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -17,36 +17,56 @@ import LocalizedString from '@/components/shared/LocalizedString'
import AppNavbar from '@/components/shared/AppNavbar'
export const getServerSideProps = withSession(async ({ req, query }) => {
- const userCount = await prisma.user.count()
- const playCountResult = await prisma.$queryRaw`
- SELECT SUM(coins)
- FROM user
- `
-
- const loggedInUsername = req.session?.username
- const loggedInUser = await prisma.user.findFirst({
+ // Get user session and their language
+ const session = req.session?.username
+
+ // count users and total coins and then get 5 random users
+ const totalCounts = await prisma.user.aggregate({
+ _sum: {
+ coins: true
+ },
+ _count: {
+ username: true
+ }
+ })
+
+ const skip = Math.floor(Math.random() * totalCounts._count.username)
+
+ // get random users with 5 or more coins and is public.
+ const randomUsers = await prisma.user.findMany({
+ select: {
+ username: true,
+ display_name: true,
+ updated_at: true
+ },
where: {
- username: loggedInUsername
+ coins: {
+ gt: 10
+ },
+ isPublic: true,
+ publicOverride: null
+ },
+ orderBy: {
+ updated_at: 'desc'
+ },
+ take: 5,
+ skip
+ })
+
+ const sessionUser = await prisma.user.findUnique({
+ where: {
+ username: session
},
select: {
language: true
}
})
- const playCount = Number(playCountResult[0]['SUM(coins)'])
- const randomUsers = await prisma.$queryRaw`
- SELECT user.username, user.display_name, user.updated_at
- FROM user
- WHERE user.coins > 10 AND user.isPublic = 1 AND user.publicOverride IS NULL
- ORDER BY RAND()
- LIMIT 5
- `
-
return {
props: {
- userCount,
- playCount,
- language: loggedInUser.language,
+ userCount: totalCounts._count.username,
+ playCount: totalCounts._sum.coins,
+ language: sessionUser?.language || 'en',
randomUsers: JSON.parse(safeJsonStringify(randomUsers))
}
}
@@ -54,7 +74,6 @@ export const getServerSideProps = withSession(async ({ req, query }) => {
function IndexPage ({ userCount, playCount, language, randomUsers }) {
const router = useRouter()
-
const { user, isLoading } = useInfo()
useEffect(() => {
@@ -68,105 +87,105 @@ function IndexPage ({ userCount, playCount, language, randomUsers }) {
return (
-
-
-
-
-
-
-
-
-
- {
- isLoading === false
- ? (
-
-
- {user?.username === undefined && (
- <>
- {' '}
- >
- )}
-
-
+
+
+
+
+
+
+
+
+
+ {
+ isLoading === false
+ ? (
+
+
+ {user?.username === undefined && (
+ <>
+ {' '}
+ >
+ )}
+
+
+
+
+ )
+ : null
+ }
+
+ {
+ isLoading === false && user?.username === undefined && (
+
+
+
+ If an account does not exist, it will be created. You agree to our{' '}
+ Privacy Policy and our{' '}
+ Terms of Service.
+
- )
- : null
- }
+ )
+ }
- {
- isLoading === false && user?.username === undefined && (
-
-
-
- If an account does not exist, it will be created. You agree to our{' '}
- Privacy Policy and our{' '}
- Terms of Service.
-
-
-
- )
- }
+ {
+ userCount !== 0 && (
+
+
+
+ {' '}
+
+
+
+ )
+ }
- {
- userCount !== 0 && (
-
-
-
- {' '}
-
-
-
- )
- }
+ {
+ randomUsers.length > 0 && (
+
+
+
+
+
+ )
+ }
- {
- randomUsers.length > 0 && (
-
+
+
+
+
+
-
+ Wii
+
+ Dolphin Discord RPC
+ USB Loaders
+
+ Configurable USB Loader
+ USB Loader GX
+ WiiFlow
+
+
-
- )
- }
-
-
-
-
-
-
-
- Wii
-
- Dolphin Discord RPC
- USB Loaders
+
+ Wii U
- Configurable USB Loader
- USB Loader GX
- WiiFlow
+ Aroma Plugin
+ Cemu Discord RPC
-
-
-
- Wii U
-
- Aroma Plugin
- Cemu Discord RPC
-
-
+
+
-
-
+
)
}
diff --git a/src/pages/user/[username]/index.jsx b/src/pages/user/[username]/index.jsx
index 0fa56b7..4899d48 100644
--- a/src/pages/user/[username]/index.jsx
+++ b/src/pages/user/[username]/index.jsx
@@ -17,8 +17,10 @@ import AppNavbar from '@/components/shared/AppNavbar'
export const getServerSideProps = withSession(async ({ req, query }) => {
const { username } = query
- const loggedInUsername = req.session?.username
+ // Get the logged in user. This can be null.
+ const session = req.session?.username
+ // get user and ban reason
const user = await prisma.user.findUnique({
where: {
username: username.toString()
@@ -29,7 +31,6 @@ export const getServerSideProps = withSession(async ({ req, query }) => {
image: true,
display_name: true,
created_at: true,
- updated_at: true,
overlay: true,
background: true,
coin: true,
@@ -40,15 +41,32 @@ export const getServerSideProps = withSession(async ({ req, query }) => {
role: true,
isBanned: true,
isPublic: true,
- publicOverride: true
+ publicOverride: true,
+ banned_user: true,
+ playlog: {
+ select: {
+ game: true,
+ play_time: true,
+ play_count: true,
+ played_on: true
+ },
+ orderBy: {
+ played_on: 'desc'
+ }
+ },
+ game_sessions: {
+ select: {
+ game: true,
+ start_time: true
+ }
+ }
}
})
- const banReason = await prisma.banned_user.findFirst({
- where: {
- user_id: user.id
- }
- })
+ // If there's no user, don't continue from here.
+ if (!user) {
+ return { notFound: true }
+ }
const event = await prisma.events.findFirst({
where: {
@@ -61,45 +79,10 @@ export const getServerSideProps = withSession(async ({ req, query }) => {
}
})
- const playlog = await prisma.playlog.findMany({
- where: {
- user: {
- username: username.toString()
- }
- },
- select: {
- play_time: true,
- play_count: true,
- played_on: true,
- game: {
- select: {
- game_id: true,
- name: true
- }
- }
- },
- orderBy: {
- played_on: 'desc'
- },
- take: 10
- })
-
- const session = await prisma.game_sessions.findFirst({
- where: {
- user_id: user.username
- }
- })
-
- const sessionGame = await prisma.game.findFirst({
- where: {
- game_id: session?.game_id || '0'
- }
- })
-
- const loggedInUser = loggedInUsername != null
+ const loggedInUser = session != null
? await prisma.user.findUnique({
where: {
- username: loggedInUsername
+ username: session
},
select: {
role: true,
@@ -108,26 +91,21 @@ export const getServerSideProps = withSession(async ({ req, query }) => {
})
: { role: 'guest' }
- if (!user) {
- return { notFound: true }
- }
-
return {
props: {
user: JSON.parse(safeJsonStringify(user)),
- isLoggedIn: user.username === loggedInUsername,
+ isLoggedIn: user.username === session,
loggedInUser,
language: loggedInUser?.language || 'en',
- banReason: JSON.parse(safeJsonStringify(banReason)),
+ banReason: JSON.parse(safeJsonStringify(user.banned_user)),
event: JSON.parse(safeJsonStringify(event)),
- playlog: JSON.parse(safeJsonStringify(playlog)),
- session: JSON.parse(safeJsonStringify(session)),
- game: JSON.parse(safeJsonStringify(sessionGame))
+ playlog: JSON.parse(safeJsonStringify(user.playlog)),
+ session: JSON.parse(safeJsonStringify(user.game_sessions))
}
}
})
-function ProfilePage ({ user, isLoggedIn, banReason, loggedInUser, event, playlog, language, session, game }) {
+function ProfilePage ({ user, isLoggedIn, banReason, loggedInUser, event, playlog, language, session }) {
return (
@@ -166,13 +144,13 @@ function ProfilePage ({ user, isLoggedIn, banReason, loggedInUser, event, playlo
/>
-
+
: ''}
{event && An event is currently ongoing: {event.name}. Until {event.date}, you will recieve {event.bonus + 1}x more coins. }
- {session && }
+ {session && }
{isLoggedIn && }